Sensor-Alarm Example
This example demonstrates a fundamental event-driven interaction between a Sensor and an Alarm. The Sensor reactor is designed to periodically monitor for a specific condition. If the condition is met, it triggers an event by sending a message to the Alarm reactor, which then takes appropriate action.
The Data Models
The simulation is defined by two simple data models, one for the sensor and one for the alarm, which specify their respective states.
Sensor Data Model (sensor.yml)
The sensor's data model contains a single boolean node called detected. This node represents whether the sensor has detected the event it is monitoring. It is initialized to False.
name: "sensor"
description: "Sensor"
root:
!!FolderNode
name: "root"
children:
- !!BooleanVariableNode
name: "detected"
initial_value: False
Alarm Data Model (alarm.yml)
The alarm's data model includes a boolean node called ringing, which is also initialized to False. This node represents the state of the alarm. The Alarm reactor will set this to True when it receives a signal from the sensor.
name: "alarm"
description: "Alarm"
root:
!!FolderNode
name: "root"
children:
- !!BooleanVariableNode
name: "ringing"
initial_value: False
The Sensor Reactor
The Sensor reactor simulates the behavior of a real-world sensor. It uses a timer to periodically perform a check. In this simulation, the check involves generating a random number. If this number exceeds a predefined threshold, the sensor considers the event "detected," sets its detected state to True, and sends a message to the Alarm reactor to activate it.
reactor Sensor extends FrostMachine {
state detected
reaction(startup) {=
self.detected = self.data_model.get_node("root/detected")
=}
timer check_timer(1000 msec, 3000 msec)
reaction(check_timer) -> channel_out {=
// Simulate random detection
new_value = random.random()
self.detected.value = new_value > 0.9
if self.detected.value:
message = FrostMessage(
sender=self.name,
target="alarm",
// ... message header ...
payload=VariablePayload(
node="root/ringing",
value=self.detected.value,
),
)
self._set_channel_out_port(message, channel_out)
=}
}
The Alarm Reactor
The Alarm reactor represents the alarm device itself. It has a ringing state that is initially False. The Alarm reactor also has a timer that periodically checks the value of its ringing state. If it finds that ringing is True, it logs a "RINGING!" message to the console and requests the simulation to stop. This shows how a component can react to an event triggered by another component and take a decisive action.