Alexa Voice Command Room Awareness via OH

Tags: #<Tag:0x00007f2fb15d8c10> #<Tag:0x00007f2fb15d8760>

Currently, the Alexa room awareness feature (aka Alexa-enabled groups) is derived from the majority of the current display categories. So, until Amazon adds new categories, there is no way to address devices not part of that list (e.g. fans) via that feature.

Thanks to the Amazon Echo Control binding lastVoiceCommand channel and a proxy Alexa-linked activity item, we can mimic that feature from the OH side for unsupported categories.

The definitions below set the room awareness portion. This should handle any permutations of the Alexa activity capability commands. To add a new category, you just need to add an Alexa-enabled activity item, the category name lower-cased in the category regex ".*\\b(fan|<newCategory>)\\b.*", and the relevant devices to the mapping file using format <CATEGORY>-<Location>=<DeviceName>. If a specific room doesn’t have a device for a given category, specify the mapping with an empty device name. That way a voice error message will be sent back.

In order to prevent misfiring on specific named device voice commands (turn off bedroom fan from another room vs turn on the fan in the current room), the associated Alexa-linked activity item state is checked to determine if it was triggered or not. That way, only relevant voice commands that occurred within a second the activity item was triggered will generate a command, otherwise, they will be ignored.

Keep in mind that the fan control definition below is just indicative here and can be more complex if necessary but wanted to simplify that portion to focus on the room awareness logic.


Group gAlexaVoiceCommand "Alexa Voice Command"

String BedroomEchoDotLastVoiceCommand "Last Voice Command" (gAlexaVoiceCommand) {channel="amazonechocontrol:echo:account:echodot_bedroom:lastVoiceCommand"}
String BedroomEchoDotTextToSpeech "Text to Speech" {channel="amazonechocontrol:echo:account:echodot_bedroom:textToSpeech"}

Switch BedroomFanPower "Bedroom Fan" {alexa="Switchable"}

Switch AlexaActivityFan "Fan" {alexa="Activity", expire="1s"}


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

rule "Alexa Voice Command Room Awareness"
  Member of gAlexaVoiceCommand received update
  // Exit if voice command is "alexa"
  if (triggeringItem.state == "alexa") return;
  // Determine room location based on triggering item name
  val location ="Echo").get(0)
  // Determine device category and voice command based on triggering item state regex matching
  val category = transform("REGEX", ".*\\b(fan)\\b.*", triggeringItem.state.toString)
  val command = transform("REGEX", ".*\\b(activate|deactivate|disable|enable|on|off|start|stop)\\b.*", triggeringItem.state.toString)
  // Exit if category or command is null
  if (category === null || command === null) return;
  // Determine activity item state based on device category
  val activityState = ScriptServiceUtil.getItemRegistry.getItem("AlexaActivity" + category.capitalize).state.toString
  // Exit if activity item not triggered (state not defined)
  if (activityState == "NULL" || activityState == "UNDEF") return;
  // Determine device name and state based on category-location mapping and voice command
  val deviceName = transform("MAP", "", category.toUpperCase + "-" + location)
  val deviceState = if (command == "activate" || command == "enable" || command == "on" || command == "start") "ON" else "OFF"
  // Send command to device if name defined, otherwise generate text to speech error message
  if (deviceName != "")
    sendCommand(deviceName, deviceState)
    sendCommand("LastVoiceCommand", "TextToSpeech"), "There is no " + category + " to control in this room")