Skip to content

Reactive client to interact with Homie IoT devices via MQTT

License

Notifications You must be signed in to change notification settings

CMCRobotics/homie-client-rx

 
 

Repository files navigation

Python Homie client

PyPI versionPython package

This is an implementation of a client for IoT devices following the Homie MQTT convention. Currently, it only really supports sensor-like devices, i.e., those devices that publish retained non-settable properties. It is based on [https://github.com/michelwilson/homieclient] but intends to extend it by adding :

  • Support for URL based MQTT configuration (instead of IP / Port, to allow support for websockets for instance)
  • Support for reactive Rx3 events (instead of plain callbacks, to support async and reactive operators)

Usage

Create an instance of the client, register observables, and connect it to your MQTT server:

from homieclientrx.client import HomieClientRx
from homieclientrx.event import Event, EventType, EVENTS_PROPERTY

mqtt = paho.mqtt.client.Client()
c = HomieClientRx(mqtt)
subj = Subject()
# You can use your favorite reactive operator to triage, filter and debounce Homie events
subj.pipe(ops.filter(lambda evt: evt.event_type == EventType.DEVICE_DISCOVERED)) \
        .subscribe(on_next=lambda evt: print(f"Device discovered, name: {evt.device.name} type: {evt.device.name}"))

subj.pipe(ops.filter(lambda evt: evt.event_type in EVENTS_PROPERTY)) \
        .subscribe(on_next=lambda evt: print(f"Property updated, name: {evt.homie_property.name} new value : {evt.updated_value}"))

# Register the reactive observable to start receiving events
c.register_observable(subj)  

# Likewise, you can unregister observables if you wish to stop receiving messages
c.unregister_observable(subj)

# Do not forget to activate the MQTT connection, or messages will not flow !
mqtt.connect("localhost", 1883)

# Receive property updates (...)

# If you need to update a property, send an MQTT message on the desired topic (Homie won't help you there ;-) )
mqtt.publish("homie/mydevice/mynode/myproperty","my new value")

# When you are done, do not forget to disconnect your MQTT client
mqtt.disconnect()

# Following the similar philosophy, you are in charge of handling MQTT disconnections, reconnections
#  for instance, by using retry decorators.

The following event types are supported :

  • DEVICE_DISCOVERED : A previously unknown Homie device has been found in the device hierarchy.
  • DEVICE_UPDATED : A known Homie device had one of its attributes updated (find the name of the attribute in the event's homie_attr property)
  • NODE_DISCOVERED : A previously unknown node has been found on a known device.
  • NODE_UPDATED : A known node had one of its attributes updated (find the name of the attribute in the event's homie_attr property)
  • PROPERTY_DISCOVERED : A previously unknown property has been found on a known node.
  • PROPERTY_UPDATED : The property value has changed (find the name of the attribute in the event's homie_property property)

It is also possible to access all the devices, nodes and properties via the client, without using any of the callbacks. Every device is exposed as a property on the client, the nodes are exposed as properties on the device, and the properties as properties on the node. So if you have a device with id outdoor_sensor with node sensor and property temperature, you can do

temperature = c.outdoor_sensor.sensor.temperature
print('%s: %.1f %s' % (temperature.name, temperature.value, temperature.unit))

This will print something like

Temperature: 21.4 °C

assuming the name of the property is Temperature, and it reports a float value, and the weather is quite nice.

About

Reactive client to interact with Homie IoT devices via MQTT

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%