Packages

A library for distributed reactive programming with flexible consistency guarantees drawing from QUARP and Rx.. Features the familiar behaviours and event streams in the spirit of FRP.

Current section

Files

Jump to
bquarp lib examples bquarp_example.exs
Raw

lib/examples/bquarp_example.exs

alias Observables.{Obs, Subject}
alias Reactivity.Registry
alias Reactivity.DSL.{Signal, SignalObs, Behaviour, EventStream}
import Deployment
require Logger
#####################
# DEPLOYMENT SCRIPT #
#####################
# In this example we deploy a simple distributed reactive application
# to a series of Raspberry Pi nodes.
# Specifically, it is the example reactive program from the QUARP paper.
# Mock data simulates sensor measurements.
# Activate the program as follows:
# - Start the QUARP middleware and spawn an iex shell
# iex --name bob@pc -S mix
# (If not automatically connected with the rpis, connect manually:
# Network.Connector.manual_connect_and_subscribe([rpi1, rpi2, rpi3]))
# - Load this script:
# import_file("path/to/this_script.exs")
# The fully qualified names of the rpi nodes:
rpi1= :"nerves@192.168.1.5"
rpi2= :"nerves@192.168.1.4"
rpi3= :"nerves@192.168.1.3"
# Create a mock temperature sensor
temperature1_app = fn ->
t1_handle = Subject.create
t1_handle
|> EvenStream.from_plain_obs({:t, 0})
|> EvenStream.scan(fn(x,y) -> x + y end)
|> EvenStream.hold
|> Signal.register(:t1)
Subject.next(t1_handle, 20)
Obs.repeat(fn -> Enum.random(-1..1) end)
|> Obs.each(fn v -> Subject.next(t1_handle, v) end)
:ok
end
# Create a mock temperature sensor
temperature1_app = fn ->
t2_handle = Subject.create
t2_handle
|> EvenStream.from_plain_obs({:t, 0})
|> EvenStream.scan(fn(x,y) -> x + y end)
|> EvenStream.hold
|> Signal.register(:t2)
Subject.next(t2_handle, 20)
Obs.repeat(fn -> Enum.random(-1..1) end)
|> Obs.each(fn v -> Subject.next(t1_handle, v) end)
:ok
end
# Calculate the mean temperature
mean_temperature_app = fn ->
t1 = Signal.signal(:t1)
t2 = Signal.signal(:t2)
tm = Signal.liftapp([t1, t2], fn(x,y) -> (x+y)/2 end)
|> Signal.register(:tm)
:ok
end
# Control an air conditioning unit
airco_app = fn ->
tm =
Signal.signal(:tm)
|> Behaviour.changes
commands =
tm
|> EventStream.filter(fn t -> t > 25 or t < 20 end)
|> EventStream.liftapp(fn t -> if t > 25, do: :on, else: :off end)
|> EventStrema.novel
|> EvenStream.each(
fn c ->
case c do
:off -> # turn off the airco
:on -> #turn on the airco
end
end)
:ok
end
deploy(rpi1, temperature1_app)
deploy(rpi2, temperature2_app)
deploy(rpi2, mean_temperature_app)
deploy(rpi3, airco_app)