Current section
Files
Jump to
Current section
Files
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.4"
rpi2= :"nerves@192.168.1.5"
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)