Minimal async pub/sub package with decorators and state machines
Project description
cm-events
Simple async pub/sub package I made for an assignment of an Embedded Systems curricular unit.
What it does
Just decouples pub/sub messaging from actual business logic like reading sensors and pushing notifications. Didn't like all the bloated code I had so I built this mini package to abstract away event handling using decorators and implementing just the required methods for an RPI controller needed for the assignment.
Basically, It lets you:
- Have components that publish events (like sensor readers)
- Have components that subscribe to events (like data processors)
- Auto-register components with decorators
- Basic state machine support for stateful components
Basic usage
from events import EventType, Event, Publisher, Subscriber, Broker, register
class YourEvents(EventType):
SOME_EVENT = "some_event"
@register
class YourSensor(Publisher):
async def startup(self):
... # start up your sensor
async def run(self):
while True:
reading = sense() # your sensor code
await self.publish(Event(
type=YourEvents.SOME_EVENT,
source="sensor_1",
payload={"value": reading}
))
await asyncio.sleep(1)
async def shutdown(self):
... # shutdown your sensor
@register
class ReadingLogger(Subscriber):
async def startup(self):
self.subscribe_to(YourEvents.SOME_EVENT)
async def handle_event(self, event):
print(f"Reading: {event.payload['value']}")
# Run it
async def main():
broker = Broker()
await broker.start()
try:
while True:
await asyncio.sleep(1)
except KeyboardInterrupt:
pass
await broker.stop()
asyncio.run(main())
Component types
Publisher- broadcasts events viapublish()Subscriber- receives subscribed events viahandle_event()Transceiver- does both
Multiple instances
If you need multiple instances of the same component:
from events import Publisher, register_multiple
@register_multiple([
{"pin": 18, "name": "sensor1"},
{"pin": 19, "name": "sensor2"}
])
class GPIOSensor(Publisher):
def __init__(self, pin, name):
self._pin = pin
self._name = name
# ...
State machines
For components that need states:
from events import StateMachine, Publisher, register, state, initial_state
@register
@initial_state("idle")
class StatefulComponent(StateMachine, Publisher):
@state("idle", poll_interval=1.0)
async def idle_state(self):
if some_condition():
return "working"
@state("working", poll_interval=0.1)
async def working_state(self):
do_work()
if done():
return "idle"
Install
poetry add cm-events
Requires Python 3.11+ and pydantic.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cm_events-0.1.0.tar.gz.
File metadata
- Download URL: cm_events-0.1.0.tar.gz
- Upload date:
- Size: 11.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.12.3 Linux/6.11.0-26-generic
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e9dba06b638c55d2afa949876c37c6570f81b0e241be829408a6abb0d11c91e7
|
|
| MD5 |
51e4e656c7ac59d04c09bc9cc678585b
|
|
| BLAKE2b-256 |
bc512ba4858d24e6672727b110afe14ef0221e65915d0ef2cece864d093f7643
|
File details
Details for the file cm_events-0.1.0-py3-none-any.whl.
File metadata
- Download URL: cm_events-0.1.0-py3-none-any.whl
- Upload date:
- Size: 18.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.12.3 Linux/6.11.0-26-generic
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e3735afd6cdeb360729208893dc922129407aae50c311e04f88521c65085a10e
|
|
| MD5 |
bf2605debad2b412db3e6cd02fb5171b
|
|
| BLAKE2b-256 |
120d2e21ced213aa16d2b500547b77b2bc882aa2f6c8847ac437dfc80deb896d
|