Official Alexa Smart Home Skill for openHAB 2

Hi @jeshab,

I’m struggling for hours … I wonder if there is not a bug with Alexa.
I exactly tried your item definition and phrases, but i got the message l'appareil salon volet ne prend pas en charge cette commande

I have deployed my own Lambda instance to debug, and it seems that the device descriptor is totally ignored by Alexa…

{
          "endpointId": "AX_DW_mRDC_Salon_volettest",
          "manufacturerName": "openHAB",
          "friendlyName": "Salon Volet",
          "description": "Rollershutter AX_DW_mRDC_Salon_volettest via openHAB",
          "displayCategories": [
            "EXTERIOR_BLIND"
          ],
          "cookie": {
            "propertyMap": "{\"RangeController:AX_DW_mRDC_Salon_volettest\":{\"rangeValue\":{\"parameters\":{\"supportedRange\":{\"minimumValue\":0,\"maximumValue\":100,\"precision\":10},\"actionMappings\":[{\"name\":\"Close\",\"directive\":{\"name\":\"SetRangeValue\",\"payload\":{\"rangeValue\":0}}},{\"name\":\"Open\",\"directive\":{\"name\":\"SetRangeValue\",\"payload\":{\"rangeValue\":100}}},{\"name\":\"Lower\",\"directive\":{\"name\":\"AdjustRangeValue\",\"payload\":{\"rangeValueDelta\":-10,\"rangeValueDeltaDefault\":false}}},{\"name\":\"Raise\",\"directive\":{\"name\":\"AdjustRangeValue\",\"payload\":{\"rangeValueDelta\":10,\"rangeValueDeltaDefault\":false}}}],\"unitOfMeasure\":\"Percent\",\"category\":\"EXTERIOR_BLIND\",\"stateMappings\":[{\"name\":\"Closed\",\"value\":0},{\"name\":\"Open\",\"range\":{\"minimumValue\":1,\"maximumValue\":100}}],\"friendlyNames\":[\"Salon Volet\"]},\"item\":{\"name\":\"AX_DW_mRDC_Salon_volettest\",\"type\":\"Rollershutter\"},\"schema\":{\"name\":\"rangeValue\"}}}}"
          },
          "capabilities": [
            {
              "type": "AlexaInterface",
              "interface": "Alexa",
              "version": "3"
            },
            {
              "type": "AlexaInterface",
              "interface": "Alexa.RangeController",
              "version": "3",
              "instance": "AX_DW_mRDC_Salon_volettest",
              "capabilityResources": {
                "friendlyNames": [
                  {
                    "@type": "text",
                    "value": {
                      "text": "Salon Volet",
                      "locale": "en-AU"
                    }
                  },
                  {
                    "@type": "text",
                    "value": {
                      "text": "Salon Volet",
                      "locale": "en-CA"
                    }
                  },
                  {
                    "@type": "text",
                    "value": {
                      "text": "Salon Volet",
                      "locale": "en-GB"
                    }
                  },
                  {
                    "@type": "text",
                    "value": {
                      "text": "Salon Volet",
                      "locale": "en-IN"
                    }
                  },
                  {
                    "@type": "text",
                    "value": {
                      "text": "Salon Volet",
                      "locale": "en-US"
                    }
                  }
                ]
              },
              "properties": {
                "supported": [
                  {
                    "name": "rangeValue"
                  }
                ],
                "proactivelyReported": false,
                "retrievable": true,
                "nonControllable": false
              },
              "configuration": {
                "supportedRange": {
                  "minimumValue": 0,
                  "maximumValue": 100,
                  "precision": 10
                },
                "unitOfMeasure": "Alexa.Unit.Percent"
              },
              "semantics": {
                "actionMappings": [
                  {
                    "@type": "ActionsToDirective",
                    "actions": [
                      "Alexa.Actions.Close"
                    ],
                    "directive": {
                      "name": "SetRangeValue",
                      "payload": {
                        "rangeValue": 0
                      }
                    }
                  },
                  {
                    "@type": "ActionsToDirective",
                    "actions": [
                      "Alexa.Actions.Open"
                    ],
                    "directive": {
                      "name": "SetRangeValue",
                      "payload": {
                        "rangeValue": 100
                      }
                    }
                  },
                  {
                    "@type": "ActionsToDirective",
                    "actions": [
                      "Alexa.Actions.Lower"
                    ],
                    "directive": {
                      "name": "AdjustRangeValue",
                      "payload": {
                        "rangeValueDelta": -10,
                        "rangeValueDeltaDefault": false
                      }
                    }
                  },
                  {
                    "@type": "ActionsToDirective",
                    "actions": [
                      "Alexa.Actions.Raise"
                    ],
                    "directive": {
                      "name": "AdjustRangeValue",
                      "payload": {
                        "rangeValueDelta": 10,
                        "rangeValueDeltaDefault": false
                      }
                    }
                  }
                ],
                "stateMappings": [
                  {
                    "@type": "StatesToValue",
                    "states": [
                      "Alexa.States.Closed"
                    ],
                    "value": 0
                  },
                  {
                    "@type": "StatesToRange",
                    "states": [
                      "Alexa.States.Open"
                    ],
                    "range": {
                      "minimumValue": 1,
                      "maximumValue": 100
                    }
                  }
                ]
              }
            },
            {
              "type": "AlexaInterface",
              "interface": "Alexa.EndpointHealth",
              "version": "3",
              "properties": {
                "supported": [
                  {
                    "name": "connectivity"
                  }
                ],
                "proactivelyReported": false,
                "retrievable": true
              }
            }
          ]
        }

Your regional settings are not setup properly on your server. If you look at the friendly names text-based locales, there are in English which is the default setting.

I changed it - but unfortunately not working better. Did you manage to have your shutters working fine with Alexa ?

Have you triggered an Alexa discovery after making the change? If so, try to delete your existing device and re-run the discovery. What utterances are you using based on your voice history?

As long as you are using the same exact item definition and utterances I mentioned above, it will work.

When I was testing I found Alexa can sometimes be very picky with words and pronunciation, especially if there are other similar sounding items. One tip for testing is to use item words that are very different from everything else and easy to say. Also, as Jeremy says, you can check Alexa history to see if the words were heard correctly.

@jeshab: Just tested your item and it still does not work for me :

Me : "Alexa, ouvre le volet du salon" (checked that Alexa actually understood it weel)
Alexa : "L'appareil volet salon ne prend pas en charge cette commande"

Very surprising that identical declaration/sentence does not behave the same on my end.

Same here… Driving me crazy. I have cleared all Alexa history, cache… etc.
Surprizingly, I have just enabled Homekit tags [ "WindowCovering" ] and it enabled only basic feature : the “lower” (baisse) and “raise” (monte), which does +10 / -10. Open and Close won’t work.

Not sure what to recommend at this point. Assuming it might be an issue with the Alexa simulator, I just switched one of my echo device to French (France), requested the same commands by voice and it still worked for me. I even added a light device called “Salon” to see if it create some conflict and still no problem controlling the two devices. The only difference I can see at this point would be the Amazon account country setting. Anyway, if we can’t get it solve, the support ticket I opened with the Alexa developer support team was escalated and I am waiting on a response.

In meantime, you can just define the raise/lower semantic actions to the open/close value, that you could have your blind open/close when requesting monte or baisse.

Since you have deployed your own skill, could you try to use the Alexa simulator, accessible through your Alexa Developer Console (under Test tab), and see if you get the same result? Make sure to use the same item definition I listed above.

The skill supports the Homekit tags. So you basically modeled your item as a Blind metadata label, which translates to the same item definition listed above.

I just got the update below on that support ticket. It seems like a capability overlapping issue on the Alexa side.

“I don’t have any news to share from the internal engineering team. However, in my research I found that this might be a known issue on our end stemming from the fact that evidently, it is acceptable in French to use “ouvre” or “ferme” in the context of turning a light bulb on or off as well. For example, “ouvre la lumière.” I’ll let you know once I have more information or confirmation from our engineers.”

Ah ! Thanks @jeshab ! Seems interesting !

@hairdresser Any chance you could do the testing I mentioned above? I would like to know if you get the same result than I did. Thanks!

Item
(Appended language parameter to force French language on that item for testing consistency)

Rollershutter AX_DW_mRDC_Salon_volettest "Salon Volet" {alexa="RangeController.rangeValue" [category="EXTERIOR_BLIND", supportedRange="0:100:10", unitOfMeasure="Percent", actionMappings="Close=0,Open=100,Lower=(-10),Raise=(+10)", stateMappings="Closed=0,Open=1:100", language="fr"]}

Simulator
(Brief mode is enabled on my account; that’s why there is an “Audio only response” on acknowledgement)

Events

2019-12-30 21:15:39.167 [ome.event.ItemCommandEvent] - Item 'AX_DW_mRDC_Salon_volettest' received command 100
2019-12-30 21:15:39.168 [vent.ItemStateChangedEvent] - AX_DW_mRDC_Salon_volettest changed from NULL to 100
2019-12-30 21:15:45.641 [ome.event.ItemCommandEvent] - Item 'AX_DW_mRDC_Salon_volettest' received command 0
2019-12-30 21:15:45.642 [vent.ItemStateChangedEvent] - AX_DW_mRDC_Salon_volettest changed from 100 to 0
2019-12-30 21:15:55.502 [ome.event.ItemCommandEvent] - Item 'AX_DW_mRDC_Salon_volettest' received command 100
2019-12-30 21:15:55.502 [vent.ItemStateChangedEvent] - AX_DW_mRDC_Salon_volettest changed from 0 to 100
2019-12-30 21:16:05.014 [ome.event.ItemCommandEvent] - Item 'AX_DW_mRDC_Salon_volettest' received command 0
2019-12-30 21:16:05.015 [vent.ItemStateChangedEvent] - AX_DW_mRDC_Salon_volettest changed from 100 to 0

How do you tell alexa to activate the stop mode?
I have configured it like you, in the alexa app I see the mode stop, up and down. I can select it and I see the change in the openhab log. But I am not able to tell alexa to do so :slight_smile:

Edit:
Now I got it :heart_eyes:
Your example is an english one. In my case alexa understand “stopp” (german) and your example uses stop.
For all german ones, here my setup + commands:

Group gEins                   "eins"                {alexa="Endpoint.EXTERIOR_BLIND"}
String Rollo_WZ_klein_stopp   "halt"       (gEins)  {alexa="ModeController.mode" [supportedModes="STOP=stopp,UP=auf,DOWN=zu", autoupdate="false"]}
Rollershutter Rollo_WZ_klein  "eins Rollo" (gEins)  {alexa="RangeController.rangeValue" [category="EXTERIOR_BLIND", friendlyNames="@Setting.Opening",
                                                     supportedRange="0:100:10", unitOfMeasure="Percent", actionMappings="Close=100,Open=0,Lower=(+10),Raise=(-10)", 
                                                     stateMappings="Closed=100,Open=0:100"],channel="loxone:miniserver:.." }
  • schliesse eins (close eins) → full close
  • oeffne eins (open eins) → full open
  • setze eins auf xx% (set eins auf xx %) → moves to % value
  • fahre eins hoch (raise eins) → moves up by 10%
  • fahre eins runter (lower eins) → moves down by 10%
  • eins stopp (oder: setze eins auf stopp) (set eins to stopp) → STOP mode is selected

For setting modes (mode controller item) you need to say it like this: ‘Set item name to STOP’.
If you want to say it like: ‘STOP item name’, then you need to create an Alexa routine for that phrase.

is it possible to send an openhab voicecommand to Alexa same as I would do when I command her by voice?
example: when echo spot is streaming radio, the display just shows the boring radio logo but the clock disappears. I need to call “Homescreen” to get back the clock display.
it would be great if I could sendcommand “Homescreen” to an item.
any idea?

For echo device control, you should check the Amazon Echo Control binding and its relevant community thread.

Hi

Is there a list of allowed endpoint names? I looked but I didn’t find one.

edit I think I found it… The allowed endpoint names are the same as those used for the display category

display-categories

@wawa79 @hairdresser So the latest update, related to the support case I have opened with Amazon, is that specific words need to be part of the device name, along with the usage of preposition, for the French and most likely other latin-based languages. This is something that I noticed in my testing above.

Therefore, for the French language, in order to prevent the capability overlapping issue, you will need to include the word “Volet”, “Store” or “Rideau”, for blinds, and “Porte”, for doors, in the device name. If you only have one device, you can just name it based on these words only. For composed names (e.g. “Salon Volet” or “Cuisine Store”), you will need to use a preposition “de” or “du” (e.g. “ouvre le volet du salon” or “ferme le store de la cuisine”).

It’s obviously not ideal especially since there are no device name restrictions with raise and lower semantic action requests but unfortunately, this is how Amazon implemented.

1 Like

The amazon link points to .com. I couldn’t add a review there, don’t spend enough there, but did so at .de , in English :slight_smile:

1 Like

Did you create for each blind an own stop rule?

I tried to solve this with one general rule. The item names of each group have the same name + the stop item has an additional “_stop” string.
If a member of a group receives the STOPP command, I get the item name via triggeringItem and remove the “_stop” string. So I get the real rollershutter item name and can use it to send the stop command.

Item/Group definition:

Group gName "group name" { .....

String test_stop "name1" (gName) {....
Rollershutter test "name2" (gName) {....

String test2_stop "name10" (gName) {....
Rollershutter test2 "name20" (gName) {....

....

Rule definition:

rule "stopp"
when
  Member of gName received command STOPP
then
val itemName = triggeringItem.name.replace("_stop", "")
sendCommand(itemName, "STOP")
end
1 Like

I have 19 blinds and only set up the STOP for 2 of them where its most useful. Plus an Alexa Routine to make the phrase ‘STOP blind’ work instead of ‘set blind to STOP’. I like your idea though.

I modified to code to make it work with my previous example and added some logging

This line needed the .toString to make it work

sendCommand(itemName.toString,'STOP')

.item

Group:String gShutterCommand  "Shutter command group"  // for Alexa STOP command rule

Group OfficeBlind "Office blind" {alexa="Endpoint.EXTERIOR_BLIND"}
    String OfficeShutter_Command "Office shutter command" (OfficeBlind,gShutterCommand) {alexa="ModeController.mode" [supportedModes="STOP=STOP,UP=UP, DOWN=DOWN", autoupdate="false"]} 
    Rollershutter Office_RollerShutter "Office shutter [%d %%]" <blinds> (OfficeBlind,gAllBlinds) {alexa="RangeController.rangeValue" [supportedRange="0:100:10", unitOfMeasure="Percent", actionMappings="Close=100,Open=0,Lower=(+10),Raise=(-10)", stateMappings="Closed=100,Open=1:100"], channel="openwebnet:bus_automation:Screen10:55:shutter" }

.rule

rule "STOP command"
when
    Member of gShutterCommand received command STOP
then
    val itemName = new StringBuilder()
    itemName.append = (triggeringItem.name.replace("Shutter_Command", ""))
    itemName.append('_RollerShutter')
    sendCommand(itemName.toString,'STOP')
    logInfo("Blinds", "STOP command sent to "+ itemName )
end

Blind stops. Log shows:

[INFO ] [clipse.smarthome.model.script.Blinds] - STOP command sent to Office_RollerShutter
2 Likes