A vital component of MudPi is the underlying event system. This system is used to allow all internal components to communicate. MudPi offers support for redis and MQTT to utilize their Pub/Sub capabilities since they also work across multiple languages (Python, PHP, and Javascript in our case).
MudPi will publish events for all of its internal operations. Events are the main way MudPi systems interact with one another. Examples of when events are emitted include state update, user input, time changes etc. Each event will return a JSON payload with an event
and its data
. Depending on your configurations MudPi will broadcast events on both Redis and MQTT.
A topic is a communication line that MudPi will broadcast data on. Only clients listening on a topic can receive its events and event data. Events are not rebroadcast so if a listener misses an event it's gone.
You can subscribe to events in MudPi through the mudpi core instance which has the event system available through its events
attribute. Here is how you would subscribe to an event on the state
topic.
def display_data(event_data):
print(event_data)
mudpi.events.subscribe('state', display_data)
MudPi emits several events throughout its operations. It can be useful to know these events to add features and hook in additional functionality.
topic: state
Fired anytime new state is detected. Data will be an object with its state.
{
"event": "StateUpdated",
"new_state": {...},
"component_id": "example_1",
"previous_state": {...},
"updated_at": "2021-03-13 12:15:11"
}
topic: core
Fired when core is prepared. Useful for hooks. Data will be Null.
{
"event": "Loaded",
"data": None
}
Fired when core is starting. Useful for hooks. Data will be Null.
{
"event": "Starting",
"data": None
}
Fired after core is started. Useful for hooks. Data will be Null.
{
"event": "Started",
"data": None
}
Fired when core is stopping. Useful for hooks. Data will be Null.
{
"event": "Stopping",
"data": None
}
Fired when core is stopped. Useful for hooks. Data will be Null.
{
"event": "Stopped",
"data": None
}
Fired when core is shutting down. Useful for hooks. Data will be Null.
{
"event": "ShuttingDown",
"data": None
}
Fired just before core is fully shutdown. Useful for hooks. Data will be Null.
{
"event": "Shutdown",
"data": None
}
Fired when an action is called. Data will be an object of all your action data.
{
"event": "ActionCall",
"data": {...},
"action": 'example_1.action',
"namespace": None
}
Fired when an action is registered to the core. Data will be an object of all your action data.
{
"event": "ActionRegistered",
"action": 'example_1.action',
"namespace": None
}
Fired when a component is registered to the core. Data will be an object of all your component data.
{
"event": "ComponentRegistered",
"component": 'component_key',
"namespace": None
}
Fired when a extension is registered to the core. Data will be an object of your extension namespace.
{
"event": "ExtensionRegistered",
"namespace": 'extension_namespace'
}
Extensions also work on the event system. The rule for extensions is that they must only emit events on a topic
the same as their namespace. They are allowed to subscribe to any topic though. Extensions often emit events when their components are updated or some change has taken place i.e. a toggle turned on.
topic: Based on value set for "namespace"
option in extension configuration
Below is an example of an event that is emit by the toggle
extension.
{
"event": "ToggleUpdated",
"component_id": "example_toggle_1",
"state": {...},
"invert_state": False,
"updated_at": "2021-03-13 12:15:11"
}
MudPi supports multiple event systems to broadcast events on. Since you could possibly enable multiple systems at once there is going to be duplicate events listened for. For example if you have both redis
and mqtt
configured MudPi will send and listen for events on both. This means now each listener is getting the same message once on each bus. To prevent duplicate events across channels MudPi will insert a uuid
on all events it broadcasts. You can provide one manually but this is taken care of for you.
Most extensions that interact with events are encouraged to cache the previous event handled and check that that same event is not being handled again just from a different bus. Only the last event is cached so if another event get handled in between it is likely a duplicate event could still occur. However, because these events are sent microseconds between one another when they do occur its highly unlikely another event will squeeze in between during this time.