Connection to MQTT

Last updated 3 months ago

Introduction

You can imagine MQTT as a chat room. As a user, you connect to a chat room created, you can subscribe to specific topics to filter out messages. You can send and receive messages from other users on specific topics.

In our case, users are Snips Platform's components, like the Hotword, Automatic Speech Recognition or Text To Speech These components are sending and receiving messages to each other on predefined topics. We call it the Hermes Protocol. You can learn more by reading the Hermes Protocol documentation.

The bare minimum your action code needs to do is react to intents being detected by the NLU (Natural Language Understanding). When it detects an intent, the NLU component sends a message over MQTT. This means your action code simply needs to connect to MQTT, and listen to the right topics. The sample code we are going to provide here can be extrapolated to any language you may choose to code your action, as long as you are able to find an MQTT client for that language.

If you are coding your app in Python, we are providing you with a helper library, Hermes Python, that makes it easier to send and receive messages from MQTT. Jump straight to this page if you want to use it.

Sample code with paho mqtt library

Let's now give you an example on how to connect to MQTT. We'll illustrate this in Python, but the logic would be the same using any MQTT client in any language.

Prerequisites

  • Snips platform installed and running on the Pi

  • Snips' official weather app installed

  • Python pip & virtualenv installed

In Python, the Eclipse's paho.mqtt library is perfect for what we need. You can create and run the following python file on your computer. First, we connect to the relevant MQTT topic:

# !/usr/bin/env python
# encoding: utf-8
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print('Connected')
mqtt.subscribe('hermes/intent/#')
mqtt = mqtt.Client()
mqtt.on_connect = on_connect
mqtt.connect('raspberrypi.local', 1883)
mqtt.loop_forever()

Note that in the code above, # is used as a wildcard, to connect to all topics starting by hermes/intent. An alternative is to connect to the topic of a given topic, for example:

mqtt.subscribe('hermes/intent/searchWeatherForecast')

We now need to add a callback, to be able to react to the messages being received. For this, we will also need to import the json module. Here is the complete code, to simply print the objects being broadcated over the intent topics on MQTT:

# !/usr/bin/env python
# encoding: utf-8
import paho.mqtt.client as mqtt
import json
def on_connect(client, userdata, flags, rc):
print('Connected')
mqtt.subscribe('hermes/intent/#')
def on_message(client, userdata, msg):
# Parse the json response
intent_json = json.loads(msg.payload)
intentName = intent_json['intent']['intentName']
slots = intent_json['slots']
print('Intent {}'.format(intentName))
for slot in slots:
slot_name = slot['slotName']
raw_value = slot['rawValue']
value = slot['value']['value']
print('Slot {} -> \n\tRaw: {} \tValue: {}'.format(slot_name, raw_value, value))
mqtt = mqtt.Client()
mqtt.on_connect = on_connect
mqtt.on_message = on_message
mqtt.connect('raspberrypi.local', 1883)
mqtt.loop_forever()

Let's test this. Install the paho-mqtt dependency. For this we recommend using a virtualenv.

cd <path_to_your_action>
virtualenv venv
source venv/bin/activate
pip install paho-mqtt
python your-action.py

If you have the Snips Weather demo installed, try:

'Hey Snips! What will be the weather in London in two days?'

You should see the output:

Connected
Intent searchWeatherForecast
forecast_locality
Raw: london Value: London
forecast_start_datetime
Raw: in two days Value: 2018-06-22 00:00:00 +00:00

The corresponding JSON sent by the platform on MQTT on the topic hermes/intent/searchWeatherForecast

{
"sessionId": "4d2d171d-fb21-4bea-a76d-0293634f50d9",
"customData": null,
"siteId": "default",
"input": "what will be the weather in london in two days",
"intent": {
"intentName": "searchWeatherForecast",
"probability": 0.9337856
},
"slots": [
{
"rawValue": "london",
"value": {
"kind": "Custom",
"value": "London"
},
"range": {
"start": 28,
"end": 34
},
"entity": "locality",
"slotName": "forecast_locality"
},
{
"rawValue": "in two days",
"value": {
"kind": "InstantTime",
"value": "2018-06-22 00:00:00 +00:00",
"grain": "Day",
"precision": "Exact"
},
"range": {
"start": 35,
"end": 46
},
"entity": "snips/datetime",
"slotName": "forecast_start_datetime"
}
]
}

Once you are able to react to intents being shared on MQTT, it's up to you to write what you want to do after receiving the intent!