Connecting snips to openhab

#1

Hello all
I was asked to share my knowledge about connecting snips with openhab, so I will. :grinning:

I set up snips on a different device (rapsberry pi) as my openhab system is running (another raspberry pi).

  1. Install the mqtt binding and mqtt action in openhab

  2. Do mqtt bridging by editing the /etc/mosquitto/mosquitto.conf file on your snips server and add

    connection snips-openhab-bridge
    address <name or ip of openhab server>:1883
    clientid snips
    start_type automatic
    username <username>
    password <password>
    notifications false
    try_private true
    topic hermes/intent/# both 0
    topic hermes/dialogueManager/# both 0

Replace the parts in <> with your configuration data.
This will publish all snips intents of the snips mqtt broker to the openhab mqtt broker, too.

  1. In openhab create an item to get the snips mqtt messages.
String Snips_Intent "Snips Intent" { mqtt="&lt;[mqtt-openhab:hermes/intent/#:state:default]" }
  1. Create a rule in openhab to get the snips intent data
rule "Snips"
when
    Item Snips_Intent received update
then
    //logInfo("Snips Intent", Snips_Intent.toString)

    var String intentName = transform("JSONPATH", "$.intent.intentName", Snips_Intent.state.toString) 
    var String snipsIntent  = intentName.split(":").get(1);
    var String snipsSlot1RawValue = transform("JSONPATH", "$.slots[0].rawValue", Snips_Intent.state.toString)
    var String snipsSlot1Value    = transform("JSONPATH", "$.slots[0].value.value", Snips_Intent.state.toString)

    logInfo("snips.rule", "intent: " + snipsIntent)
    logInfo("snips.rule", "raw value: " + snipsSlot1RawValue)
    logInfo("snips.rule", "slot: " + snipsSlot1Value)
end

Within this rule you can do anything what is possible in openhab.

In my environment I have temperature sensors in my house that I can ask snips to reply the current temperature.

For this I created a snips app with the intent TemperaturAbfrage.
This intent has one slot for the room.
For example a snips output could be:

{
  "input": "wie ist die temperatur in wohnzimmer",
  "intent": {
    "intentName": "Agamemnon:TemperaturAbfrage",
    "probability": 1
  },
  "slots": [
    {
      "rawValue": "wohnzimmer",
      "value": {
        "kind": "Custom",
        "value": "Wohnzimmer"
      },
      "range": {
        "start": 26,
        "end": 36
      },
      "entity": "roomNames",
      "slotName": "RoomName"
    }
  ]
}

In the openhab rule I added the following:

import org.eclipse.smarthome.model.script.ScriptServiceUtil

if (snipsIntent == 'TemperaturAbfrage') {
        var ItemName = "LaCrosseTemperatureSensor" + snipsSlot1Value + "_Temperatur"
        val MyItem = ScriptServiceUtil.getItemRegistry.getItem(ItemName)
        var CurrentTemperature = MyItem.state.toString
        CurrentTemperature = CurrentTemperature.replace(".", ",")
        publish("mqtt-openhab", "hermes/dialogueManager/startSession", "{\"siteId\":\"default\",\"init\":{\"type\":\"notification\",\"text\":\"Die Temperatur beträgt " + CurrentTemperature + " Grad\"}}")
        logInfo("snips.rule", "Temperatur in " + snipsSlot1Value + ": " + CurrentTemperature)
}

This is creating the openhab item name out of the slot of the intent.
I then use this itemname with the getItemRegistry function to get the item and the state (temperature).
At least I use the mqtt publish action to publish the result to the local (openhab) mqtt broker.
Due tu the bridging on top it is automatically published to the snips mqtt broker (dialogueManager), too.

Ask, if you need further support on this setup.

Best regards,
Matthias

2 Likes
Change voice feedback to german
#2

Thank you for sharing your setup. Great idea. I will try to build it like this.
Is there a reason why you use mqtt and not the REST API?

#3

I am already using mqtt in openhab for other connections and snips is using mqtt, too.
For me that was by far the easiest way to connect both systems without any programming.

#4

Thank you for sharing, I’m trying to move from Alexa to snips and making my first steps, with your example I get the snips output in the openhab log.

But, I can’t get the “ScriptServiceUtil” to work.
Have I something to import?

Great work, go on

#5

My fault… I forgot the very first line.
Yes, you need to import the ScriptServiceUtils

import org.eclipse.smarthome.model.script.ScriptServiceUtil

I modified the initial post.
Thanks for that hint.

BR
Matthias

#6

Thank you for fast replay,
I’ll try this afternoon.

Have a nice day

BR
Matthias :wink:

#7

Hello,

I use snips with openhab too. But i did it in different way.
I added mqtt bind (client) to openhab. And create a bridge with a channel by intent :

Bridge mqtt:broker:mymqttsnips "MQTT Snips Broker" [ host="snips-master" ] 
{
    Thing topic thsnips "Generic MQTT Snips" 
    {
        Channels:
            Type string : light_off "Light off"  [ stateTopic="hermes/intent/cedcox:eteindreLumiere", commandTopic="", formatBeforePublish="" ]
            Type string : light_dim_down "Light DIM down"  [ stateTopic="hermes/intent/cedcox:varierBasLumiere", commandTopic="", formatBeforePublish="" ]
        [....... and so on ....]
}

}

and after, i create one rule by intent :

rule "light off"
    when
        Item Snips_Intent_light_off received update 
    then
        confidence = transform("JSONPATH", "$.intent.probability", Snips_Intent_light_off.state.toString)
        logInfo("rule light off", "confidence : " + confidence.toString)  

    if (Double::parseDouble(confidence) > 0.8) {
        //
        // Get variables
        //   

        siteId = transform("JSONPATH", "$.siteId", Snips_Intent_light_off.state.toString)
        logInfo("rule light off", "siteId : " + siteId.toString)  

        sessionId = transform("JSONPATH", "$.sessionId", Snips_Intent_light_off.state.toString)
        logInfo("rule light off", "sessionId : " + sessionId.toString)  

        entity_room = transform("JSONPATH", "$.slots.[?(@.slotName== 'house_room')].value.value", Snips_Intent_light_off.state.toString)
        entity_room = entity_room.replace("-","_")
        entity_room = entity_room.replace(" le ","")
        entity_room = entity_room.replace(" la ","")
        entity_room = entity_room.replace(" du ","")
        entity_room = entity_room.replace(" d'","")
        entity_room = entity_room.replace(" l'","")
        entity_room = entity_room.replace(" ","_")
        entity_room = entity_room.replace("'","_")
        entity_room = entity_room.replace("é","e")
        entity_room = entity_room.replace("à","a")
        entity_room = entity_room.replace("ê","e")
        entity_room = entity_room.replace("î","i")
        logInfo("rule light off", "entity_room : " + entity_room)  

    [.... blablablabla ...]

An alternative solution that does not need a mqtt srever on openhab (if you did not need it before :wink: )
Does not manage multislot of house_room, but i have already an idea to implement… I just need time :slight_smile:

Ced

#8

Thank you for that alternative.
I like the idea to check for the confidence, will implement that, too. :grin:

#9

Hi all,

I use Openhab with Snips too, but I’ve a problem with the mqtt connection. With one Snips-Master everything works fine but when I add a satellite the communication between openhab and snips is broken. When i deconnect the sattelite all things works fine.
Anybody have an idea?
Thanks a lot.

#10

I do not have experience with using satellites, but I recommend to use http://mqttfx.jensd.de/ and checking what is going on in mqtt.

1 Like
#11

Edit: Working now

Following this I ran into this problem:

Any idea what’s wrong?

1 Like
#12

Hello everybody! this is my first time on forum, I have a working openhab installation with mqtt running and I want to test Snips!
I am trying to configure basic command configurations for controlling music, like pause, play, next song and up/down volume… could you please better explain how to configure in snips console side (for send datas via mqtt to my broker)? I mean… i create some intents for different commands… and then? what do I have to do in action types?
thank you very much for your help and sharing!

Daniele

#13

Hi @dntr,

maybe just tell us a bit more about your setup so we can give you a good answer. :slight_smile:
Which hardware do you use and which items did you define in OpenHAB?

It is possible to connect Snips and OpenHAB without defining any actions, just intents. Have a look at this post: Connecting snips to openhab

#14

Hi @dntr,

do you use standard rules or Next-Gen-Rules via JSR223? If you use the latter, do you use JavaScript? If so, then I can provide you a mini howto.

Have a nice weekend!
freddy

#15

Hello everybody! thanks for your answers!

I use some sonoff with tasmota firmware and I would like to use snips mainly for controlling music (for now)… play, pause, next track and volume.
I have chromecast audio (with binding installed in openhab) with multiroom configuration and my main source is spotify premium… (or some web radio)
Openhab run on raspberry pi 2 with mosquitto and now I have set up a new raspberry pi3 only for snips (and would like to add some snips satellite in future if they are working good!).
I prefer to use the openhab broker, not the snips one because it is already working!
I use standard rules, I am not up-to-date with next-gen-rules but if they are easier… why not?! :slight_smile:

thanks everybody for your help!

Daniele

#16

I tried Mathias solution but it is not working, I think there is a problem with mqtt because I cant see anything on openhab broker about the hermes topic…
I added the code in the /etc/mosquitto/mosquitto.conf file on snips server (and reboot) but still no updates… how can I make snips talking to openhab (easy way) :slight_smile:

thanks

#17

Could you past your mosquitto.conf of your snips Raspi.
Maybe we can figure out what is wrong.

#18

It Works! I receive update on openhab mosquitto now!

I have also created the rule as in Matthias post:
rule “Snips”
when
Item Snips_Intent received update
then
//logInfo(“Snips Intent”, Snips_Intent.toString)

var String intentName = transform("JSONPATH", "$.intent.intentName", Snips_Intent.state.toString) 
var String snipsIntent  = intentName.split(":").get(1);
var String snipsSlot1RawValue = transform("JSONPATH", "$.slots[0].rawValue", Snips_Intent.state.toString)
var String snipsSlot1Value    = transform("JSONPATH", "$.slots[0].value.value", Snips_Intent.state.toString)

logInfo("snips.rule", "intent: " + snipsIntent)
logInfo("snips.rule", "raw value: " + snipsSlot1RawValue)
logInfo("snips.rule", "slot: " + snipsSlot1Value)

end

but when I use 2 slot I am not able to grab the content…

So I have added:
var String snipsSlot2Value = transform(“JSONPATH”, “$.slots[1].value.value”, Snips_Intent.state.toString)

but doesn’t work… any suggestion?

I am also trying to control a chromecast stream with snips but I am only able to pause it!

in .item:
Player Music (gAudio) { channel=“chromecast:audiogroup:c2bad9e1-5203-421c-b7b3-7051b8d25681:control” }

in .rules:
if (snipsIntent == ‘pause’) {
sendCommand(Music,PAUSE)
}

how can i send a webstream instead?!

Thank you everybody!

#19

Hey, great to hear. Could you post the JSON that you get via MQTT?

As an example I show you one of my rules:

rule "Device ON"
when
    Item SnipsIntentDeviceOn received update
then
    var intent = transform("JSONPATH", "$.intent.intentName", SnipsIntentDeviceOn.state.toString)
    logInfo("rule device on", "Intent : " + intent.toString)  

    var confidence = transform("JSONPATH", "$.intent.confidenceScore", SnipsIntentDeviceOn.state.toString)
    logInfo("rule device on", "confidence : " + confidence.toString)  

    if (Double::parseDouble(confidence) > 0.7) {

        var siteId = transform("JSONPATH", "$.siteId", SnipsIntentDeviceOn.state.toString)
        logInfo("rule device on", "siteId : " + siteId.toString)  

        var sessionId = transform("JSONPATH", "$.sessionId", SnipsIntentDeviceOn.state.toString)
        logInfo("rule device on", "sessionId : " + sessionId.toString)  

        var slotDevice = transform("JSONPATH", "$.slots.[0].value.value", SnipsIntentDeviceOn.state.toString)
        logInfo("rule device on", "slotDevice : " + slotDevice)

        var slotRoom = transform("JSONPATH", "$.slots.[1].value.value", SnipsIntentDeviceOn.state.toString)
        logInfo("rule device on", "slotRoom : " + slotRoom)

    val testItem = ScriptServiceUtil.getItemRegistry.getItem(slotDevice)

    testItem.sendCommand("ON")

    }
end

This rule is connected to my “Device on” intent within Snips. This intent consists of two slots:

  1. The device that I want to turn on
  2. The room in which the device is located (optional)
#20

thank you, I’ll try your configuration soon!
I can’t understand the last part:

val testItem = ScriptServiceUtil.getItemRegistry.getItem(slotDevice)

testItem.sendCommand("ON")

anyway in my configuration I receive this json string:

{“sessionId”:“f71e9d3f-100d-496c-ad15-602448dcc8b6”,“customData”:null,“siteId”:“default”,“input”:“accendi la luce in sala”,“asrTokens”:[[{“value”:“accendi”,“confidence”:1.0,“rangeStart”:0,“rangeEnd”:7,“time”:{“start”:0.0,“end”:0.26999998}},{“value”:“la”,“confidence”:0.98170763,“rangeStart”:8,“rangeEnd”:10,“time”:{“start”:0.26999998,“end”:0.5056098}},{“value”:“luce”,“confidence”:1.0,“rangeStart”:11,“rangeEnd”:15,“time”:{“start”:0.5056098,“end”:0.75}},{“value”:“in”,“confidence”:1.0,“rangeStart”:16,“rangeEnd”:18,“time”:{“start”:0.75,“end”:0.75}},{“value”:“sala”,“confidence”:0.9643355,“rangeStart”:19,“rangeEnd”:23,“time”:{“start”:0.75320977,“end”:0.94279736}}]],“asrConfidence”:0.9891042,“intent”:{“intentName”:“dntr:TurnOn”,“confidenceScore”:0.7114572},“slots”:[{“rawValue”:“luce”,“value”:{“kind”:“Custom”,“value”:“luce”},“range”:{“start”:11,“end”:15},“entity”:“snips/default–house_device”,“slotName”:“house_device”,“confidenceScore”:1.0},{“rawValue”:“sala”,“value”:{“kind”:“Custom”,“value”:“sala”},“range”:{“start”:19,“end”:23},“entity”:“house_room”,“slotName”:“house_room”,“confidenceScore”:0.9643355}]}

I use one slot for house_device and one for house_room, now I will play with the code! will let you know! :slight_smile: