Defines the behaviour and metadata macro for Sensors in the Jido system.
A Sensor is a pure behaviour that transforms external events into Signals.
Sensors are stateless modules that define how to initialize, handle events,
and emit signals. Runtime execution is handled by Jido.Sensor.Runtime.
Usage
To define a new Sensor, use the Jido.Sensor behaviour in your module:
defmodule MySensor do
use Jido.Sensor,
name: "my_sensor",
description: "Monitors a specific metric",
schema: Zoi.object(%{
metric: Zoi.string()
})
@impl true
def init(config, _context) do
{:ok, %{metric: config.metric, last_value: nil}}
end
@impl true
def handle_event({:metric_update, value}, state) do
signal = Jido.Signal.new!(%{
source: "my_sensor",
type: "metric.updated",
data: %{value: value, previous: state.last_value}
})
{:ok, %{state | last_value: value}, [{:emit, signal}]}
end
endCallbacks
Implementing modules must define:
init/2: Initialize sensor state from config and contexthandle_event/2: Process incoming events and emit signals
Optional callbacks:
terminate/2: Called when the sensor is shutting down (default::ok)
Directives
Callbacks can return directives to request runtime actions:
{:schedule, interval}- Schedule next poll after interval ms{:schedule, interval, payload}- Schedule with custom payload{:emit, signal}- Emit a signal immediately
Sensor modules that need external subscriptions or connections should establish
them in init/2 and clean them up in terminate/2.
Summary
Callbacks
Handle an incoming event and produce directives.
Initialize the sensor state.
Called when the sensor is shutting down.
Types
@type sensor_directive() :: {:schedule, pos_integer()} | {:schedule, pos_integer(), term()} | {:emit, Jido.Signal.t()}
Callbacks
@callback handle_event(event :: term(), state :: term()) :: {:ok, state :: term()} | {:ok, state :: term(), directives :: [sensor_directive()]} | {:error, reason :: term()}
Handle an incoming event and produce directives.
Called when the sensor receives an event from its connected source(s). Should return directives describing what actions to take.
Parameters
event- The incoming event (format depends on the source)state- Current sensor state
Returns
{:ok, state}- Updated state with no directives{:ok, state, directives}- Updated state with directives to execute{:error, reason}- Event handling failed
Directives
{:emit, signal}- Emit a signal to the connected agent{:schedule, interval_ms}- Schedule a:tickevent after interval{:schedule, interval_ms, event}- Schedule a custom event after interval
Example
def handle_event(:tick, state) do
signal = Jido.Signal.new!(%{source: "/sensor/example", type: "example.tick"})
{:ok, state, [{:emit, signal}, {:schedule, 1000}]}
end
@callback init(config :: map(), context :: map()) :: {:ok, state :: term()} | {:ok, state :: term(), directives :: [sensor_directive()]} | {:error, reason :: term()}
Initialize the sensor state.
Called when the sensor is started. Receives the validated configuration and a context map containing runtime information.
Parameters
config- Validated configuration map (parsed against the sensor's schema)context- Runtime context (e.g., sensor id, parent process info)
Returns
{:ok, state}- Initial state for the sensor{:ok, state, directives}- Initial state with startup directives{:error, reason}- Initialization failed
Called when the sensor is shutting down.
Use this to clean up any resources. The default implementation returns :ok.
Parameters
reason- The shutdown reasonstate- Current sensor state
Returns
:ok- Shutdown complete