-
Notifications
You must be signed in to change notification settings - Fork 55
Feature Request: MQTT trigger #98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
You can use a However, if you set up a Home Assistant automation that subscribes to the topic and then fires an event with the topic and payload in it, you can easily use Something like: - alias: MQTT Messages
trigger:
- platform: mqtt
topic: mytopic/#
action:
- event: MQTT_MESSAGE
event_data:
topic: "{{ trigger.topic }}"
payload: "{{ trigger.payload }}" @event_trigger('MQTT_MESSAGE')
def mqtt_message(**data):
log.info(f"Got an MQTT MESSAGE: {data}") |
Thank you for the quick and very detailed answer! Since I finally (after giving a deeper thought) use some automations within HA (the simple ones), I will go for your second solution. EDIT: it works great - thank you very much once again! |
@craigbarratt in order to prevent the need for the Home Assistant automation in this scenario, a |
I don't know anything about mqtt. But it does seem popular and useful, so adding some native trigger support sounds like a great idea. Where should I start to learn about mqtt? I presume pyscript should natively trigger off mqtt messages (as you propose), and also be able to generate mqtt messages? |
First of all - thank you for MQTT is a bus to which you connect to either send messages to a topic (a topic would be for instance It is asynchronous and you can request some messages to be persistent (so when you subscribe to a topic, you get the last one - there is no stack). I use it extensively in my microservices to get some data, and push them so that other services can make use of it. For instance I check Internet access and push it to a topic. If there is a problem, I have Home Assistant listening to it, but also a home made dashboard that will display an alert, and a monitoring system that sends notifications etc. It is also typically used by IoTs to send their status, actions performed on them etc. So this is a many-to-many distribution system (several programs can register to a topic to send to it, independently of others, but typically there is one source and several listeners). It is implemented in Python via paho mqtt |
@craigbarratt since pyscript is entirely within Home Assistant, most of the work is already done for you. You don't need to worry about connecting to an MQTT server or how to publish payloads. Put VERY simply, MQTT is a message queue. Messages are published to topics. And other processes subscribe to those topics to receive the messages. Topics use "/" as a separator. Topic SUBSCRIPTIONS can contain two wildcard characters. "+" means one level and can appear anywhere. "#" means multiple levels and can only appear at the end. Nothing is ever as simple as it seems, but, in Home Assistant, I think the basics for listening to MQTT messages looks a lot like from homeassistant.components import mqtt
def message_handler(mqttmsg):
"""Listen for MQTT messages."""
func_vars = {
"topic": mqttmsg.topic,
"payload": mqttmsg.payload,
"qos": mqttmsg.qos,
}
try:
func_vars["payload_json"] = json.loads(mqttmsg.payload)
except ValueError:
pass
call_user_defined_method_here(func_vars)
remove = await mqtt.async_subscribe(
hass, topic, message_handler, encoding=encoding, qos=qos
)
A second argument to
Example user code might look like this: @mqtt_trigger('test/#', 'payload == "ON" and topic.endswith("/set")', qos=2)
def dothething(topic=None, payload=None):
# some code to turn the thing on
log.info(f"{topic} is now {payload}") This would match on topic |
For the sake of completeness, the MQTT protocol only supports one message per topic, new messages override the previous one (there is no stack). This is in case where persistence is enabled, otherwise messages are transient and if someone is not listening at the time it is sent, the message is lost. There are other implementations of such buses (RabbitMQ for instance) where the history of messages is kept (and a listener can retrieve all of them for a given topic) @dlashua thank you for the code, such a trigger would indeed be very useful. I have to learn someday async/await in Python (I use threading extensively but this is apparently old school). |
Yes: |
@craigbarratt another possible "gotcha" is that some people don't have MQTT established in Home Assistant. I have no idea what happens if you call MQTT has other features too (for instance, if you don't request a "clean_session" when you connect, MQTT will remember messages that you previously subscribed to and send them to you when you reconnect even if they aren't "retained"). This makes it really useful for not-constantly-connected IoT devices and such to be able to save battery and only check periodically for new messages. But, Home Assistant handles all of those pieces already. All pyscript needs to do is allow subscriptions and allow publishing (which it already does because of the service call). I can take a shot at a PR, if you'd like. But, I'll be copy-pasting the event_trigger bits and crossing my fingers that I did it right since I still haven't managed to work out how you implemented pseudo-decorators in pyscript. :) Though, in performing he copy-paste, I might actually finally figure it out. |
The only improvement I can think of compared to HASS's mqtt.publish deals with JSON. Lots of MQTT consumers use JSON to format messages. Doing this (the hard way) means:
Since pyscript has python-power, we can do this instead:
But, it would be nice if mqtt.publish could take a
|
I have updated the title of the question because it is not really relevant to the discussion after @craigbarratt reopened it. |
Thank you for the addition of this trigger - this is wonderful. How is it going to appear in HA? At the next version? Should I forcefully bring in the new version (and if so - how?) |
If you installed pyscript using HACS, go to HACS -> Integrations -> pyscript and select "Reinstall" from the menu. Then instead of 1.0.0, select the master version. |
@wsw70 you will likely be the first real user of this feature, as I'm not currently using it except in my test cases. So, if you see any issues, please open an issue right away so we can get them all cleaned up before it lands in a release. |
@dlashua I just tested it for I will rewrite my switch automation tonight (when everyone is asleep as I test in production :)) and will raise issues if there are any. The ability to have the actual topic when using wildcards is wonderful, thank you again for that! |
I could not resist and rewrote the automations in the evening (I am in France), and everything works perfectly with my Zigbee and RF433 devices (all of them ultimately communicate via MQTT). I am keeping an eye on my monitoring and the log console just in case but I think the code is top-notch. Thank you very much once again. |
Note: the original tile of the question was "[question] how to run a always-on script?"
I am converting my automation from AppDaemon to
pyscript
and some of them depend on MQTT (as a client). A typical case is a switch emitting to MQTT topic I want to listen to and act accordingly.This means that such a script is not triggered by anything but runs in the background, responds to some events it manages itself (MQTT messages in my case), and then contacts HA for some actions (switching on a light for instance).
Is it possible to run such a script? The only cases I saw in the documentation are ones that react to something (either time based, or coming from HA)
One solution would be to use HA to manage the MQTT messages, but there are problems with this in some cases (see https://community.home-assistant.io/t/how-to-get-the-name-of-the-actual-state-topic-in-an-mqtt-sensor/248541 for an example). Using HA is doable but I would prefer to avoid automations there and move everything to pyscript for consistency.
The text was updated successfully, but these errors were encountered: