MQTT Events

Now I get your point, and yes you right about using an event. I will test that now and get back to you. Kind regards

@gpbenton,

Its me again. I have created the automation that triggers when a mqtt message is retrieved on my said topic, and my custom event is triggered. But no idea how to place the payload_json generated on the mqtt bus in my event; for I do understand that custom events don’t support templating yet.

So pls how do I transfer the data?

Thanks

I think that rather scuppers the whole idea. One of the reasons I hated all that yaml stuff in the first place.

Your stuck with your five different sensors I’m afraid.

:sob::sob::sob::sob::sob::sob::sob:

I implemented event_data_template to help with this so the data just gets handed directly to the event. I am unsure what limitation you are running into with sensors holding the data, is it just too many fields?

I have a pull request in. Hopefully get this merged at some point since I think it would be really useful to avoid the kludging of setting sensor states.

https://github.com/home-assistant/home-assistant/pull/11057/files#diff-271c3f410a76f769b10ff2dd3c7ec7d7

1 Like

@Odianosen25 @gpbenton so I just tested this config in my automations and it worked for me. This reads the topic off mqtt and passes the entire payload to appdaemon

- alias: intentNotParsed
  trigger:
    platform: mqtt
    topic: hermes/nlu/intentNotParsed
  action:
    event: APP_INTENT_NOT_PARSED
    event_data_template:
      payload: '{{ trigger.payload }}'

AppDaemon get this
LOG INFO myapp: myapp_nluIntentNotParsed: {‘payload’: “{‘intent’: ‘this_intent’}”}

@ReneTode @aimc figure you guys might like this as well since it will greatly simplify getting external data into an app. Now just need to get Paulus to accept it :slight_smile:

1 Like

@tschmidty,

Thanks for this, and I am also trying to use it to process snips data in AppDaemon :slight_smile:.

So is there something I need to do to activate the templating or is it a custom component or something? I went to your link, but I really don’t know how to pull stuffs in except via custom component.

Hope this will also work for the json payload too?

Kind regards

@Odianosen25 you would need to do a git checkout and merge which is a bit of a bear and would get overwritten next upgrade if it doesn’t get merged. An easy cheat if you want to test is to do a git clone and copy these 4 files

homeassistant/helpers/template.py
homeassistant/helpers/script.py
homeassistant/helpers/service.py
homeassistant/helpers/config_validation.py

Into wherever your home assistant libs are, mine is /srv/homeassistant/lib/python3.6/site-packages/homeassistant/helpers with the standard virtualenv install. Docker or hassio you are on your own!

Not sure what you mean about json payload since that is one. Here is an example of literally just sending the entire intent to appdaemon
automations.yaml

- alias: snips_intent
  trigger:
    platform: mqtt
    topic: hermes/intent/#
  action:
    event: JARVIS_INTENT_NOT_PARSED
    event_data_template:
      payload: '{{ trigger.payload }}'
INFO jarvis: jarvis_intent_not_parsed: {'payload': '{"sessionId":"6bbd31e1-8168-4ee0-bdcc-20073c313b10","customData":null,"siteId":"default","input":"turn christmas lights on","intent":{"intentName":"user_rZEKlr8M7M3__lightsTurnOnSet","probability":0.7173734},"slots":[{"rawValue":"christmas","value":{"kind":"Custom","value":"christmas"},"range":{"start":5,"end":14},"entity":"house_room","slotName":"house_room"}]}'}

With this, the intent was parsed properly in HASS (my christmas lights came on) and the full json intent was also passed to app daemon as you can see in the log.

for me there is no advantage, because i dont use mqtt, but the question is what the real advantage is.

the mqtt gives raw data that you translate to sensors.
those sensors can be used to make actions inside AD.

if i want the raw data into AD i wouldnt go through HA, but write an app that can read out mqtt data.

so i see only 2 real use cases:

  1. MQTT > HA > splitt out data > AD
  2. MQTT > AD > splitt out data > HA

but i gladly hear what your usecase for it is.

@tschmidty,

Ok many thanks for that and will do as said. I am new to git so no clue what “git checkout” means though know git clone.

Will just copy the files into the directory. But I believe that will still wipe it out after the next updates anyway.

Hopefully it will be merged in during the next update as it will really make things easier.

Kind regards

But why go through the extra step of putting data into sensors to get it into AD? Parsing the data in yaml and mapping values is a pain and much easier to do in AD IMO. Plus then you have extra sensors cluttering things up.

And yeah, I could write an app to listen to mqtt events as well and had one running but why have another daemon when HA is already there? And there is also the benefit as you say of having the data split.

A use case for that is that I will do will be having HASS/AD/Snips be able to initiate conversations off of events, and to do so I need the full data that comes across MQTT. And again, yeah I could have a separate listener.

@tschmidty,

Yep that was my initial thought, until I figured out there was no way to listen for mqtt messages which @gpbenton did confirm was true. That was the only way I could get around the issue so it wasn’t intentional as per say. if you know otherwise, pls advise as I had tried this

self.listen_event(self.mqttEvent, "mqtt", topic= "hermes/nlu/intentParsed")

But nothing worked even though the event trigger was triggering in yaml on the same topic.

The next option was to use custom event which I couldn’t until you came up with this template of event data. My use case is actually to communicate with snips over chatbot on telegram and create like a little “chatbot” for the home (as I refused to expose my system to the internet due to some limitations and other stuffs). For this I needed full access to the data on mqtt.

Regards

I also tried implementing a listener in appdaemon and it would start and connect but I couldn’t get the loop to run. But that felt like a kludge anyway since I have a perfectly good listener in hass.

Well at least you got the skill to develop the event_data_template. I am no programmer so was stuck :pensive:. Will test your software and get back to you if any issues.

Thanks again for the help

This is also my thinking. I hope you progress your event_data_template through to a full HA release.

maybe my failing understanding from MQTT.
i just see it as entity communication. so for me the raw data is just something that needs to be translated to entities.
i see not much value from pulling raw data through my HA only to give it to something else.

then again, i dont also think of sensors cluthering things up, but as something to give me a view on things.
in AD i create sensors like last motion, last value changed, etc to view things in 1 view, without going through logs or history.

i guess we look at things differently :wink:

Oh sensor are perfect for something I want to keep a state of but a lot of what I will do is just pass one time info to AD in which case having a sensor isn’t a good fit since it is a static thing.

But everyone has their own ideas on how to implement things so having more options is always better.

1 Like

@tschmidty,

Well I finally solved my issue by coping a cue from how the Alexa and Google API is handled. I created a python script that subscribes to the topic of interest, and made it a service so it starts at boot up. This then sends the data to AD using “requests.post”. In AD I just registered an endpoint and I get all the raw data without getting HA involved.

I think this helps me with extra flexibility, without using sensors and making it independent of HA is actually a plus as I don’t need to cluster it just because I need to pass data.

Kind regards everyone for all the help and suggestions.

3 Likes

Hi,
@Odianosen25 can you give me more details or is there event the code of your python script available? Working on the same thing and this would save a lot of time :slight_smile:
Thank you

Hello @Fuffi,

Find below my script that sends the data from Snips to AppDaemon. I don’t send data from AppDaemon to Snips yet as I have no need of it for the mean time but have a script I could use for that also.

Basically I modified the handler I saw in this example project. I am parsing the data in the script, so a “clean” set of data is sent to AppDaemon instead of doing all that in AppDaemon. Snips runs on a different Pi from that of AppDaemon and HA. Also I have data being sent from Telegram to Snips to make use of its NLU without ASR, so I can use it to make the same queries over chat and that’s why its busier than it needs to. You can modify and remove the unneeded bits.

#!/usr/bin/python

from __future__ import unicode_literals

import datetime
import json
import paho.mqtt.client as mqtt
import requests
import re

fromtimestamp = datetime.datetime.fromtimestamp

# MQTT client to connect to the bus
mqtt_client = mqtt.Client()
HOST = "YOUR HOST" 
PORT = 1883
TOPICS = ["hermes/nlu/intentParsed", "hermes/hotword/default/detected", "hermes/nlu/intentNotRecognized"] 
URL = "http://localhost:5000/api/appdaemon/snips"
API_TOKEN = "AppDaemon API KEY"
header = {'content-type': 'application/json', 'x-ad-access': '{}'.format(API_TOKEN)}
MQTT_USERNAME = "YOUR MQTT BROKER USERNAME"
MQTT_PASSWORD = "YOUR MQTT BROKER PASSWORD"
USERS = ["USER1", "USER2", "USER3"]
global site

# Subscribe to the important messages
def on_connect(client, userdata, flags, rc):
    print("AppDaemon-Snips Bridge Connected to Broker") # for debug reasons
    for topic in TOPICS:
        mqtt_client.subscribe(topic)

# Process a message as it arrives
def on_message(client, userdata, msg):
    print(msg.topic)  # for debug reasons
    print(msg.payload)  # for debug reasons
    data = parse_data(msg)
    if data == "default":
        return
    slots = parse_slots(msg)
    for k,v in slots.items():
        data[k] = v
    print(json.dumps(data))  # for debug reasons
    try:
        requests.post(URL, data = json.dumps(data) , headers = header)  
    except:
        raise Exception("Error When sending request")
        print("Error When sending request")
        
def parse_data(msg):
    global site
    data = {}
    if msg.topic == TOPICS[1]:
        rawData = json.loads(msg.payload)
        site = rawData["siteId"]
        data = site
        return data
    rawData = json.loads(msg.payload)
    intent = rawData['intent']['intentName']
    value = re.findall("[a-zA-Z0-9]+", intent)
    data['intent'] = value[len(data) - 1]
    if rawData['id'] in USERS:
        data['id'] = rawData['id']
    else:
        data['id'] = site
    data['sessionId'] = rawData['sessionId']
    return data
        
def parse_slots(msg):
    '''
    We extract the slots as a dict
    '''
    data = json.loads(msg.payload)
    try:
        slot_data = {slot['slotName']: slot['value']['value'] for slot in data['slots']}
    except:
        slot_data = {}
    return slot_data


if __name__ == '__main__':
    mqtt_client.on_connect = on_connect
    mqtt_client.on_message = on_message
    mqtt_client.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD)
    mqtt_client.connect(HOST, PORT)
    mqtt_client.loop_forever()

In AD I have this to call my function when a message is received self.register_endpoint(self.api_interface, "snips") and it calls my function def api_interface(self, data).

A more detailed explanation is on my little repository

Hope this helps and pls let me know if you spot something fishy in the code as I am not a programmer but just good at copying and pasting :see_no_evil: