From 5bb020742e5d9d393b0d34027115eabd338d086d Mon Sep 17 00:00:00 2001 From: jsetton Date: Tue, 6 Jul 2021 19:27:20 -0400 Subject: [PATCH] Major code refactoring * introduced new item configuration syntax using device metadata concept * added new device capabilities for camera, door/window covering, fan, networking and vacuum * improved security arm state error handling * added input custom mappings support * added playback stop and thermostat hold/fan capabilities support * added new custom asset ids and semantic extensions * added switch support to mode generic capability * improved dimmer/rollershutter support for range value generic capability * updated test suite increasing code coverage * added support for ask-cli v2 using cloudformation deployer * improved ci integration with automated production release deployment * added github action to update repository locales on crowdin changes * deprecated item sensor concept for decouple state support on specific capabilities * removed item tag support for oh3.x * removed alexa smarthome api v2 support Signed-off-by: jsetton --- .ask/config | 9 - .github/workflows/build.yml | 30 - .github/workflows/ci.yml | 107 + .github/workflows/doc.yml | 23 + .github/workflows/locale.yml | 36 + .gitignore | 8 +- .markdownlint.yml | 9 + CONTRIBUTING.md | 26 +- README.md | 165 +- USAGE.md | 2780 ++++++++++----- ask-resources.json | 30 + hooks/post_new_hook.ps1 | 53 - hooks/post_new_hook.sh | 40 - hooks/pre_deploy_hook.ps1 | 95 - hooks/pre_deploy_hook.sh | 72 - infrastructure/cfn-deployer/skill-stack.yml | 98 + lambda/.eslintrc.json | 14 + lambda/alexa/smarthome/capabilities/alexa.js | 32 + .../capabilities/brightnessController.js | 52 + .../capabilities/cameraStreamController.js | 84 + .../smarthome/capabilities/capability.js | 333 ++ .../capabilities/channelController.js | 52 + .../smarthome/capabilities/colorController.js | 76 + .../colorTemperatureController.js | 77 + .../smarthome/capabilities/contactSensor.js | 52 + .../smarthome/capabilities/endpointHealth.js | 43 + .../capabilities/equalizerController.js | 80 + lambda/alexa/smarthome/capabilities/index.js | 63 + .../smarthome/capabilities/inputController.js | 66 + .../capabilities/keypadController.js | 66 + .../smarthome/capabilities/lockController.js | 52 + .../smarthome/capabilities/modeController.js | 124 + .../smarthome/capabilities/motionSensor.js | 52 + .../networkingAccessController.js | 59 + .../capabilities/networkingConnectedDevice.js | 69 + .../networkingHomeNetworkController.js | 32 + .../capabilities/percentageController.js | 52 + .../capabilities/playbackController.js | 79 + .../smarthome/capabilities/powerController.js | 52 + .../capabilities/powerLevelController.js | 52 + .../smarthome/capabilities/rangeController.js | 140 + lambda/alexa/smarthome/capabilities/safety.js | 62 + .../smarthome/capabilities/sceneController.js | 66 + .../capabilities/securityPanelController.js | 81 + .../alexa/smarthome/capabilities/speaker.js | 53 + .../smarthome/capabilities/stepSpeaker.js | 53 + .../capabilities/temperatureSensor.js | 52 + .../capabilities/thermostatController.js | 145 + .../capabilities/toggleController.js | 93 + lambda/alexa/smarthome/catalog.js | 466 +++ lambda/alexa/smarthome/category.js | 347 ++ lambda/alexa/smarthome/constants.js | 144 + .../smarthome/device/attributes/alarmAlert.js | 39 + .../smarthome/device/attributes/armState.js | 42 + .../smarthome/device/attributes/attribute.js | 35 + .../device/attributes/batteryLevel.js | 70 + .../smarthome/device/attributes/brightness.js | 39 + .../device/attributes/burglaryAlarm.js | 39 + .../device/attributes/cameraStream.js | 39 + .../device/attributes/carbonMonoxideAlarm.js | 39 + .../smarthome/device/attributes/channel.js | 42 + .../smarthome/device/attributes/color.js | 39 + .../device/attributes/colorTemperature.js | 39 + .../attributes/contactDetectionState.js | 39 + .../device/attributes/coolingSetpoint.js | 53 + .../device/attributes/currentLockState.js | 39 + .../device/attributes/currentOpenState.js | 39 + .../device/attributes/ecoCoolingSetpoint.js | 39 + .../device/attributes/ecoHeatingSetpoint.js | 39 + .../device/attributes/equalizerBass.js | 46 + .../device/attributes/equalizerMidrange.js | 46 + .../device/attributes/equalizerMode.js | 39 + .../device/attributes/equalizerTreble.js | 46 + .../device/attributes/fanDirection.js | 105 + .../device/attributes/fanOscillate.js | 65 + .../smarthome/device/attributes/fanSpeed.js | 158 + .../smarthome/device/attributes/fireAlarm.js | 39 + .../device/attributes/heatingCoolingMode.js | 53 + .../device/attributes/heatingSetpoint.js | 53 + .../smarthome/device/attributes/humidity.js | 70 + .../smarthome/device/attributes/index.js | 93 + .../smarthome/device/attributes/input.js | 72 + .../smarthome/device/attributes/lockState.js | 39 + .../alexa/smarthome/device/attributes/mode.js | 61 + .../device/attributes/motionDetectionState.js | 39 + .../smarthome/device/attributes/muteState.js | 52 + .../smarthome/device/attributes/navigation.js | 39 + .../device/attributes/networkAccess.js | 39 + .../device/attributes/obstacleAlert.js | 39 + .../smarthome/device/attributes/openState.js | 118 + .../smarthome/device/attributes/percentage.js | 39 + .../smarthome/device/attributes/playback.js | 42 + .../device/attributes/playbackStop.js | 39 + .../device/attributes/positionState.js | 187 + .../smarthome/device/attributes/powerLevel.js | 39 + .../smarthome/device/attributes/powerState.js | 39 + .../smarthome/device/attributes/rangeValue.js | 77 + .../smarthome/device/attributes/readyAlert.js | 39 + .../device/attributes/safetyBeamAlert.js | 39 + .../smarthome/device/attributes/scene.js | 31 + .../device/attributes/targetTemperature.js | 52 + .../device/attributes/temperature.js | 59 + .../device/attributes/thermostatFan.js | 93 + .../device/attributes/thermostatHold.js | 39 + .../smarthome/device/attributes/tiltAngle.js | 182 + .../device/attributes/toggleState.js | 53 + .../device/attributes/troubleAlert.js | 39 + .../smarthome/device/attributes/vacuumMode.js | 173 + .../device/attributes/volumeLevel.js | 52 + .../smarthome/device/attributes/waterAlarm.js | 39 + .../smarthome/device/attributes/zonesAlert.js | 39 + lambda/alexa/smarthome/device/index.js | 133 + .../alexa/smarthome/device/types/activity.js | 39 + .../smarthome/device/types/airConditioner.js | 56 + .../smarthome/device/types/airFreshener.js | 39 + .../smarthome/device/types/airPurifier.js | 39 + .../smarthome/device/types/automobile.js | 48 + .../device/types/automobileAccessory.js | 48 + .../device/types/bluetoothSpeaker.js | 48 + lambda/alexa/smarthome/device/types/camera.js | 56 + .../smarthome/device/types/christmasTree.js | 39 + .../smarthome/device/types/coffeeMaker.js | 39 + .../alexa/smarthome/device/types/computer.js | 39 + .../smarthome/device/types/contactSensor.js | 56 + .../smarthome/device/types/dishwasher.js | 39 + lambda/alexa/smarthome/device/types/door.js | 56 + .../alexa/smarthome/device/types/doorbell.js | 39 + lambda/alexa/smarthome/device/types/dryer.js | 39 + .../smarthome/device/types/dummy.js} | 18 +- .../smarthome/device/types/entertainment.js | 56 + .../smarthome/device/types/exteriorBlind.js | 39 + lambda/alexa/smarthome/device/types/fan.js | 56 + .../smarthome/device/types/gameConsole.js | 39 + .../smarthome/device/types/garageDoor.js | 48 + .../smarthome/device/types/genericDevice.js | 39 + .../smarthome/device/types/headphones.js | 39 + lambda/alexa/smarthome/device/types/hub.js | 39 + lambda/alexa/smarthome/device/types/index.js | 84 + .../smarthome/device/types/interiorBlind.js | 56 + lambda/alexa/smarthome/device/types/laptop.js | 39 + lambda/alexa/smarthome/device/types/light.js | 56 + lambda/alexa/smarthome/device/types/lock.js | 56 + .../alexa/smarthome/device/types/microwave.js | 39 + .../smarthome/device/types/mobileDevice.js | 31 + .../smarthome/device/types/mobilePhone.js | 39 + .../smarthome/device/types/motionSensor.js | 56 + .../smarthome/device/types/musicSystem.js | 39 + .../smarthome/device/types/networkDevice.js | 40 + .../smarthome/device/types/networkHardware.js | 48 + lambda/alexa/smarthome/device/types/other.js | 39 + lambda/alexa/smarthome/device/types/outlet.js | 39 + lambda/alexa/smarthome/device/types/oven.js | 39 + lambda/alexa/smarthome/device/types/phone.js | 39 + .../alexa/smarthome/device/types/printer.js | 39 + lambda/alexa/smarthome/device/types/router.js | 39 + lambda/alexa/smarthome/device/types/scene.js | 56 + lambda/alexa/smarthome/device/types/screen.js | 39 + .../smarthome/device/types/securityPanel.js | 78 + .../smarthome/device/types/securitySystem.js | 39 + lambda/alexa/smarthome/device/types/sensor.js | 31 + .../smarthome/device/types/slowCooker.js | 39 + .../alexa/smarthome/device/types/speaker.js | 48 + .../smarthome/device/types/streamingDevice.js | 48 + lambda/alexa/smarthome/device/types/switch.js | 56 + lambda/alexa/smarthome/device/types/tablet.js | 39 + .../smarthome/device/types/television.js | 48 + .../device/types/temperatureSensor.js | 56 + .../smarthome/device/types/thermostat.js | 96 + lambda/alexa/smarthome/device/types/type.js | 68 + .../smarthome/device/types/vacuumCleaner.js | 56 + lambda/alexa/smarthome/device/types/washer.js | 39 + .../smarthome/device/types/waterHeater.js | 48 + .../alexa/smarthome/device/types/wearable.js | 39 + lambda/alexa/smarthome/directive.js | 148 + lambda/alexa/smarthome/endpoint.js | 548 +++ lambda/alexa/smarthome/errors.js | 639 ++++ lambda/alexa/smarthome/handlers/alexa.js | 76 + .../alexa/smarthome/handlers/authorization.js | 58 + .../handlers/brightnessController.js | 107 + .../handlers/cameraStreamController.js | 96 + .../smarthome/handlers/channelController.js | 125 + .../smarthome/handlers/colorController.js | 73 + .../handlers/colorTemperatureController.js | 158 + lambda/alexa/smarthome/handlers/discovery.js | 118 + .../smarthome/handlers/equalizerController.js | 173 + lambda/alexa/smarthome/handlers/handler.js | 35 + lambda/alexa/smarthome/handlers/index.js | 59 + .../smarthome/handlers/inputController.js | 75 + .../smarthome/handlers/keypadController.js | 75 + .../smarthome/handlers/lockController.js | 74 + .../smarthome/handlers/modeController.js | 129 + .../handlers/networkingAccessController.js | 66 + .../handlers/percentageController.js | 113 + .../smarthome/handlers/playbackController.js | 128 + .../smarthome/handlers/powerController.js | 81 + .../handlers/powerLevelController.js | 107 + .../smarthome/handlers/rangeController.js | 116 + lambda/alexa/smarthome/handlers/safety.js | 68 + .../smarthome/handlers/sceneController.js | 94 + .../handlers/securityPanelController.js | 181 + lambda/alexa/smarthome/handlers/speaker.js | 152 + .../alexa/smarthome/handlers/stepSpeaker.js | 86 + .../handlers/thermostatController.js | 321 ++ .../smarthome/handlers/toggleController.js | 81 + lambda/alexa/smarthome/index.js | 100 + lambda/alexa/smarthome/metadata.js | 226 ++ .../alexa/smarthome/properties/alarmState.js | 57 + .../alexa/smarthome/properties/alertState.js | 50 + lambda/alexa/smarthome/properties/armState.js | 196 + .../alexa/smarthome/properties/binaryState.js | 105 + .../alexa/smarthome/properties/brightness.js | 48 + .../smarthome/properties/cameraStream.js | 193 + lambda/alexa/smarthome/properties/channel.js | 80 + lambda/alexa/smarthome/properties/color.js | 45 + .../smarthome/properties/colorTemperature.js | 187 + .../smarthome/properties/connectedDevice.js | 109 + .../smarthome/properties/connectivity.js | 46 + .../smarthome/properties/decoupleState.js | 45 + .../smarthome/properties/detectionState.js | 42 + .../smarthome/properties/equalizerBands.js | 144 + .../smarthome/properties/equalizerMode.js | 148 + lambda/alexa/smarthome/properties/generic.js | 184 + lambda/alexa/smarthome/properties/index.js | 60 + lambda/alexa/smarthome/properties/input.js | 103 + .../alexa/smarthome/properties/keystroke.js | 205 ++ .../alexa/smarthome/properties/lockState.js | 134 + .../smarthome/properties/lowerSetpoint.js | 87 + lambda/alexa/smarthome/properties/mode.js | 209 ++ .../alexa/smarthome/properties/muteState.js | 71 + lambda/alexa/smarthome/properties/muteStep.js | 30 + .../smarthome/properties/networkAccess.js | 51 + .../alexa/smarthome/properties/percentage.js | 85 + lambda/alexa/smarthome/properties/playback.js | 157 + .../smarthome/properties/playbackAction.js | 157 + .../smarthome/properties/playbackStop.js | 84 + .../alexa/smarthome/properties/powerLevel.js | 43 + .../alexa/smarthome/properties/powerState.js | 110 + lambda/alexa/smarthome/properties/property.js | 328 ++ .../alexa/smarthome/properties/rangeValue.js | 229 ++ lambda/alexa/smarthome/properties/scene.js | 58 + .../smarthome/properties/securityAlert.js | 31 + .../smarthome/properties/targetSetpoint.js | 67 + .../alexa/smarthome/properties/temperature.js | 114 + .../smarthome/properties/thermostatHold.js | 79 + .../smarthome/properties/thermostatMode.js | 240 ++ .../alexa/smarthome/properties/toggleState.js | 229 ++ .../smarthome/properties/upperSetpoint.js | 31 + .../alexa/smarthome/properties/volumeLevel.js | 62 + .../alexa/smarthome/properties/volumeSteps.js | 39 + lambda/alexa/smarthome/resources.js | 164 + lambda/alexa/smarthome/response.js | 89 + lambda/alexa/smarthome/semantics.js | 188 + lambda/alexa/smarthome/unitOfMeasure.js | 510 +++ lambda/catalog.json | 658 ++++ lambda/config.js | 52 + lambda/index.js | 34 + lambda/log.js | 43 + lambda/openhab/constants.js | 145 + lambda/openhab/index.js | 271 ++ lambda/package-lock.json | 3149 +++++++++++++++++ lambda/package.json | 84 + lambda/smarthome/.eslintrc.json | 7 - lambda/smarthome/alexa/v2/ohConnector.js | 881 ----- lambda/smarthome/alexa/v3/capabilities.js | 566 --- lambda/smarthome/alexa/v3/config.js | 679 ---- lambda/smarthome/alexa/v3/directive.js | 193 - lambda/smarthome/alexa/v3/directives/alexa.js | 31 - .../alexa/v3/directives/authorization.js | 36 - .../v3/directives/brightnessController.js | 66 - .../v3/directives/cameraStreamController.js | 35 - .../alexa/v3/directives/channelController.js | 82 - .../alexa/v3/directives/colorController.js | 50 - .../directives/colorTemperatureController.js | 124 - .../alexa/v3/directives/discovery.js | 406 --- .../v3/directives/equalizerController.js | 105 - lambda/smarthome/alexa/v3/directives/index.js | 43 - .../alexa/v3/directives/inputController.js | 45 - .../alexa/v3/directives/lockController.js | 46 - .../alexa/v3/directives/modeController.js | 83 - .../v3/directives/percentageController.js | 66 - .../alexa/v3/directives/playbackController.js | 52 - .../alexa/v3/directives/powerController.js | 46 - .../v3/directives/powerLevelController.js | 66 - .../alexa/v3/directives/rangeController.js | 70 - .../alexa/v3/directives/sceneController.js | 58 - .../v3/directives/securityPanelController.js | 146 - .../smarthome/alexa/v3/directives/speaker.js | 81 - .../alexa/v3/directives/stepSpeaker.js | 59 - .../v3/directives/thermostatController.js | 267 -- .../alexa/v3/directives/toggleController.js | 47 - .../alexa/v3/directives/unsupported.js | 23 - lambda/smarthome/alexa/v3/ohConnector.js | 35 - lambda/smarthome/alexa/v3/propertyMap.js | 831 ----- lambda/smarthome/alexa/v3/propertyState.js | 251 -- lambda/smarthome/alexa/v3/response.js | 220 -- lambda/smarthome/config_sample.js | 40 - lambda/smarthome/index.js | 41 - lambda/smarthome/lib/log.js | 52 - lambda/smarthome/lib/rest.js | 239 -- lambda/smarthome/lib/utils.js | 35 - lambda/smarthome/package-lock.json | 1741 --------- lambda/smarthome/package.json | 50 - lambda/smarthome/test/common.js | 323 -- lambda/smarthome/test/mocha.opts | 3 - lambda/smarthome/test/settings.js | 179 - lambda/smarthome/test/test_ohConnectorV2.js | 117 - lambda/smarthome/test/test_ohConnectorV3.js | 122 - .../smarthome/test/v2/test_controllerAlexa.js | 39 - .../smarthome/test/v2/test_controllerColor.js | 56 - .../smarthome/test/v2/test_controllerLock.js | 76 - .../smarthome/test/v2/test_controllerOnOff.js | 69 - .../test/v2/test_controllerPercentage.js | 109 - .../test/v2/test_controllerTemperature.js | 221 -- .../test/v2/test_discoverLightColor.js | 38 - .../test/v2/test_discoverLightGroup.js | 73 - lambda/smarthome/test/v2/test_discoverLock.js | 34 - .../smarthome/test/v2/test_discoverOutlet.js | 34 - .../v2/test_discoverSwitchRollershutter.js | 35 - .../test/v2/test_discoverThermostat.js | 76 - .../smarthome/test/v3/test_controllerAlexa.js | 279 -- .../test/v3/test_controllerAuthorization.js | 50 - .../test/v3/test_controllerBrightness.js | 151 - .../test/v3/test_controllerChannel.js | 213 -- .../smarthome/test/v3/test_controllerColor.js | 66 - .../v3/test_controllerColorTemperature.js | 338 -- .../test/v3/test_controllerContactSensor.js | 58 - .../test/v3/test_controllerEqualizer.js | 366 -- .../smarthome/test/v3/test_controllerInput.js | 59 - .../smarthome/test/v3/test_controllerLock.js | 142 - .../smarthome/test/v3/test_controllerMode.js | 177 - .../test/v3/test_controllerMotionSensor.js | 58 - .../test/v3/test_controllerPercentage.js | 107 - .../test/v3/test_controllerPlayback.js | 51 - .../smarthome/test/v3/test_controllerPower.js | 179 - .../test/v3/test_controllerPowerLevel.js | 107 - .../smarthome/test/v3/test_controllerRange.js | 126 - .../smarthome/test/v3/test_controllerScene.js | 93 - .../test/v3/test_controllerSecurityPanel.js | 546 --- .../test/v3/test_controllerSpeaker.js | 152 - .../test/v3/test_controllerStepSpeaker.js | 135 - .../test/v3/test_controllerThermostatMode.js | 212 -- .../test_controllerThermostatTemperature.js | 999 ------ .../test/v3/test_controllerToggle.js | 60 - .../smarthome/test/v3/test_discoverBlind.js | 176 - lambda/smarthome/test/v3/test_discoverDoor.js | 70 - lambda/smarthome/test/v3/test_discoverFan.js | 178 - .../test/v3/test_discoverLightColor.js | 137 - .../v3/test_discoverLightColorTemperature.js | 78 - .../test/v3/test_discoverLightGroup.js | 81 - lambda/smarthome/test/v3/test_discoverLock.js | 35 - .../smarthome/test/v3/test_discoverOutlet.js | 35 - .../smarthome/test/v3/test_discoverRouter.js | 60 - .../smarthome/test/v3/test_discoverScene.js | 84 - .../test/v3/test_discoverSecurityPanel.js | 230 -- .../smarthome/test/v3/test_discoverSensor.js | 51 - .../smarthome/test/v3/test_discoverSpeaker.js | 186 - .../test/v3/test_discoverStepSpeaker.js | 76 - .../v3/test_discoverSwitchRollershutter.js | 58 - .../test/v3/test_discoverTelevision.js | 79 - .../test/v3/test_discoverThermostat.js | 579 --- .../smarthome/test/v3/test_discoverWasher.js | 296 -- lambda/{smarthome => }/test/.eslintrc.json | 0 lambda/test/alexa/cases/alexa.test.js | 1436 ++++++++ lambda/test/alexa/cases/authorization.test.js | 48 + .../alexa/cases/brightnessController.test.js | 235 ++ .../cases/cameraStreamController.test.js | 182 + .../alexa/cases/channelController.test.js | 329 ++ .../test/alexa/cases/colorController.test.js | 183 + .../cases/colorTemperatureController.test.js | 1149 ++++++ .../alexa/cases/discovery/activity.test.js | 41 + .../cases/discovery/airConditioner.test.js | 40 + .../cases/discovery/airFreshener.test.js | 104 + .../alexa/cases/discovery/airPurifier.test.js | 35 + .../alexa/cases/discovery/automobile.test.js | 106 + .../discovery/automobileAccessory.test.js | 133 + .../test/alexa/cases/discovery/blind.test.js | 1015 ++++++ .../cases/discovery/bluetoothSpeaker.test.js | 35 + .../test/alexa/cases/discovery/camera.test.js | 103 + .../cases/discovery/christmasTree.test.js | 40 + .../alexa/cases/discovery/coffeeMaker.test.js | 35 + .../alexa/cases/discovery/computer.test.js | 125 + .../cases/discovery/contactSensor.test.js | 65 + .../alexa/cases/discovery/dishwasher.test.js | 35 + .../test/alexa/cases/discovery/door.test.js | 563 +++ .../alexa/cases/discovery/doorbell.test.js | 57 + .../test/alexa/cases/discovery/dryer.test.js | 35 + lambda/test/alexa/cases/discovery/fan.test.js | 704 ++++ .../alexa/cases/discovery/gameConsole.test.js | 35 + .../alexa/cases/discovery/headphones.test.js | 73 + lambda/test/alexa/cases/discovery/hub.test.js | 35 + .../test/alexa/cases/discovery/laptop.test.js | 35 + .../test/alexa/cases/discovery/light.test.js | 414 +++ .../test/alexa/cases/discovery/lock.test.js | 105 + .../alexa/cases/discovery/microwave.test.js | 232 ++ .../alexa/cases/discovery/mobilePhone.test.js | 35 + .../cases/discovery/motionSensor.test.js | 65 + .../alexa/cases/discovery/musicSystem.test.js | 35 + .../cases/discovery/networkHardware.test.js | 35 + .../test/alexa/cases/discovery/other.test.js | 908 +++++ .../test/alexa/cases/discovery/outlet.test.js | 35 + .../test/alexa/cases/discovery/oven.test.js | 35 + .../test/alexa/cases/discovery/phone.test.js | 35 + .../alexa/cases/discovery/printer.test.js | 35 + .../test/alexa/cases/discovery/router.test.js | 80 + .../test/alexa/cases/discovery/scene.test.js | 56 + .../test/alexa/cases/discovery/screen.test.js | 35 + .../cases/discovery/securityPanel.test.js | 329 ++ .../cases/discovery/securitySystem.test.js | 53 + .../alexa/cases/discovery/shutter.test.js | 201 ++ .../alexa/cases/discovery/slowCooker.test.js | 35 + .../alexa/cases/discovery/speaker.test.js | 288 ++ .../alexa/cases/discovery/stepSpeaker.test.js | 101 + .../cases/discovery/streamingDevice.test.js | 165 + .../test/alexa/cases/discovery/switch.test.js | 127 + .../test/alexa/cases/discovery/tablet.test.js | 35 + .../alexa/cases/discovery/television.test.js | 263 ++ .../cases/discovery/temperatureSensor.test.js | 135 + .../alexa/cases/discovery/thermostat.test.js | 798 +++++ .../cases/discovery/vacuumCleaner.test.js | 377 ++ .../test/alexa/cases/discovery/washer.test.js | 409 +++ .../alexa/cases/discovery/waterHeater.test.js | 70 + .../alexa/cases/discovery/wearable.test.js | 135 + .../alexa/cases/equalizerController.test.js | 571 +++ lambda/test/alexa/cases/index.js | 97 + .../test/alexa/cases/inputController.test.js | 100 + .../test/alexa/cases/keypadController.test.js | 93 + .../test/alexa/cases/lockController.test.js | 387 ++ .../test/alexa/cases/modeController.test.js | 575 +++ .../cases/networkingAccessController.test.js | 187 + .../alexa/cases/percentageController.test.js | 284 ++ .../alexa/cases/playbackController.test.js | 211 ++ .../test/alexa/cases/powerController.test.js | 350 ++ .../alexa/cases/powerLevelController.test.js | 189 + .../test/alexa/cases/rangeController.test.js | 376 ++ .../test/alexa/cases/sceneController.test.js | 97 + .../cases/securityPanelController.test.js | 809 +++++ lambda/test/alexa/cases/speaker.test.js | 552 +++ lambda/test/alexa/cases/stepSpeaker.test.js | 254 ++ .../cases/thermostatControllerMode.test.js | 502 +++ .../thermostatControllerTemperature.test.js | 1668 +++++++++ .../test/alexa/cases/toggleController.test.js | 251 ++ lambda/test/alexa/chai.js | 251 ++ .../alexa_smart_home_message_schema.json | 3049 +++++++++++----- lambda/test/alexa/smarthome.test.js | 132 + lambda/test/openhab.test.js | 391 ++ lambda/test/skill.test.js | 74 + lambda/test/utils.test.js | 90 + lambda/utils.js | 78 + resources/locales/de/catalog.json | 4 +- resources/locales/de/manifest.json | 4 +- resources/locales/en/catalog.json | 31 +- resources/locales/en/manifest.json | 10 +- resources/locales/es/catalog.json | 4 +- resources/locales/es/manifest.json | 4 +- resources/locales/fr/catalog.json | 4 +- resources/locales/fr/manifest.json | 4 +- resources/locales/hi/catalog.json | 4 +- resources/locales/hi/manifest.json | 4 +- resources/locales/it/catalog.json | 4 +- resources/locales/it/manifest.json | 4 +- resources/locales/ja/catalog.json | 4 +- resources/locales/ja/manifest.json | 4 +- resources/locales/pt/catalog.json | 4 +- resources/locales/pt/manifest.json | 4 +- .../assets/images/openhab_largeIcon.png | Bin .../assets/images/openhab_smallIcon.png | Bin skill-package/skill.json | 522 +++ skill.json | 37 - tools/generateProdConfig.js | 156 + tools/updateSkillCatalog.js | 90 - tools/updateSkillLocale.js | 143 + tools/updateSkillManifest.js | 149 - 472 files changed, 51192 insertions(+), 19321 deletions(-) delete mode 100644 .ask/config delete mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/doc.yml create mode 100644 .github/workflows/locale.yml create mode 100644 .markdownlint.yml create mode 100644 ask-resources.json delete mode 100755 hooks/post_new_hook.ps1 delete mode 100755 hooks/post_new_hook.sh delete mode 100755 hooks/pre_deploy_hook.ps1 delete mode 100755 hooks/pre_deploy_hook.sh create mode 100644 infrastructure/cfn-deployer/skill-stack.yml create mode 100644 lambda/.eslintrc.json create mode 100644 lambda/alexa/smarthome/capabilities/alexa.js create mode 100644 lambda/alexa/smarthome/capabilities/brightnessController.js create mode 100644 lambda/alexa/smarthome/capabilities/cameraStreamController.js create mode 100644 lambda/alexa/smarthome/capabilities/capability.js create mode 100644 lambda/alexa/smarthome/capabilities/channelController.js create mode 100644 lambda/alexa/smarthome/capabilities/colorController.js create mode 100644 lambda/alexa/smarthome/capabilities/colorTemperatureController.js create mode 100644 lambda/alexa/smarthome/capabilities/contactSensor.js create mode 100644 lambda/alexa/smarthome/capabilities/endpointHealth.js create mode 100644 lambda/alexa/smarthome/capabilities/equalizerController.js create mode 100644 lambda/alexa/smarthome/capabilities/index.js create mode 100644 lambda/alexa/smarthome/capabilities/inputController.js create mode 100644 lambda/alexa/smarthome/capabilities/keypadController.js create mode 100644 lambda/alexa/smarthome/capabilities/lockController.js create mode 100644 lambda/alexa/smarthome/capabilities/modeController.js create mode 100644 lambda/alexa/smarthome/capabilities/motionSensor.js create mode 100644 lambda/alexa/smarthome/capabilities/networkingAccessController.js create mode 100644 lambda/alexa/smarthome/capabilities/networkingConnectedDevice.js create mode 100644 lambda/alexa/smarthome/capabilities/networkingHomeNetworkController.js create mode 100644 lambda/alexa/smarthome/capabilities/percentageController.js create mode 100644 lambda/alexa/smarthome/capabilities/playbackController.js create mode 100644 lambda/alexa/smarthome/capabilities/powerController.js create mode 100644 lambda/alexa/smarthome/capabilities/powerLevelController.js create mode 100644 lambda/alexa/smarthome/capabilities/rangeController.js create mode 100644 lambda/alexa/smarthome/capabilities/safety.js create mode 100644 lambda/alexa/smarthome/capabilities/sceneController.js create mode 100644 lambda/alexa/smarthome/capabilities/securityPanelController.js create mode 100644 lambda/alexa/smarthome/capabilities/speaker.js create mode 100644 lambda/alexa/smarthome/capabilities/stepSpeaker.js create mode 100644 lambda/alexa/smarthome/capabilities/temperatureSensor.js create mode 100644 lambda/alexa/smarthome/capabilities/thermostatController.js create mode 100644 lambda/alexa/smarthome/capabilities/toggleController.js create mode 100644 lambda/alexa/smarthome/catalog.js create mode 100644 lambda/alexa/smarthome/category.js create mode 100644 lambda/alexa/smarthome/constants.js create mode 100644 lambda/alexa/smarthome/device/attributes/alarmAlert.js create mode 100644 lambda/alexa/smarthome/device/attributes/armState.js create mode 100644 lambda/alexa/smarthome/device/attributes/attribute.js create mode 100644 lambda/alexa/smarthome/device/attributes/batteryLevel.js create mode 100644 lambda/alexa/smarthome/device/attributes/brightness.js create mode 100644 lambda/alexa/smarthome/device/attributes/burglaryAlarm.js create mode 100644 lambda/alexa/smarthome/device/attributes/cameraStream.js create mode 100644 lambda/alexa/smarthome/device/attributes/carbonMonoxideAlarm.js create mode 100644 lambda/alexa/smarthome/device/attributes/channel.js create mode 100644 lambda/alexa/smarthome/device/attributes/color.js create mode 100644 lambda/alexa/smarthome/device/attributes/colorTemperature.js create mode 100644 lambda/alexa/smarthome/device/attributes/contactDetectionState.js create mode 100644 lambda/alexa/smarthome/device/attributes/coolingSetpoint.js create mode 100644 lambda/alexa/smarthome/device/attributes/currentLockState.js create mode 100644 lambda/alexa/smarthome/device/attributes/currentOpenState.js create mode 100644 lambda/alexa/smarthome/device/attributes/ecoCoolingSetpoint.js create mode 100644 lambda/alexa/smarthome/device/attributes/ecoHeatingSetpoint.js create mode 100644 lambda/alexa/smarthome/device/attributes/equalizerBass.js create mode 100644 lambda/alexa/smarthome/device/attributes/equalizerMidrange.js create mode 100644 lambda/alexa/smarthome/device/attributes/equalizerMode.js create mode 100644 lambda/alexa/smarthome/device/attributes/equalizerTreble.js create mode 100644 lambda/alexa/smarthome/device/attributes/fanDirection.js create mode 100644 lambda/alexa/smarthome/device/attributes/fanOscillate.js create mode 100644 lambda/alexa/smarthome/device/attributes/fanSpeed.js create mode 100644 lambda/alexa/smarthome/device/attributes/fireAlarm.js create mode 100644 lambda/alexa/smarthome/device/attributes/heatingCoolingMode.js create mode 100644 lambda/alexa/smarthome/device/attributes/heatingSetpoint.js create mode 100644 lambda/alexa/smarthome/device/attributes/humidity.js create mode 100644 lambda/alexa/smarthome/device/attributes/index.js create mode 100644 lambda/alexa/smarthome/device/attributes/input.js create mode 100644 lambda/alexa/smarthome/device/attributes/lockState.js create mode 100644 lambda/alexa/smarthome/device/attributes/mode.js create mode 100644 lambda/alexa/smarthome/device/attributes/motionDetectionState.js create mode 100644 lambda/alexa/smarthome/device/attributes/muteState.js create mode 100644 lambda/alexa/smarthome/device/attributes/navigation.js create mode 100644 lambda/alexa/smarthome/device/attributes/networkAccess.js create mode 100644 lambda/alexa/smarthome/device/attributes/obstacleAlert.js create mode 100644 lambda/alexa/smarthome/device/attributes/openState.js create mode 100644 lambda/alexa/smarthome/device/attributes/percentage.js create mode 100644 lambda/alexa/smarthome/device/attributes/playback.js create mode 100644 lambda/alexa/smarthome/device/attributes/playbackStop.js create mode 100644 lambda/alexa/smarthome/device/attributes/positionState.js create mode 100644 lambda/alexa/smarthome/device/attributes/powerLevel.js create mode 100644 lambda/alexa/smarthome/device/attributes/powerState.js create mode 100644 lambda/alexa/smarthome/device/attributes/rangeValue.js create mode 100644 lambda/alexa/smarthome/device/attributes/readyAlert.js create mode 100644 lambda/alexa/smarthome/device/attributes/safetyBeamAlert.js create mode 100644 lambda/alexa/smarthome/device/attributes/scene.js create mode 100644 lambda/alexa/smarthome/device/attributes/targetTemperature.js create mode 100644 lambda/alexa/smarthome/device/attributes/temperature.js create mode 100644 lambda/alexa/smarthome/device/attributes/thermostatFan.js create mode 100644 lambda/alexa/smarthome/device/attributes/thermostatHold.js create mode 100644 lambda/alexa/smarthome/device/attributes/tiltAngle.js create mode 100644 lambda/alexa/smarthome/device/attributes/toggleState.js create mode 100644 lambda/alexa/smarthome/device/attributes/troubleAlert.js create mode 100644 lambda/alexa/smarthome/device/attributes/vacuumMode.js create mode 100644 lambda/alexa/smarthome/device/attributes/volumeLevel.js create mode 100644 lambda/alexa/smarthome/device/attributes/waterAlarm.js create mode 100644 lambda/alexa/smarthome/device/attributes/zonesAlert.js create mode 100644 lambda/alexa/smarthome/device/index.js create mode 100644 lambda/alexa/smarthome/device/types/activity.js create mode 100644 lambda/alexa/smarthome/device/types/airConditioner.js create mode 100644 lambda/alexa/smarthome/device/types/airFreshener.js create mode 100644 lambda/alexa/smarthome/device/types/airPurifier.js create mode 100644 lambda/alexa/smarthome/device/types/automobile.js create mode 100644 lambda/alexa/smarthome/device/types/automobileAccessory.js create mode 100644 lambda/alexa/smarthome/device/types/bluetoothSpeaker.js create mode 100644 lambda/alexa/smarthome/device/types/camera.js create mode 100644 lambda/alexa/smarthome/device/types/christmasTree.js create mode 100644 lambda/alexa/smarthome/device/types/coffeeMaker.js create mode 100644 lambda/alexa/smarthome/device/types/computer.js create mode 100644 lambda/alexa/smarthome/device/types/contactSensor.js create mode 100644 lambda/alexa/smarthome/device/types/dishwasher.js create mode 100644 lambda/alexa/smarthome/device/types/door.js create mode 100644 lambda/alexa/smarthome/device/types/doorbell.js create mode 100644 lambda/alexa/smarthome/device/types/dryer.js rename lambda/{smarthome/lib/catalog.js => alexa/smarthome/device/types/dummy.js} (56%) create mode 100644 lambda/alexa/smarthome/device/types/entertainment.js create mode 100644 lambda/alexa/smarthome/device/types/exteriorBlind.js create mode 100644 lambda/alexa/smarthome/device/types/fan.js create mode 100644 lambda/alexa/smarthome/device/types/gameConsole.js create mode 100644 lambda/alexa/smarthome/device/types/garageDoor.js create mode 100644 lambda/alexa/smarthome/device/types/genericDevice.js create mode 100644 lambda/alexa/smarthome/device/types/headphones.js create mode 100644 lambda/alexa/smarthome/device/types/hub.js create mode 100644 lambda/alexa/smarthome/device/types/index.js create mode 100644 lambda/alexa/smarthome/device/types/interiorBlind.js create mode 100644 lambda/alexa/smarthome/device/types/laptop.js create mode 100644 lambda/alexa/smarthome/device/types/light.js create mode 100644 lambda/alexa/smarthome/device/types/lock.js create mode 100644 lambda/alexa/smarthome/device/types/microwave.js create mode 100644 lambda/alexa/smarthome/device/types/mobileDevice.js create mode 100644 lambda/alexa/smarthome/device/types/mobilePhone.js create mode 100644 lambda/alexa/smarthome/device/types/motionSensor.js create mode 100644 lambda/alexa/smarthome/device/types/musicSystem.js create mode 100644 lambda/alexa/smarthome/device/types/networkDevice.js create mode 100644 lambda/alexa/smarthome/device/types/networkHardware.js create mode 100644 lambda/alexa/smarthome/device/types/other.js create mode 100644 lambda/alexa/smarthome/device/types/outlet.js create mode 100644 lambda/alexa/smarthome/device/types/oven.js create mode 100644 lambda/alexa/smarthome/device/types/phone.js create mode 100644 lambda/alexa/smarthome/device/types/printer.js create mode 100644 lambda/alexa/smarthome/device/types/router.js create mode 100644 lambda/alexa/smarthome/device/types/scene.js create mode 100644 lambda/alexa/smarthome/device/types/screen.js create mode 100644 lambda/alexa/smarthome/device/types/securityPanel.js create mode 100644 lambda/alexa/smarthome/device/types/securitySystem.js create mode 100644 lambda/alexa/smarthome/device/types/sensor.js create mode 100644 lambda/alexa/smarthome/device/types/slowCooker.js create mode 100644 lambda/alexa/smarthome/device/types/speaker.js create mode 100644 lambda/alexa/smarthome/device/types/streamingDevice.js create mode 100644 lambda/alexa/smarthome/device/types/switch.js create mode 100644 lambda/alexa/smarthome/device/types/tablet.js create mode 100644 lambda/alexa/smarthome/device/types/television.js create mode 100644 lambda/alexa/smarthome/device/types/temperatureSensor.js create mode 100644 lambda/alexa/smarthome/device/types/thermostat.js create mode 100644 lambda/alexa/smarthome/device/types/type.js create mode 100644 lambda/alexa/smarthome/device/types/vacuumCleaner.js create mode 100644 lambda/alexa/smarthome/device/types/washer.js create mode 100644 lambda/alexa/smarthome/device/types/waterHeater.js create mode 100644 lambda/alexa/smarthome/device/types/wearable.js create mode 100644 lambda/alexa/smarthome/directive.js create mode 100644 lambda/alexa/smarthome/endpoint.js create mode 100644 lambda/alexa/smarthome/errors.js create mode 100644 lambda/alexa/smarthome/handlers/alexa.js create mode 100644 lambda/alexa/smarthome/handlers/authorization.js create mode 100644 lambda/alexa/smarthome/handlers/brightnessController.js create mode 100644 lambda/alexa/smarthome/handlers/cameraStreamController.js create mode 100644 lambda/alexa/smarthome/handlers/channelController.js create mode 100644 lambda/alexa/smarthome/handlers/colorController.js create mode 100644 lambda/alexa/smarthome/handlers/colorTemperatureController.js create mode 100644 lambda/alexa/smarthome/handlers/discovery.js create mode 100644 lambda/alexa/smarthome/handlers/equalizerController.js create mode 100644 lambda/alexa/smarthome/handlers/handler.js create mode 100644 lambda/alexa/smarthome/handlers/index.js create mode 100644 lambda/alexa/smarthome/handlers/inputController.js create mode 100644 lambda/alexa/smarthome/handlers/keypadController.js create mode 100644 lambda/alexa/smarthome/handlers/lockController.js create mode 100644 lambda/alexa/smarthome/handlers/modeController.js create mode 100644 lambda/alexa/smarthome/handlers/networkingAccessController.js create mode 100644 lambda/alexa/smarthome/handlers/percentageController.js create mode 100644 lambda/alexa/smarthome/handlers/playbackController.js create mode 100644 lambda/alexa/smarthome/handlers/powerController.js create mode 100644 lambda/alexa/smarthome/handlers/powerLevelController.js create mode 100644 lambda/alexa/smarthome/handlers/rangeController.js create mode 100644 lambda/alexa/smarthome/handlers/safety.js create mode 100644 lambda/alexa/smarthome/handlers/sceneController.js create mode 100644 lambda/alexa/smarthome/handlers/securityPanelController.js create mode 100644 lambda/alexa/smarthome/handlers/speaker.js create mode 100644 lambda/alexa/smarthome/handlers/stepSpeaker.js create mode 100644 lambda/alexa/smarthome/handlers/thermostatController.js create mode 100644 lambda/alexa/smarthome/handlers/toggleController.js create mode 100644 lambda/alexa/smarthome/index.js create mode 100644 lambda/alexa/smarthome/metadata.js create mode 100644 lambda/alexa/smarthome/properties/alarmState.js create mode 100644 lambda/alexa/smarthome/properties/alertState.js create mode 100644 lambda/alexa/smarthome/properties/armState.js create mode 100644 lambda/alexa/smarthome/properties/binaryState.js create mode 100644 lambda/alexa/smarthome/properties/brightness.js create mode 100644 lambda/alexa/smarthome/properties/cameraStream.js create mode 100644 lambda/alexa/smarthome/properties/channel.js create mode 100644 lambda/alexa/smarthome/properties/color.js create mode 100644 lambda/alexa/smarthome/properties/colorTemperature.js create mode 100644 lambda/alexa/smarthome/properties/connectedDevice.js create mode 100644 lambda/alexa/smarthome/properties/connectivity.js create mode 100644 lambda/alexa/smarthome/properties/decoupleState.js create mode 100644 lambda/alexa/smarthome/properties/detectionState.js create mode 100644 lambda/alexa/smarthome/properties/equalizerBands.js create mode 100644 lambda/alexa/smarthome/properties/equalizerMode.js create mode 100644 lambda/alexa/smarthome/properties/generic.js create mode 100644 lambda/alexa/smarthome/properties/index.js create mode 100644 lambda/alexa/smarthome/properties/input.js create mode 100644 lambda/alexa/smarthome/properties/keystroke.js create mode 100644 lambda/alexa/smarthome/properties/lockState.js create mode 100644 lambda/alexa/smarthome/properties/lowerSetpoint.js create mode 100644 lambda/alexa/smarthome/properties/mode.js create mode 100644 lambda/alexa/smarthome/properties/muteState.js create mode 100644 lambda/alexa/smarthome/properties/muteStep.js create mode 100644 lambda/alexa/smarthome/properties/networkAccess.js create mode 100644 lambda/alexa/smarthome/properties/percentage.js create mode 100644 lambda/alexa/smarthome/properties/playback.js create mode 100644 lambda/alexa/smarthome/properties/playbackAction.js create mode 100644 lambda/alexa/smarthome/properties/playbackStop.js create mode 100644 lambda/alexa/smarthome/properties/powerLevel.js create mode 100644 lambda/alexa/smarthome/properties/powerState.js create mode 100644 lambda/alexa/smarthome/properties/property.js create mode 100644 lambda/alexa/smarthome/properties/rangeValue.js create mode 100644 lambda/alexa/smarthome/properties/scene.js create mode 100644 lambda/alexa/smarthome/properties/securityAlert.js create mode 100644 lambda/alexa/smarthome/properties/targetSetpoint.js create mode 100644 lambda/alexa/smarthome/properties/temperature.js create mode 100644 lambda/alexa/smarthome/properties/thermostatHold.js create mode 100644 lambda/alexa/smarthome/properties/thermostatMode.js create mode 100644 lambda/alexa/smarthome/properties/toggleState.js create mode 100644 lambda/alexa/smarthome/properties/upperSetpoint.js create mode 100644 lambda/alexa/smarthome/properties/volumeLevel.js create mode 100644 lambda/alexa/smarthome/properties/volumeSteps.js create mode 100644 lambda/alexa/smarthome/resources.js create mode 100644 lambda/alexa/smarthome/response.js create mode 100644 lambda/alexa/smarthome/semantics.js create mode 100644 lambda/alexa/smarthome/unitOfMeasure.js create mode 100644 lambda/catalog.json create mode 100644 lambda/config.js create mode 100644 lambda/index.js create mode 100644 lambda/log.js create mode 100644 lambda/openhab/constants.js create mode 100644 lambda/openhab/index.js create mode 100644 lambda/package-lock.json create mode 100644 lambda/package.json delete mode 100644 lambda/smarthome/.eslintrc.json delete mode 100644 lambda/smarthome/alexa/v2/ohConnector.js delete mode 100644 lambda/smarthome/alexa/v3/capabilities.js delete mode 100644 lambda/smarthome/alexa/v3/config.js delete mode 100644 lambda/smarthome/alexa/v3/directive.js delete mode 100644 lambda/smarthome/alexa/v3/directives/alexa.js delete mode 100644 lambda/smarthome/alexa/v3/directives/authorization.js delete mode 100644 lambda/smarthome/alexa/v3/directives/brightnessController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/cameraStreamController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/channelController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/colorController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/colorTemperatureController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/discovery.js delete mode 100644 lambda/smarthome/alexa/v3/directives/equalizerController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/index.js delete mode 100644 lambda/smarthome/alexa/v3/directives/inputController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/lockController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/modeController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/percentageController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/playbackController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/powerController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/powerLevelController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/rangeController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/sceneController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/securityPanelController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/speaker.js delete mode 100644 lambda/smarthome/alexa/v3/directives/stepSpeaker.js delete mode 100644 lambda/smarthome/alexa/v3/directives/thermostatController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/toggleController.js delete mode 100644 lambda/smarthome/alexa/v3/directives/unsupported.js delete mode 100644 lambda/smarthome/alexa/v3/ohConnector.js delete mode 100644 lambda/smarthome/alexa/v3/propertyMap.js delete mode 100644 lambda/smarthome/alexa/v3/propertyState.js delete mode 100644 lambda/smarthome/alexa/v3/response.js delete mode 100644 lambda/smarthome/config_sample.js delete mode 100644 lambda/smarthome/index.js delete mode 100644 lambda/smarthome/lib/log.js delete mode 100644 lambda/smarthome/lib/rest.js delete mode 100644 lambda/smarthome/lib/utils.js delete mode 100644 lambda/smarthome/package-lock.json delete mode 100644 lambda/smarthome/package.json delete mode 100644 lambda/smarthome/test/common.js delete mode 100644 lambda/smarthome/test/mocha.opts delete mode 100644 lambda/smarthome/test/settings.js delete mode 100644 lambda/smarthome/test/test_ohConnectorV2.js delete mode 100644 lambda/smarthome/test/test_ohConnectorV3.js delete mode 100644 lambda/smarthome/test/v2/test_controllerAlexa.js delete mode 100644 lambda/smarthome/test/v2/test_controllerColor.js delete mode 100644 lambda/smarthome/test/v2/test_controllerLock.js delete mode 100644 lambda/smarthome/test/v2/test_controllerOnOff.js delete mode 100644 lambda/smarthome/test/v2/test_controllerPercentage.js delete mode 100644 lambda/smarthome/test/v2/test_controllerTemperature.js delete mode 100644 lambda/smarthome/test/v2/test_discoverLightColor.js delete mode 100644 lambda/smarthome/test/v2/test_discoverLightGroup.js delete mode 100644 lambda/smarthome/test/v2/test_discoverLock.js delete mode 100644 lambda/smarthome/test/v2/test_discoverOutlet.js delete mode 100644 lambda/smarthome/test/v2/test_discoverSwitchRollershutter.js delete mode 100644 lambda/smarthome/test/v2/test_discoverThermostat.js delete mode 100644 lambda/smarthome/test/v3/test_controllerAlexa.js delete mode 100644 lambda/smarthome/test/v3/test_controllerAuthorization.js delete mode 100644 lambda/smarthome/test/v3/test_controllerBrightness.js delete mode 100644 lambda/smarthome/test/v3/test_controllerChannel.js delete mode 100644 lambda/smarthome/test/v3/test_controllerColor.js delete mode 100644 lambda/smarthome/test/v3/test_controllerColorTemperature.js delete mode 100644 lambda/smarthome/test/v3/test_controllerContactSensor.js delete mode 100644 lambda/smarthome/test/v3/test_controllerEqualizer.js delete mode 100644 lambda/smarthome/test/v3/test_controllerInput.js delete mode 100644 lambda/smarthome/test/v3/test_controllerLock.js delete mode 100644 lambda/smarthome/test/v3/test_controllerMode.js delete mode 100644 lambda/smarthome/test/v3/test_controllerMotionSensor.js delete mode 100644 lambda/smarthome/test/v3/test_controllerPercentage.js delete mode 100644 lambda/smarthome/test/v3/test_controllerPlayback.js delete mode 100644 lambda/smarthome/test/v3/test_controllerPower.js delete mode 100644 lambda/smarthome/test/v3/test_controllerPowerLevel.js delete mode 100644 lambda/smarthome/test/v3/test_controllerRange.js delete mode 100644 lambda/smarthome/test/v3/test_controllerScene.js delete mode 100644 lambda/smarthome/test/v3/test_controllerSecurityPanel.js delete mode 100644 lambda/smarthome/test/v3/test_controllerSpeaker.js delete mode 100644 lambda/smarthome/test/v3/test_controllerStepSpeaker.js delete mode 100644 lambda/smarthome/test/v3/test_controllerThermostatMode.js delete mode 100644 lambda/smarthome/test/v3/test_controllerThermostatTemperature.js delete mode 100644 lambda/smarthome/test/v3/test_controllerToggle.js delete mode 100644 lambda/smarthome/test/v3/test_discoverBlind.js delete mode 100644 lambda/smarthome/test/v3/test_discoverDoor.js delete mode 100644 lambda/smarthome/test/v3/test_discoverFan.js delete mode 100644 lambda/smarthome/test/v3/test_discoverLightColor.js delete mode 100644 lambda/smarthome/test/v3/test_discoverLightColorTemperature.js delete mode 100644 lambda/smarthome/test/v3/test_discoverLightGroup.js delete mode 100644 lambda/smarthome/test/v3/test_discoverLock.js delete mode 100644 lambda/smarthome/test/v3/test_discoverOutlet.js delete mode 100644 lambda/smarthome/test/v3/test_discoverRouter.js delete mode 100644 lambda/smarthome/test/v3/test_discoverScene.js delete mode 100644 lambda/smarthome/test/v3/test_discoverSecurityPanel.js delete mode 100644 lambda/smarthome/test/v3/test_discoverSensor.js delete mode 100644 lambda/smarthome/test/v3/test_discoverSpeaker.js delete mode 100644 lambda/smarthome/test/v3/test_discoverStepSpeaker.js delete mode 100644 lambda/smarthome/test/v3/test_discoverSwitchRollershutter.js delete mode 100644 lambda/smarthome/test/v3/test_discoverTelevision.js delete mode 100644 lambda/smarthome/test/v3/test_discoverThermostat.js delete mode 100644 lambda/smarthome/test/v3/test_discoverWasher.js rename lambda/{smarthome => }/test/.eslintrc.json (100%) create mode 100644 lambda/test/alexa/cases/alexa.test.js create mode 100644 lambda/test/alexa/cases/authorization.test.js create mode 100644 lambda/test/alexa/cases/brightnessController.test.js create mode 100644 lambda/test/alexa/cases/cameraStreamController.test.js create mode 100644 lambda/test/alexa/cases/channelController.test.js create mode 100644 lambda/test/alexa/cases/colorController.test.js create mode 100644 lambda/test/alexa/cases/colorTemperatureController.test.js create mode 100644 lambda/test/alexa/cases/discovery/activity.test.js create mode 100644 lambda/test/alexa/cases/discovery/airConditioner.test.js create mode 100644 lambda/test/alexa/cases/discovery/airFreshener.test.js create mode 100644 lambda/test/alexa/cases/discovery/airPurifier.test.js create mode 100644 lambda/test/alexa/cases/discovery/automobile.test.js create mode 100644 lambda/test/alexa/cases/discovery/automobileAccessory.test.js create mode 100644 lambda/test/alexa/cases/discovery/blind.test.js create mode 100644 lambda/test/alexa/cases/discovery/bluetoothSpeaker.test.js create mode 100644 lambda/test/alexa/cases/discovery/camera.test.js create mode 100644 lambda/test/alexa/cases/discovery/christmasTree.test.js create mode 100644 lambda/test/alexa/cases/discovery/coffeeMaker.test.js create mode 100644 lambda/test/alexa/cases/discovery/computer.test.js create mode 100644 lambda/test/alexa/cases/discovery/contactSensor.test.js create mode 100644 lambda/test/alexa/cases/discovery/dishwasher.test.js create mode 100644 lambda/test/alexa/cases/discovery/door.test.js create mode 100644 lambda/test/alexa/cases/discovery/doorbell.test.js create mode 100644 lambda/test/alexa/cases/discovery/dryer.test.js create mode 100644 lambda/test/alexa/cases/discovery/fan.test.js create mode 100644 lambda/test/alexa/cases/discovery/gameConsole.test.js create mode 100644 lambda/test/alexa/cases/discovery/headphones.test.js create mode 100644 lambda/test/alexa/cases/discovery/hub.test.js create mode 100644 lambda/test/alexa/cases/discovery/laptop.test.js create mode 100644 lambda/test/alexa/cases/discovery/light.test.js create mode 100644 lambda/test/alexa/cases/discovery/lock.test.js create mode 100644 lambda/test/alexa/cases/discovery/microwave.test.js create mode 100644 lambda/test/alexa/cases/discovery/mobilePhone.test.js create mode 100644 lambda/test/alexa/cases/discovery/motionSensor.test.js create mode 100644 lambda/test/alexa/cases/discovery/musicSystem.test.js create mode 100644 lambda/test/alexa/cases/discovery/networkHardware.test.js create mode 100644 lambda/test/alexa/cases/discovery/other.test.js create mode 100644 lambda/test/alexa/cases/discovery/outlet.test.js create mode 100644 lambda/test/alexa/cases/discovery/oven.test.js create mode 100644 lambda/test/alexa/cases/discovery/phone.test.js create mode 100644 lambda/test/alexa/cases/discovery/printer.test.js create mode 100644 lambda/test/alexa/cases/discovery/router.test.js create mode 100644 lambda/test/alexa/cases/discovery/scene.test.js create mode 100644 lambda/test/alexa/cases/discovery/screen.test.js create mode 100644 lambda/test/alexa/cases/discovery/securityPanel.test.js create mode 100644 lambda/test/alexa/cases/discovery/securitySystem.test.js create mode 100644 lambda/test/alexa/cases/discovery/shutter.test.js create mode 100644 lambda/test/alexa/cases/discovery/slowCooker.test.js create mode 100644 lambda/test/alexa/cases/discovery/speaker.test.js create mode 100644 lambda/test/alexa/cases/discovery/stepSpeaker.test.js create mode 100644 lambda/test/alexa/cases/discovery/streamingDevice.test.js create mode 100644 lambda/test/alexa/cases/discovery/switch.test.js create mode 100644 lambda/test/alexa/cases/discovery/tablet.test.js create mode 100644 lambda/test/alexa/cases/discovery/television.test.js create mode 100644 lambda/test/alexa/cases/discovery/temperatureSensor.test.js create mode 100644 lambda/test/alexa/cases/discovery/thermostat.test.js create mode 100644 lambda/test/alexa/cases/discovery/vacuumCleaner.test.js create mode 100644 lambda/test/alexa/cases/discovery/washer.test.js create mode 100644 lambda/test/alexa/cases/discovery/waterHeater.test.js create mode 100644 lambda/test/alexa/cases/discovery/wearable.test.js create mode 100644 lambda/test/alexa/cases/equalizerController.test.js create mode 100644 lambda/test/alexa/cases/index.js create mode 100644 lambda/test/alexa/cases/inputController.test.js create mode 100644 lambda/test/alexa/cases/keypadController.test.js create mode 100644 lambda/test/alexa/cases/lockController.test.js create mode 100644 lambda/test/alexa/cases/modeController.test.js create mode 100644 lambda/test/alexa/cases/networkingAccessController.test.js create mode 100644 lambda/test/alexa/cases/percentageController.test.js create mode 100644 lambda/test/alexa/cases/playbackController.test.js create mode 100644 lambda/test/alexa/cases/powerController.test.js create mode 100644 lambda/test/alexa/cases/powerLevelController.test.js create mode 100644 lambda/test/alexa/cases/rangeController.test.js create mode 100644 lambda/test/alexa/cases/sceneController.test.js create mode 100644 lambda/test/alexa/cases/securityPanelController.test.js create mode 100644 lambda/test/alexa/cases/speaker.test.js create mode 100644 lambda/test/alexa/cases/stepSpeaker.test.js create mode 100644 lambda/test/alexa/cases/thermostatControllerMode.test.js create mode 100644 lambda/test/alexa/cases/thermostatControllerTemperature.test.js create mode 100644 lambda/test/alexa/cases/toggleController.test.js create mode 100644 lambda/test/alexa/chai.js rename lambda/{smarthome/test => test/alexa}/schemas/alexa_smart_home_message_schema.json (88%) create mode 100644 lambda/test/alexa/smarthome.test.js create mode 100644 lambda/test/openhab.test.js create mode 100644 lambda/test/skill.test.js create mode 100644 lambda/test/utils.test.js create mode 100644 lambda/utils.js rename resources/icons/openhablogo-512.png => skill-package/assets/images/openhab_largeIcon.png (100%) rename resources/icons/openhablogo-108.png => skill-package/assets/images/openhab_smallIcon.png (100%) create mode 100644 skill-package/skill.json delete mode 100644 skill.json create mode 100644 tools/generateProdConfig.js delete mode 100644 tools/updateSkillCatalog.js create mode 100644 tools/updateSkillLocale.js delete mode 100644 tools/updateSkillManifest.js diff --git a/.ask/config b/.ask/config deleted file mode 100644 index 5e93e17e..00000000 --- a/.ask/config +++ /dev/null @@ -1,9 +0,0 @@ -{ - "deploy_settings": { - "default": { - "skill_id": "", - "was_cloned": false, - "merge": {} - } - } -} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index cc7a7f75..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: build - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -defaults: - run: - working-directory: lambda/smarthome - -jobs: - build: - - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [10.x, 12.x] - - steps: - - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: npm ci - - run: npm run build --if-present - - run: npm test diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..d5292a85 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,107 @@ +name: CI + +on: + push: + branches: [ main ] + paths: [ lambda/** ] + pull_request: + branches: [ main ] + paths: [ lambda/** ] + release: + types: [ published ] + +jobs: + test: + name: Testing + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: ['12', '14'] + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + cache: npm + cache-dependency-path: lambda/package-lock.json + + - name: Install dependencies + run: npm ci + working-directory: lambda + + - name: Run tests + run: npm run test:coverage + working-directory: lambda + + - name: Upload coverage report + uses: actions/upload-artifact@v2 + with: + name: coverage-report + path: lambda/coverage + + codeql: + name: Code Analysis + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: javascript + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 + + deploy: + name: Release Deployment + if: github.event_name == 'release' + runs-on: ubuntu-latest + needs: [test, codeql] + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '14' + cache: npm + cache-dependency-path: lambda/package-lock.json + + - name: Install ASK CLI + run: npm install -g jsetton/ask-cli + + - name: Cache ASK CLI states + uses: actions/cache@v2 + with: + path: .ask/ask-states.json + key: ask-states-production + + - name: Generate production config + run: node tools/generateProdConfig.js + env: + FUNCTION_NAME: openhab-alexa + LOG_LEVEL: error + SKILL_ID: ${{ secrets.SKILL_ID }} + TESTING_USERNAME: ${{ secrets.TESTING_USERNAME }} + TESTING_PASSWORD: ${{ secrets.TESTING_PASSWORD }} + + - name: Deploy skill and AWS resources + run: ask deploy + env: + AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + ASK_ACCESS_TOKEN: ${{ secrets.ASK_ACCESS_TOKEN }} + ASK_REFRESH_TOKEN : ${{ secrets.ASK_REFRESH_TOKEN }} + ASK_VENDOR_ID: ${{ secrets.ASK_VENDOR_ID }} + ASK_SHARE_USAGE: false diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml new file mode 100644 index 00000000..91650610 --- /dev/null +++ b/.github/workflows/doc.yml @@ -0,0 +1,23 @@ +name: Documentation + +on: + push: + branches: [ main ] + paths: [ '**.md' ] + pull_request: + branches: [ main ] + paths: [ '**.md' ] + +jobs: + Lint: + name: Linter + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Lint Markdown files + uses: nosborn/github-action-markdown-cli@v2 + with: + files: '**.md' diff --git a/.github/workflows/locale.yml b/.github/workflows/locale.yml new file mode 100644 index 00000000..afc1212f --- /dev/null +++ b/.github/workflows/locale.yml @@ -0,0 +1,36 @@ +name: Locale + +on: + push: + branches: [ main ] + paths: [ resources/locales/** ] + +jobs: + update: + name: Locale Updates + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '14' + + - name: Update skill locale + run: node tools/updateSkillLocale.js + + - name: Check for changes to commit + id: changes + run: test -n "$(git status -suno)" + continue-on-error: true + + - name: Commit and push changes + if: steps.changes.outcome == 'success' + run: | + git config user.name openhab-bot + git config user.email bot@openhab.org + git commit -a -m "New locale updates" + git push diff --git a/.gitignore b/.gitignore index 29be9c99..c6363b64 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ -/lambda/*/catalog.json -/lambda/*/config.js -ssl/ +.ask +lambda/ssl/ +skill-package/accountLinking.json + +# VS Code .vscode # Logs diff --git a/.markdownlint.yml b/.markdownlint.yml new file mode 100644 index 00000000..ff780770 --- /dev/null +++ b/.markdownlint.yml @@ -0,0 +1,9 @@ +default: true + +# Line length +MD013: false +# Multiple top-level headings in the same document +MD025: false +# Inline HTML +MD033: + allowed_elements: [a, br, img] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 663218de..c2ce27e9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,6 @@ -## Contribution guidelines +# Contributing + +## Guidelines ### Pull requests are always welcome @@ -10,7 +12,7 @@ If your pull request is not accepted on the first try, don't be discouraged! If there's a problem with the implementation, hopefully you received feedback on what to improve. -### Discuss your design on the mailing list +### Discuss your design in the discussion forum We recommend discussing your plans [in the discussion forum](https://community.openhab.org/) before starting to code - especially for more ambitious contributions. @@ -18,19 +20,17 @@ This gives other contributors a chance to point you in the right direction, give feedback on your design, and maybe point out if someone else is working on the same thing. -### Create issues... - -Any significant improvement should be documented as [a GitHub -issue](https://github.com/openhab/openhab-alxea/issues?labels=enhancement&page=1&state=open) before anybody -starts working on it. - -### ...but check for existing issues first! +### Create issues Please take a moment to check that an issue doesn't already exist documenting your bug report or improvement proposal. If it does, it never hurts to add a quick "+1" or "I have this problem too". This will help prioritize the most common problems and requests. +Any significant improvement should be documented as [a GitHub +issue](https://github.com/openhab/openhab-alxea/issues?labels=enhancement&page=1&state=open) before anybody +starts working on it. + ### Conventions Fork the repo and make changes on your fork in a feature branch. @@ -78,7 +78,7 @@ pass it on as an open-source patch. The rules are pretty simple: if you can certify the below (from [developercertificate.org](http://developercertificate.org/)): -``` +```text Developer Certificate of Origin Version 1.1 @@ -119,7 +119,9 @@ By making a contribution to this project, I certify that: then you just add a line to every git commit message: - Signed-off-by: Joe Smith (github: github_handle) +```text +Signed-off-by: Joe Smith (github: github_handle) +``` using your real name (sorry, no pseudonyms or anonymous contributions.) @@ -130,7 +132,7 @@ There are several exceptions to the signing requirement. Currently these are: * Your patch fixes spelling or grammar errors. * Your patch is a single line change to documentation. -## Community Guidelines +## Code of Conduct We want to keep the openHAB-alexa community awesome, growing and collaborative. We need your help to keep it that way. To help with this we've come up with some diff --git a/README.md b/README.md index 60d73bee..33919aeb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -# Amazon Alexa Smart Home skill for openHAB 2 +# openHAB Skill for Amazon Alexa -[![Build Status](https://github.com/openhab/openhab-alexa/workflows/build/badge.svg?branch=main)](https://github.com/openhab/openhab-alexa/actions?query=workflow%3Abuild) +[![CI](https://github.com/openhab/openhab-alexa/actions/workflows/ci.yml/badge.svg)](https://github.com/openhab/openhab-alexa/actions/workflows/ci.yml) [![Crowdin](https://badges.crowdin.net/openhab-alexa/localized.svg)](https://crowdin.com/project/openhab-alexa) +[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier) This is a nodejs / lambda application that connects the Alexa Smart Home API to a user's openHAB instance, either directly or through the openHAB Cloud service (preferred). The Smart Home API is not a general skill API, it allows the user to bypass using a application wake work and instead ask Alexa to perform a smart home action like "Alexa turn lights on" @@ -13,7 +14,7 @@ This document describes how to configure and deploy the skill for development or ## Skill Usage -For end-user documentation and general usage, see the [Usage](USAGE.md) page for examples and instructions on configuring items for Alexa within openHAB. +For end-user documentation and general usage, see the [Usage](USAGE.md) page for examples and instructions on configuring items for Amazon Alexa within openHAB. ## Requirements @@ -23,99 +24,92 @@ You need an [AWS account](https://aws.amazon.com) and an [Amazon developer accou In order to use the ASK CLI features to automatically deploy and manage your Lambda skill, ensure that you have AWS credentials set up with the appropriate permissions on the computer you are installing ASK CLI, as described in [this documentation](https://developer.amazon.com/docs/smapi/manage-credentials-with-ask-cli.html). -You will have to install the latest [ASK CLI](https://developer.amazon.com/docs/smapi/quick-start-alexa-skills-kit-command-line-interface.html) v1.x, and then initialize it: -``` -$ npm install -g ask-cli@^1.0.0 -$ ask init +You will have to install the latest [ASK CLI](https://developer.amazon.com/docs/smapi/quick-start-alexa-skills-kit-command-line-interface.html), and then configure it: + +```shell +npm install -g ask-cli +ask configure ``` -By default, the ASK CLI deploys the lambda function in the `us-east-1` region. You will need to change your [default region](https://docs.aws.amazon.com/general/latest/gr/rande.html#lambda_region) based on the skill language you are planning to use. You should refer to the table below, based on the [smart home multi-languages development guidelines](https://developer.amazon.com/docs/smarthome/develop-smart-home-skills-in-multiple-languages.html#deploy): +By default, the ASK CLI deploys the skill resources in the `us-east-1` region. You will need to change your deploy region based on the skill language you are planning to use. You should refer to the table below, based on the [smart home multi-languages development guidelines](https://developer.amazon.com/docs/smarthome/develop-smart-home-skills-in-multiple-languages.html#deploy): -| Skill Language | Endpoint Region | Lambda Region | +| Skill Language | Endpoint Region | Deploy Region | | -------------- | --------------- | ------------- | -| English (CA), English (US), French (CA), Portuguese (BR),
Spanish (MX), Spanish (US) | North America | us-east-1 | -| English (UK), French (FR), German, Italian, Spanish (ES) | Europe | eu-west-1 | -| English (IN), Hindi (IN) | India | eu-west-1 | -| English (AU), Japanese | Far East | us-west-2 | +| English (CA), English (US), French (CA), Portuguese (BR),
Spanish (MX), Spanish (US) | North America | `us-east-1` | +| English (UK), French (FR), German, Italian, Spanish (ES) | Europe | `eu-west-1` | +| English (IN), Hindi (IN) | India | `eu-west-1` | +| English (AU), Japanese | Far East | `us-west-2` | -To change your default region, you will need to add the `region` parameter to the AWS credentials file located in your home directory, under the AWS profile name associated during the ASK CLI profile initialization. The default profile name is `ask_cli_default`. - -``` -$ cat ~/.aws/credentials -[ask_cli_default] -aws_access_key_id= -aws_secret_access_key= -region=us-east-1 -``` +To change your deploy region, update the `awsRegion` skill infrastructure user config parameter in [`ask-resources.json`](ask-resources.json). ### OAuth2 Provider If you aren't using your own OAuth2 server (e.g. private openHAB Cloud Connector), it is highly recommended to use [Login with Amazon](https://developer.amazon.com/loginwithamazon/console/site/lwa/overview.html). See [this post](https://developer.amazon.com/public/community/post/Tx3CX1ETRZZ2NPC/Alexa-Account-Linking-5-Steps-to-Seamlessly-Link-Your-Alexa-Skill-with-Login-wit) to set it up for your private skill. Doing so allows [other server level authentication methods](#openhab-server) to be used over the Alexa Smart Home skill requirements for OAuth2 authentication. -If using a private openHAB Cloud Connector, in order to setup the OAuth2 server, make sure to create a client profile and scope to use with the skill in the Mango database, and that it is accessible on port 443. It is recommended to use an online random hex number generator to create a unique client secret. +If using a private openHAB Cloud Connector, in order to setup the OAuth2 server, make sure it is accessible on port 443, and to create a client profile and scope for Alexa skills in the Mango database, by running the below commands with the `mango` CLI tool. It is recommended to use an online random hex number generator to create a unique client secret. -``` -$ mongo -> use openhab -> db.oauth2clients.insert({ name: "Alexa", description: "Alexa Voice Control", icon: "alexa.png", clientId: "alexa-skill", clientSecret: "" }) -> db.oauth2scopes.insert({ name: "alexa", description: "Access to openHAB Cloud specific API for Amazon Alexa" }) +```shell +use openhab +db.oauth2clients.insert({ name: "Alexa", description: "Alexa Voice Control", icon: "alexa.png", clientId: "alexa-skill", clientSecret: "" }) +db.oauth2scopes.insert({ name: "alexa", description: "Access to openHAB Cloud specific API for Amazon Alexa" }) ``` And use the following settings during the skill account linking deployment step instead: * Authorization URL: `https://openhab.myserver.com/oauth2/authorize` +* Access Token URL: `https://openhab.myserver.com/oauth2/token` * Client ID: `alexa-skill` * Scope: `alexa` -* Access Token URI: `https://openhab.myserver.com/oauth2/token` ### openHAB Server The openHAB server you are trying to control with the skill needs to be accessible online as an AWS service endpoint. You can either use [myopenHAB.org](http://myopenHAB.org) cloud service or point the skill directly to your server URL. If going with the latter, make sure to use a valid SSL certificate. It is highly recommended to use [Let's Encrypt](https://letsencrypt.org) to validate your certificates. -To configure the server path and credentials, you will need to setup the application configuration in `lambda/smarthome/config.js` using the sample file. Set the server rest path in the `baseURL` property if not using myopenHAB.org cloud service. The app can access an openHAB installation using three different types of authentication: SSL client certificate, basic (user/password) or bearer (OAuth2 token). For certificate authentication, place the client certificate in `lambda/smarthome/ssl/client.pfx` or set the `certFile` property with the certificate path, and optionally, set the `certPass` property with the certificate passphrase. For basic authentication, set the `user` and `pass` properties, otherwise a bearer token will be used. +To configure the server path and credentials, you will need to setup your backend configuration in [`lambda/config.js`](lambda/config.js). Set your server path in the `baseURL` property if not using myopenHAB.org cloud service. The Lambda function can access an openHAB server using three different types of authentication: SSL client certificate, basic (user/password) or bearer (OAuth2 token). For certificate authentication, place the client certificate in `lambda/ssl/client.pfx` or set the `certFile` property with the certificate path, and optionally, set the `certPass` property with the certificate passphrase. For basic authentication, set the `user` and `pass` properties, otherwise a bearer token will be used. ## Deployment Steps ### Create Smart Home Skill and Lambda Function 1. Clone or download this repository: - ``` - $ git clone https://github.com/openhab/openhab-alexa.git + + ```shell + git clone https://github.com/openhab/openhab-alexa.git ``` 2. Deploy the skill and the lambda function in one step: - ``` - $ ask deploy - Profile for the deployment: [default] - -------------------- Create Skill Project -------------------- - Skill Id: - Skill deployment finished. - [Warn]: No runtime and handler settings found for alexaUsage "smartHome/default" when creating Lambda function. CLI will use "nodejs10.x" and "index.handler" as the Runtime and Handler to create Lambda. You can update the runtime and handler for the target Lambda in the project config and deploy again if you want to set differently. - Lambda deployment finished. - Lambda function(s) created: - [Lambda ARN] - [Info]: No in-skill product to be deployed. - [Warn]: Skill api domain "smartHome" can not be enabled. Skipping the enablement. - ``` -3. Setup skill account linking using the skill id displayed in previous step and your OAuth2 provider configuration: - ``` - $ ask api create-account-linking -s - ? Authorization URL: https://www.amazon.com/ap/oa - ? Client ID: - ? Scopes(separate by comma): profile - ? Domains(separate by comma): - ? Authorization Grant Type: AUTH_CODE - ? Access Token URI: https://api.amazon.com/auth/o2/token - ? Client Secret: [hidden] - ? Client Authentication Scheme: HTTP_BASIC - ? Optional* Default Access Token Expiration Time In Seconds: - ? Optional* Reciprocal Access Token Url: - ? Optional* RedirectUrls for App-to-App Account Linking (separated by comma): - Account linking created successfully. + ```shell + ask deploy ``` -4. Enable skill with account linking: +3. Setup the skill account linking: + 1. Create the skill account linking request file as `skill-package/accountLinking.json`, adding your OAuth2 provider client credentials: + + ```json + { + "accountLinkingRequest": { + "skipOnEnablement": "false", + "type": "AUTH_CODE", + "authorizationUrl": "https://www.amazon.com/ap/oa", + "accessTokenUrl": "https://api.amazon.com/auth/o2/token", + "accessTokenScheme": "HTTP_BASIC", + "clientId": "", + "clientSecret": "", + "scopes": [ + "profile" + ], + } + } + ``` + + 2. Update the skill account linking information, using the skill ID displayed in the deploy step: + + ```shell + ask smapi update-account-linking-info -s --account-linking-request file:skill-package/accountLinking.json + ``` + +4. Enable the skill on your Alexa account: * Go to your [Alexa skill console](https://alexa.amazon.com/spa/index.html#skills/your-skills/?ref-suffix=ysa_gw) * Click on the "openHAB" skill under the "Dev Skills" tab * Click "Enable" and go through the account linking process @@ -123,37 +117,42 @@ To configure the server path and credentials, you will need to setup the applica ### Update Smart Home Skill and Lambda Function 1. Update the repository to latest commit: - ``` - $ git pull + + ```shell + git pull ``` -2. If updating from v2 version: - 1. Copy relevant settings from `config.js` (v2) to `lambda/smarthome/config.js` (v3). +2. If updating from ASK CLI v1: + 1. Copy relevant settings from `lambda/smarthome/config.js` (ask-cli-v1) to [`lambda/config.js`](lambda/config.js) (ask-cli-v2). If configuring `baseURL`, be aware that it should now point to your server root level and not the rest endpoint. Additionally, move your client certificate to `lambda/ssl` if using that authentication method. - 2. Add current skill id to ask config by using the skill id listed under your [Alexa developer console](https://developer.amazon.com/alexa/console/ask). - ``` - $ cat .ask/config + 2. Create the ASK CLI states file as `.ask/ask-states.json`, adding the skill ID listed in your [Alexa developer console](https://developer.amazon.com/alexa/console/ask). This will prevent duplicate skills from being created in your account. + + ```json { - "deploy_settings": { + "askcliStatesVersion": "2020-03-31", + "profiles": { "default": { - "skill_id": "", - "was_cloned": false, - "merge": {} + "skillId": "" } } } ``` + 3. Delete existing function and logs using the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html), or via your [AWS Console](https://console.aws.amazon.com) to prevent conflicts with the CloudFormation stack deployment. + + ```shell + aws lambda delete-function --function-name alexa-openhab + aws logs delete-log-group --log-group-name /aws/lambda/alexa-openhab + ``` + + 4. Remove old folder environment. + + ```shell + rm -rf lambda/smarthome + ``` + 3. Deploy the skill and the lambda function in one step: - ``` - $ ask deploy [--force] (Force deployment if lambda manual configs were applied) - Profile for the deployment: [default] - -------------------- Update Skill Project -------------------- - Skill Id: - Skill deployment finished. - Lambda deployment finished. - Lambda function(s) updated: - [Lambda ARN] - [Info]: No in-skill product to be deployed. - [Warn]: Skill api domain "smartHome" can not be enabled. Skipping the enablement. + + ```shell + ask deploy ``` diff --git a/USAGE.md b/USAGE.md index ee22efa0..09da9668 100644 --- a/USAGE.md +++ b/USAGE.md @@ -2,7 +2,7 @@ layout: documentation title: Amazon Alexa Smart Home Skill source: https://github.com/openhab/openhab-alexa/blob/main/USAGE.md -description: "Alexa is an intelligent personal assistant developed by Amazon and designed to run on smart speakers and devices such as the Amazon Echo and Dot." +description: "Alexa is an intelligent personal assistant developed by Amazon and designed to run on smart speakers and devices such as the Amazon Echo and Echo Dot." --- # Amazon Alexa Smart Home Skill @@ -11,62 +11,85 @@ description: "Alexa is an intelligent personal assistant developed by Amazon and Alexa is an intelligent personal assistant developed by Amazon and designed to run on smart speakers and devices such as the Amazon Echo and Dot. -This certified Amazon Smart Home Skill allows users to control their openHAB powered smart home with natural voice commands. Lights, locks, thermostats, AV devices, sensors and many other device types can be controlled through a user's Alexa powered device like the Echo or Dot. +This certified Amazon Smart Home Skill allows users to control their openHAB powered smart home with natural voice commands. Lights, locks, thermostats, AV devices, sensors and many other device types can be controlled through a user's Amazon Alexa powered device like the Echo or Echo Dot. -This page describes how to use the [openHAB Alexa Smart Home Skill](https://www.amazon.com/openHAB-Foundation/dp/B01MTY7Z5L). +This page describes how to use the [openHAB Skill for Amazon Alexa](https://www.amazon.com/openHAB-Foundation/dp/B01MTY7Z5L). The skill connects your openHAB setup through the [myopenHAB.org](http://myopenHAB.org) cloud service to Amazon Alexa. ## Table of Contents -* [Setup](#setup) - * [Requirements](#requirements) - * [Recommendations](#recommendations) - * [Item Labels](#item-labels) - * [Regional Settings](#regional-settings) - * [Concept](#concept) - * [Single Endpoint](#single-endpoint) - * [Group Endpoint](#group-endpoint) - * [Building Block APIs](#building-block-apis) - * [Semantic Extensions](#semantic-extensions) - * [Item Sensor](#item-sensor) - * [Item State](#item-state) - * [Item Unit of Measurement](#item-unit-of-measurement) - * [Item Configuration](#item-configuration) - * [Supported Item Metadata](#supported-item-metadata) - * [Supported Group Metadata](#supported-group-metadata) - * [Supported Metadata Labels](#supported-metadata-labels) - * [Regional Availability](#regional-availability) - * [Display Categories](#display-categories) - * [Asset Catalog](#asset-catalog) - * [Semantic Catalog](#semantic-catalog) - * [Unit of Measurement Catalog](#unit-of-measurement-catalog) - * [Friendly Names Not Allowed](#friendly-names-not-allowed) - * [Item Tag v2 Support](#item-tag-v2-support) + +* [Requirements](#requirements) +* [Recommendations](#recommendations) + * [Item Labels](#item-labels) + * [Regional Settings](#regional-settings) +* [Concept](#concept) + * [Single Endpoint](#single-endpoint) + * [Group Endpoint](#group-endpoint) + * [Item State](#item-state) + * [Item Unit of Measurement](#item-unit-of-measurement) + * [Networking Capabilities](#networking-capabilities) + * [Generic Capabilities](#generic-capabilities) + * [Semantic Extensions](#semantic-extensions) +* [Item Configuration](#item-configuration) + * [Device Types](#device-types) + * [Device Attributes](#device-attributes) + * [Camera Attributes](#camera-attributes) + * [Cover Attributes](#cover-attributes) + * [Entertainment Attributes](#entertainment-attributes) + * [Fan Attributes](#fan-attributes) + * [Lighting Attributes](#lighting-attributes) + * [Networking Attributes](#networking-attributes) + * [Scene Attributes](#scene-attributes) + * [Security Attributes](#security-attributes) + * [Sensor Attributes](#sensor-attributes) + * [Switchable Attributes](#switchable-attributes) + * [Thermostat Attributes](#thermostat-attributes) + * [Vacuum Attributes](#vacuum-attributes) + * [Generic Attributes](#generic-attributes) * [Troubleshooting](#troubleshooting) - * [Command Not Working](#command-not-working) - * [Device Not Found](#device-not-found) - * [Device Not Responding](#device-not-responding) - * [Duplicate Device Names](#duplicate-device-names) - * [Request Not Supported](#request-not-supported) - * [Server Authentication Issue](#server-authentication-issue) - * [Server Not Accessible](#server-not-accessible) - * [Temperature Out Of Range](#temperature-out-of-range) -* [Example Voice Commands](#example-voice-commands) -* [Other openHAB Alexa Integrations](#other-openhab-alexa-integrations) - * [Amazon Echo Control Binding](#amazon-echo-control-binding) - * [Hue Emulation Service](#hue-emulation-service) - -# Setup - -* NEW Alexa Version 3 API syntax (v3) - * Version 3 of the Alex Skill API introduces a more rich and complex set of features that required a change in how items are configured by using the new metadata feature introduced in openaHAB 2.3 - * Version 2 tags are still supported and are converted internally to v3 meta data - * Supported [item](#supported-item-metadata) & [group](#supported-group-metadata) v3 meta data - * Automatically determine number precision and unit based on [item state presentation](#item-state) and [unit of measurement](#item-unit-of-measurement). - * Decoupling between item receiving command and item state via an [item sensor](#item-sensor) - * Improved Alexa response state accuracy - * Support for [building block APIs](#building-block-apis) and [semantic extensions](#semantic-extensions) latest features - -## Requirements + * [Response Errors](#response-errors) + * [Command Not Working](#command-not-working) + * [Device Not Found](#device-not-found) + * [Device Not Responding](#device-not-responding) + * [Duplicate Device Names](#duplicate-device-names) + * [Request Error](#request-error) + * [Request Not Supported](#request-not-supported) + * [Server Authentication Issue](#server-authentication-issue) + * [Server Not Accessible](#server-not-accessible) + * [Temperature Out Of Range](#temperature-out-of-range) +* [Additional Information](#additional-information) + * [Regional Availability](#regional-availability) + * [Asset Catalog](#asset-catalog) + * [Semantic Catalog](#semantic-catalog) + * [Unit of Measurement Catalog](#unit-of-measurement-catalog) + * [Capability Names Not Allowed](#capability-names-not-allowed) + * [Other openHAB Integrations for Amazon Alexa](#other-openhab-integrations-for-amazon-alexa) + * [Amazon Echo Control Binding](#amazon-echo-control-binding) + * [Hue Emulation Service](#hue-emulation-service) + +## Latest Changes + +* Revamped [item configuration](#item-configuration) syntax using device metadata concept. + * Deprecated previous syntax, although backward compatible for the time being. +* Added new device capabilities: + * [Camera](#camera-attributes) + * [Door/Window Covering](#cover-attributes) + * [Fan](#fan-attributes) + * [Networking](#networking-attributes) + * [Vacuum](#vacuum-attributes) +* Updated existing capabilities: + * New security [arm state](#armstate) errors handling. + * Support for [input](#input) custom mappings. + * Support for [playback stop](#playbackstop) requests. + * Support for [onscreen navigation](#navigation) requests. + * Support for [thermostat hold](#thermostathold) setting and [thermostat fan](#thermostatfan) mode. +* Added new [custom asset ids](#custom-asset-catalog). +* Added new [custom semantic extensions](#custom-semantic-catalog). +* Deprecated general item sensor concept support for decoupling between item receiving command and item states. + * Decoupled state support maintained for [`LockState`](#lockstate) and added for [`OpenState`](#openstate). +* Removed version 2 tags support for openHAB 3.0 and above. + +# Requirements ::: tip This integration relies on the cloud connector addon. @@ -75,457 +98,779 @@ More information can be found in the corresponding [docs page](https://www.openh * openHAB Cloud Connector configured using myopenHAB.org * Amazon account -* Amazon Echo, Amazon Echo Dot or compatible Alexa device +* Amazon Echo, Amazon Echo Dot or compatible Amazon Alexa devices + +# Recommendations + +## Item Labels + +Matching of voice commands to items happens based on the item label (e.g. "Kitchen Light"). As an alternative, the metadata parameter `name` can be used over the item label. If neither are specified, the item will be ignored. It is therefore advisable, to choose labels that can be used to form natural commands. It is important to note that each labels needs to be unique to prevent any [duplicate issues](#duplicate-device-names). As an example, compare *Alexa, turn on the Kitchen Light* vs *Alexa, turn on the Ground Floor LEDs Kitchen*. -## Recommendations +## Regional Settings -### Item Labels -Matching of voice commands to items happens based on the item label (e.g. "Kitchen Light"). If it is not specified, the item will be ignored. It is therefore advisable, to choose labels that can be used to form natural commands. It is important to note that each of these labels needs to be unique to prevent any [duplicate issues](#duplicate-device-names). As an example, compare "Alexa, turn on the Kitchen Light" vs. "Alexa, turn on the Ground Floor LEDs Kitchen". +In order for the skill to determine your default language and measurement system to use during the discovery process, it is important to set your server regional settings including the language, country/region and measurement system properties. These can either be accomplished by using the admin UI, or setting the `language`, `region` and `measurementSystem` properties for `org.openhab.i18n` service in `$OPENHAB_CONF/services/runtime.cfg`. If these settings aren't defined, the skill will either use the item level configuration, if available, to determine these properties, or fallback to `en` language and `SI` measurement system, as default values. -### Regional Settings -In order for the skill to determine your default language and measurement system to use, during the discovery process, for some of the controllers supporting friendly language-based names and unit of measurement, it is important to set your server regional settings including the language, country/region and measurement system properties. These can either be accomplished by using Paper UI (Configuration > System > Regional Settings) or setting the `language`, `region` and `measurementSystem` properties for `org.openhab.i18n` (openHAB 3.0 and later), `org.eclipse.smarthome.i18n` (openHAB 2.5), or `org.eclipse.smarthome.core.i18nprovider` (openHAB 2.4 and prior) service in `$OPENHAB_CONF/services/runtime.cfg`. If these settings aren't defined, the skill will either use the item level configuration, if available, to determine these properties, or fallback to `en` language and `SI` measurement system, as default values. +# Concept -## Concept +The Alexa skill API uses the concept of "endpoints". Endpoints are addressable entities that expose one or more capabilities. An example endpoint may be a light switch, which has a single capability to control power and report its state (ON/OFF). A more complex endpoint may be a thermostat which has many capabilities to control and report temperature, setpoints, modes, etc... -The Alexa skill API uses the concept of "endpoints". Endpoints are addressable entities that expose functionality in the form of capability interfaces. An example endpoint may be a light switch, which has a single capability called power state (ON/OFF). A more complex endpoint may be a thermostat which has many capabilities to control and report temperature, setpoints, modes, etc... +## Single Endpoint -### Single Endpoint -Single items in openHAB can be mapped to single endpoint in Alex through the use of the Alexa metadata. +Single items in openHAB can be mapped to single endpoint in Alexa through the use of the [item metadata](https://www.openhab.org/docs/concepts/items.html#item-metadata). An simple example of this is a light switch. In openHAB a light switch is defined as a "Switch" item and responds to ON or OFF commands. + +```xtend +Switch LightSwitch "Light Switch" {alexa="Light"} ``` -Switch LightSwitch "Light Switch" -``` -In the Alexa skill a light switch endpoint implements the "PowerController" interface and exposes a "powerState" property. To map our openHAB switch to a PowerController endpoint we use a Alexa metadata: -``` -Switch LightSwitch "Light Switch" {alexa="PowerController.powerState"} -``` -Setting this on a single item will create an Alexa endpoint with the spoken addressable name "Light Switch" and map the powerState property to our item. You can ask Alexa to turn "Light Switch" on or off. -An example of how this works with other metadata is given in [Items Metadata](https://www.openhab.org/docs/concepts/items.html#item-metadata) +Setting this on a single item will create an Alexa endpoint as a lighting device with the spoken addressable name "Light Switch" and power control capability. You can ask *Alexa, turn on Light Switch*. -This can also be written using [metadata labels](#supported-metadata-labels), which is a shorthand version of the full Alexa namespace: -``` -Switch LightSwitch "Light Switch" {alexa="Switchable"} +In openHAB, a "Dimmer" item responds to both brightness and on/off commands. Using the same metadata device on that item will give power and brightness control to the Alexa endpoint. Alternatively, the device name can be defined in the metadata parameters, instead of the item label, along with a customized description that will show in the Alexa app. You can ask *Alexa, turn on Light Switch* well as *Alexa, set Light Switch to 50%*. + +```xtend +Dimmer LightSwitch {alexa="Light" [name="Light Switch", description="Super Smart Light"]} ``` -A slightly more complex example would be a Light Dimmer. In openHAB a dimmer object responds to both percentage and ON / OFF commands. In Alexa this is two different interfaces. To support both types of commands, we need to add both to the item metadata: +The same for a "Color" item responding to color, brightness and on/off commands. If you need to limit the default capabilities, you can specify in the [item configuration](#item-configuration) each device attribute your device supports, prefixed with the `Light` device type. The example below shows a colored light switch with color and power on/off controls only. The brightness control would be omitted. + +```xtend +Color LightSwitch "Light Switch" {alexa="Light.Color,Light.PowerState"} ``` -Dimmer LightSwitch "Light Switch" {alexa="PowerController.powerState,BrightnessController.brightness"} + +For a general switch, the `Switch` metadata device will give the same capability but as a switchable device Alexa endpoint. + +```xtend +Switch ApplianceSwitch "Appliance Switch" {alexa="Switch"} ``` -You can ask Alexa to "Turn Light Switch .." on or off as well as "Set Light Switch to .." a certain percentage. +By default, a `Switch` device type will have the category "SWITCH", which can be changed using a more specific device type from the [supported list](#device-types). For example, using the `CoffeeMaker` device type will retain the same power on/off capability but will show as a coffee maker in the Alexa app. -Using [metadata labels](#supported-metadata-labels) this would look like: +```xtend +Switch CoffeeMaker "Coffee Maker" {alexa="CoffeeMaker"} ``` -Dimmer LightSwitch "Light Switch" {alexa="Lighting"} + +Likewise, more complex single endpoints can be configured. Such as using a `Blind` device type, which responds to [position state](#positionstate) requests by default. + +```xtend +Rollershutter Blind "Blind" {alexa="Blind"} ``` -NOTE: the Alexa skill has 3 different percentage interfaces, BrightnessController, PowerLevelController and PercentageController. Your item should only be using one of these that best describes the type of device. So for lights this would be the BrightnessController, for roller shades this would be PercentageController. The skill will not prevent adding more then one, but voice control may suffer for that device. + -### Group Endpoint -While single mapping items works for many use cases, occasionally multiple openHAB items need to be mapped to a single endpoint in Alexa. When using a group item, keep in mind that there can only be one specific interface capability per group. If you need to have more than one instance of a given capability, you should use the [building block APIs](#building-block-apis) controllers. +## Group Endpoint -Below are examples for various use cases, such as a thermostat, a smart bulb, a stereo and a security system. +While single mapping items works for many use cases, occasionally multiple openHAB items need to be mapped to a single endpoint in Alexa. When using a group item, keep in mind that only one specific attribute capability per group can be defined, except for [generic capabilities](#generic-capabilities). -In openHAB a thermostat is modeled as many different items, typically there are items for setpoints (target, heat, cool), modes, and the current temperature. To map these items to a single endpoint in Alexa, we will add them to a group which also uses "Alexa" metadata. When items are Alexa-enabled, but are also a member of a group Alexa-enabled, they will be added to the group endpoint and not exposed as their own endpoints. +Only [functional groups](https://www.openhab.org/docs/configuration/items.html#groups) (no group type) can be configured as group endpoint. [State derived groups](https://www.openhab.org/docs/configuration/items.html#derive-group-state-from-member-items) will be considered as single endpoints based on their defined group type. + +The below example exposes 3 separate single endpoints, with "Light 1" and "Light 2" as independent lights with brightness and on/off controls, while and "Light Group" controlling these two as a group of lights with on/off control. +```xtend +Group:Switch:OR(ON,OFF) LightGroup "Light Group" {alexa="Light"} +Dimmer Light1 "Light 1" (LightGroup) {alexa="Light"} +Dimmer Light2 "Light 2" (LightGroup) {alexa="Light"} ``` -Group Thermostat "Bedroom" {alexa="Endpoint.Thermostat"} -Number Temperature "Temperature [%.0f °F]" (Thermostat) {alexa="TemperatureSensor.temperature"} -Number CoolSetpoint "Cool Setpoint [%.0f °F]" (Thermostat) {alexa="ThermostatController.upperSetpoint"} -Number HeatSetpoint "Heat Setpoint [%.0f °F]" (Thermostat) {alexa="ThermostatController.lowerSetpoint"} -Number Mode "Mode [%s]" (Thermostat) {alexa="ThermostatController.thermostatMode"} + +Below are examples for various use cases currently natively supported by the skill. + +In openHAB a thermostat is modeled as many different items, typically there are items for setpoints (target, heat, cool), modes, and the current temperature. To map these items to a single endpoint in Alexa, we will add them to a group which also uses "Alexa" metadata. When items are Alexa-enabled, but are also a member of a group Alexa-enabled, they will be added to the group endpoint and not exposed as their own endpoints. + +```xtend +Group Thermostat "Bedroom" {alexa="Thermostat"} +Number Temperature "Temperature [%.1f °F]" (Thermostat) {alexa="CurrentTemperature"} +Number CoolSetpoint "Cool Setpoint [%.1f °F]" (Thermostat) {alexa="CoolingSetpoint"} +Number HeatSetpoint "Heat Setpoint [%.1f °F]" (Thermostat) {alexa="HeatingSetpoint"} +Number Mode "Mode [%s]" (Thermostat) {alexa="HeatingCoolingMode"} ``` -The group metadata also describes the category for the endpoint, in this case a "Thermostat". See the section below on supported [group metadata](#supported-group-metadata) and [categories](#display-categories) for a complete list. In this example a single endpoint is created called "Bedroom", its various interfaces are mapped to different openHAB items. You can ask Alexa "Set the Bedroom thermostat to 72" and the 'HeatSetpoint' will receive the command, if currently in heating mode, likewise you can ask Alexa "What's the temperature of the Bedroom" and Alexa will query the "Temperature" items for its value. +The group metadata also describes the category for the endpoint, in this case a "Thermostat". In this example an endpoint is created called "Bedroom", its various capabilities are mapped to different openHAB items. You can ask *Alexa, set the Bedroom thermostat to 72* and the "HeatSetpoint" will receive the command, if currently in heating mode, likewise you can ask *Alexa, what's the temperature of the Bedroom?* and the current state of "Temperature" will be returned. When mapping items, sometime we need to pass additional parameters to Alexa to set things like what scale to use (Fahrenheit) or what values our items expect for certain states (thermostat modes). These parameters can be passed in the metadata properties, if they are omitted, then reasonable defaults are used. In our above example we may wish to use Fahrenheit as our temperature scale, and map the mode strings to numbers. This would look like: +```xtend +Group Thermostat "Thermostat" {alexa="Thermostat"} +Number Temperature "Temperature [%.1f °F]" (Thermostat) {alexa="CurrentTemperature" [scale="Fahrenheit"]} +Number CoolSetpoint "Cool Setpoint [%.1f °F]" (Thermostat) {alexa="CoolingSetpoint" [scale="Fahrenheit"]} +Number HeatSetpoint "Heat Setpoint [%.1f °F]" (Thermostat) {alexa="HeatingSetpoint" [scale="Fahrenheit"]} +Number Mode "Mode [%s]" (Thermostat) {alexa="HeatingCoolingMode" [OFF=0,HEAT=1,COOL=2,AUTO=3]} +Switch Hold "Hold [%s]" (Thermostat) {alexa="ThermostatHold"} +String Fan "Fan [%s]" (Thermostat) {alexa="ThermostatFan"} ``` -Group Thermostat "Thermostat" {alexa="Endpoint.Thermostat"} -Number Temperature "Temperature [%.0f °F]" (Thermostat) {alexa="TemperatureSensor.temperature" [scale="Fahrenheit"]} -Number CoolSetpoint "Cool Setpoint [%.0f °F]" (Thermostat) {alexa="ThermostatController.upperSetpoint" [scale="Fahrenheit"]} -Number HeatSetpoint "Heat Setpoint [%.0f °F]" (Thermostat) {alexa="ThermostatController.lowerSetpoint" [scale="Fahrenheit"]} -Number Mode "Mode [%s]" (Thermostat) {alexa="ThermostatController.thermostatMode" [OFF=0,HEAT=1,COOL=2,AUTO=3]} + +For thermostat integration such as Nest or Ecobee, a more complex configuration could involve having three setpoints and additional cooling and heating setpoints for eco mode when these are different than the standard ones. Compared to the previous example, the temperature scale here will be based on the item state presentation unit (`°F` => Fahrenheit) and the thermostat mode will be mapped according to the linked binding channel (e.g. `{channel="nest:..."}`). + +```xtend +Group Thermostat "Thermostat" {alexa="Thermostat"} +Number Temperature "Temperature [%.1f °F]" (Thermostat) {alexa="CurrentTemperature"} +Number TargetSetpoint "Target Setpoint [%.1f °F]" (Thermostat) {alexa="TargetTemperature"} +Number CoolSetpoint "Cool Setpoint [%.1f °F]" (Thermostat) {alexa="CoolingSetpoint"} +Number HeatSetpoint "Heat Setpoint [%.1f °F]" (Thermostat) {alexa="HeatingSetpoint"} +Number EcoCoolSetpoint "Eco Cool Setpoint [%.1f °F]" (Thermostat) {alexa="EcoCoolingSetpoint"} +Number EcoHeatSetpoint "Eco Heat Setpoint [%.1f °F]" (Thermostat) {alexa="EcoHeatingSetpoint"} +String Mode "Mode [%s]" (Thermostat) {alexa="HeatingCoolingMode"} ``` -For thermostat integration such as Nest or Ecobee, a more complex configuration could involve having three setpoints and additional upper and lower setpoints for eco mode when these are different than the standard ones. Compared to the previous example, the temperature scale here will be based on the item state presentation unit (`°F` => Fahrenheit) and the thermostat mode will be mapped according to the binding name. +A smart bulb with shade of colors controls. +```xtend +Group Bulb "Bulb" {alexa="Light"} +Color Color "Color" (Bulb) {alexa="PowerState,Brightness,Color"} +Dimmer Temperature "Temperature" (Bulb) {alexa="ColorTemperature"} ``` -Group Thermostat "Thermostat" {alexa="Endpoint.Thermostat"} -Number Temperature "Temperature [%.0f °F]" (Thermostat) {alexa="TemperatureSensor.temperature"} -Number TargetSetpoint "Target Setpoint [%.0f °F]" (Thermostat) {alexa="ThermostatController.targetSetpoint"} -Number HighSetpoint "High Setpoint [%.0f °F]" (Thermostat) {alexa="ThermostatController.upperSetpoint"} -Number LowSetpoint "Low Setpoint [%.0f °F]" (Thermostat) {alexa="ThermostatController.lowerSetpoint"} -Number EcoHighSetpoint "High Eco Setpoint [%.0f °F]" (Thermostat) {alexa="ThermostatController.upperSetpoint#eco"} -Number EcoLowSetpoint "Low Eco Setpoint [%.0f °F]" (Thermostat) {alexa="ThermostatController.lowerSetpoint#eco"} -Number Mode "Mode [%s]" (Thermostat) {alexa="ThermostatController.thermostatMode" [binding="nest"]} + +A smart bulb with shade of white controls. + +```xtend +Group Bulb "Bulb" {alexa="Light"} +Dimmer White "White" (Bulb) {alexa="PowerState,Brightness"} +Dimmer Temperature "Temperature" (Bulb) {alexa="ColorTemperature"} ``` -A smart bulb is another example when it supports shade of colors. Below are two ways to set up a color and a dimmable white bulb with color temperature capability. +A window blind with position and tilt angle controls. +```xtend +Group Blind "Blind" {alexa="Blind"} +Rollershutter Position "Position" (Blind) {alexa="PositionState"} +Rollershutter Tilt "Tilt" (Blind) {alexa="TiltAngle"} ``` -Group Bulb "Bulb" {alexa="Endpoint.Light"} -Color Color "Color" (Bulb) {alexa="BrightnessController.brightness,PowerController.powerState,ColorController.color"} -Dimmer Temperature "Temperature" (Bulb) {alexa="ColorTemperatureController.colorTemperatureInKelvin"} + +A fan with 6-speed, direction, oscillate and power on/off controls. + +```xtend +Group Fan "Fan" {alexa="Fan"} +Number Speed "Speed" (Fan) {alexa="FanSpeed" [speedLevels=6]} +Switch Direction "Direction" (Fan) {alexa="FanDirection"} +Switch Oscillate "Oscillate" (Fan) {alexa="FanOscillate"} +Switch Power "Power" (Fan) {alexa="PowerState"} ``` +A stereo with volume, mute, input, channel, playback, navigation, equalizer and power on/off controls. + +```xtend +Group Stereo "Stereo" {alexa="Speaker"} +Number Volume "Volume" (Stereo) {alexa="VolumeLevel"} +Switch Mute "Mute" (Stereo) {alexa="MuteState"} +Switch Power "Power" (Stereo) {alexa="PowerState"} +String Input "Input" (Stereo) {alexa="Input" [supportedInputs="HDMI1,TV"]} +String Channel "Channel" (Stereo) {alexa="Channel"} +Player Playback "Playback" (Stereo) {alexa="Playback"} +Switch Stop "Stop" (Stereo) {alexa="PlaybackStop"} +String Navigate "Navigate" (Stereo) {alexa="Navigation" [UP="up",DOWN="down",LEFT="left",RIGHT="right",SELECT="select"]} +Number Bass "Bass" (Stereo) {alexa="EqualizerBass" [range="-10:10"]} +Number Midrange "Mid" (Stereo) {alexa="EqualizerMidrange" [range="-10:10"]} +Number Treble "Treble" (Stereo) {alexa="EqualizerTreble" [range="-10:10"]} +String Mode "Mode" (Stereo) {alexa="EqualizerMode" [MOVIE="movie",MUSIC="music",TV="tv"]} ``` -Group Bulb "Bulb" {alexa="Endpoint.Light"} -Dimmer White "White" (Bulb) {alexa="BrightnessController.brightness,PowerController.powerState"} -Dimmer Temperature "Temperature" (Bulb) {alexa="ColorTemperatureController.colorTemperatureInKelvin"} + +A security panel with alarm mode and different alarm/alert states. + +```xtend +Group SecurityPanel "Security Panel" {alexa="SecurityPanel"} +Number ArmMode "Arm Mode" (SecurityPanel) {alexa="ArmState" [DISARMED=0,ARMED_STAY=1,ARMED_AWAY=2]} +Switch BurglaryAlarm "Burglary" (SecurityPanel) {alexa="BurglaryAlarm"} +Switch FireAlarm "Fire" (SecurityPanel) {alexa="FireAlarm"} +Switch CarbonMonoxideAlarm "Carbon Monoxide" (SecurityPanel) {alexa="CarbonMonoxideAlarm"} +Switch WaterAlarm "Water" (SecurityPanel) {alexa="WaterAlarm"} +Switch AlarmAlert "Alarm Alert" (SecurityPanel) {alexa="AlarmAlert"} +Switch ReadyAlert "Ready Alert" (SecurityPanel) {alexa="ReadyAlert"} +Switch TroubleAlert "Trouble Alert" (SecurityPanel) {alexa="TroubleAlert"} +Switch ZonesAlert "Zones Alert" (SecurityPanel) {alexa="ZonesAlert"} ``` -A Stereo is another example of a single endpoint that needs many items to function properly. Power, volume, input, speakers and player controllers are all typical use cases for a stereo that a user may wish to control. +A vacuum cleaner with vacuum mode and fan speed controls, and battery level status. +```xtend +Group Vacuum "Vacuum" {alexa="VacuumCleaner"} +String Mode "Mode" {alexa="VacuumMode"} +Dimmer FanSpeed "Fan Speed" {alexa="FanSpeed"} +Number BatteryLevel "Battery Level" {alexa="BatteryLevel"} ``` -Group Stereo "Stereo" {alexa="Endpoint.Speaker"} -Number Volume "Volume" (Stereo) {alexa="Speaker.volume"} -Switch Mute "Mute" (Stereo) {alexa="Speaker.muted"} -Switch Power "Power" (Stereo) {alexa="PowerController.powerState"} -String Input "Input" (Stereo) {alexa="InputController.input" [supportedInputs="HDMI1,TV"]} -String Channel "Channel" (Stereo) {alexa="ChannelController.channel"} -Player Player "Player" (Stereo) {alexa="PlaybackController.playback"} -Number Bass "Bass" (Stereo) {alexa="EqualizerController.bands:bass" [range="-10:10"]} -Number Midrange "Mid" (Stereo) {alexa="EqualizerController.bands:midrange" [range="-10:10"]} -Number Treble "Treble" (Stereo) {alexa="EqualizerController.bands:treble" [range="-10:10"]} -String Mode "Mode" (Stereo) {alexa="EqualizerController.mode" [supportedModes="MOVIE,MUSIC,TV"]} + +A water heater with temperature and power on/off controls. + +```xtend +Group WaterHeater "Water Heater" {alexa="WaterHeater"} +Number Temperature "Temperature [%.1f °C]" (WaterHeater) {alexa="CurrentTemperature"} +Number TargetSetpoint "Target Setpoint [%.1f °C]" (WaterHeater) {alexa="TargetTemperature"} +Switch Power "Power" (WaterHeater) {alexa="PowerState"} ``` -A security system is another example including alarm mode and different alarm states. + + +## Item State + +Item states, reported back to Alexa, are formatted based on their [item state presentation](https://www.openhab.org/docs/configuration/items.html#state-presentation) definition if configured. This means you can control the precision of number values (e.g. `%.1f °C` will limit reported temperature value to one decimal point). + +For items that don't have a state, these can be configured as not retrievable, automatically when the item [parameter `autoupdate`](https://www.openhab.org/docs/configuration/items.html#parameter-autoupdate) is set as `autoupdate="false"` or by using metadata parameter `retrievable="false"`. In that case, Alexa will not retrieve the given item state, and when a command is issued against that item, the requested state will be returned back without checking the current state in openHAB. If using this feature in a group endpoint, keep in mind that all associated items will need to be configured to either report or not report a state, otherwise the Alexa integration for that endpoint will be broken. +```xtend +Switch Switch1 "Switch 1" {alexa="Switch", autoupdate="false"} +Switch Switch2 "Switch 2" {alexa="Switch" [retrievable="false"]} ``` -Group SecuritySystem "Security System" {alexa="Endpoint.SecurityPanel"} -String AlarmMode "Alarm Mode" (SecuritySystem) {alexa="SecurityPanelController.armState" [supportedArmStates="DISARMED,ARMED_STAY,ARMED_AWAY"]} -Switch BurglaryAlarm "Burglary" (SecuritySystem) {alexa="SecurityPanelController.burglaryAlarm"} -Switch FireAlarm "Fire" (SecuritySystem) {alexa="SecurityPanelController.fireAlarm"} -Switch CarbonMonoxideAlarm "Carbon Monoxide" (SecuritySystem) {alexa="SecurityPanelController.carbonMonoxideAlarm"} -Switch WaterAlarm "Water" (SecuritySystem) {alexa="SecurityPanelController.waterAlarm"} + +For item decouple state, only certain [device attributes](#device-attributes), such as [`lockState`](#lockstate) and [`openState`](#openstate), supports that feature using a separate item to report the current state over the actionable one, to improve state reporting accuracy. + +It is important to note since asynchronous response is not supported by the skill as of yet, the decouple state will need to be available right away for the skill to report the device latest status. + +Below is an example of a lock device with decouple state. + +```xtend +Group Lock "Lock" {alexa="Lock"} +Switch Control "Control" (Lock) {alexa="TargetLockState"} +Contact Status "Status" (Lock) {alexa="CurrentLockState"} ``` -### Building Block APIs -For components of a device, which isn't covered by the existing interfaces, that have more than one setting, characterized by a number within a range or just turn on and off, the [Mode](#modecontroller-mode), [Range](#rangecontroller-rangevalue) and [Toggle](#togglecontroller-togglestate) controllers can be used to highly customize how you interact with that device via Alexa. These capabilities can be used like building blocks to model the full feature set of a complex device. With the expansion of these controllers support to other languages, the skill will use your server [regional settings](#regional-settings) if available, falling back to `en`, to determine your default language setting. +## Item Unit of Measurement + +With the introduction of the [unit of measurement](https://www.openhab.org/docs/concepts/units-of-measurement.html) concept, the item unit can be automatically determined for thermostat and temperature using that feature, removing the need of having to set the metadata scale parameter for each of the relevant items or groups. -A washer and its settings modeled with multiple mode interface capabilities. +Below are two examples; the scale on the first will be set to Fahrenheit based on how it is defined in the item state presentation pattern and the second one will be set based on your openHAB system [regional settings](#regional-settings) (US=Fahrenheit; SI=Celsius). +```xtend +Number:Temperature Temperature1 "Temperature [%.1f °F]" {alexa="CurrentTemperature"} +Number:Temperature Temperature2 "Temperature" {alexa="CurrentTemperature"} ``` -Group Washer "Washer" {alexa="Endpoint.Other"} -String Cycle "Cycle" (Washer) {alexa="ModeController.mode" [supportedModes="Normal=Normal:Cottons,Delicate=@Value.Delicate:Knits",friendlyNames="Wash Cycle,Wash Setting",ordered=false]} -Number Temperature "Temperature" (Washer) {alexa="ModeController.mode" [supportedModes="0=Cold:Cool,1=Warm,2=Hot",friendlyNames="Wash Temperature,@Setting.WaterTemperature",ordered=true]} -String Status "Status" (Washer) {alexa="ModeController.mode" [supportedModes="Washing,Rinsing,Spinning",friendlyNames="Wash Status",nonControllable=true]} -Switch Power "Power" (Washer) {alexa="PowerController.powerState"} + +## Networking Capabilities + +To interact with the networking capabilities of a router, such as controlling the network access for a specific device, the [networking attributes](#networking-attributes) are available to configure a representation of a home network and its connected devices. + +In order to be take advantage of these capabilities, your router must be configured as a [group endpoint](#group-endpoint) based on [`HomeNetwork`](#homenetwork) supported device types. If it doesn't have any other capabilities, it can be an empty group. Likewise, connected devices must be configured based on [`ConnectedDevice`](#connecteddevice) supported device types and metadata parameters. + +```xtend +Group Router "Router" {alexa="Router"} + +Group Laptop "Laptop" (Router) {alexa="Laptop" [macAddress="00:21:86:B5:6E:10"]} +Switch Access1 "Access" (Laptop) {alexa="NetworkAccess"} + +Group Tablet "Tablet" (Router) {alexa="Tablet" [macAddress="00:21:86:B5:6E:11"]} +Switch Access2 "Access" (Tablet) {alexa="NetworkAccess"} ``` -A fan and its settings modeled with a mix of range/toggle interface capabilities. + + +## Generic Capabilities + +For general-purpose capabilities that can be used to model different components of a device, which aren't covered by the existing [device attributes](#device-attributes), the [generic attributes](#generic-attributes) are available to highly customize how you interact with that device via Alexa, using various metadata parameters to model the full feature set of a complex device. + +A washer and its settings modeled with multiple mode-type generic attributes. +```xtend +Group Washer "Washer" {alexa="Washer"} +String Cycle "Cycle" (Washer) {alexa="Mode" [capabilityNames="Wash Cycle,Wash Setting", supportedModes="Normal=Normal:Cottons,Delicate=@Value.Delicate:Knits", ordered=false]} +Number Temperature "Temperature" (Washer) {alexa="Mode" [capabilityNames="Wash Temperature,@Setting.WaterTemperature", supportedModes="0=Cold:Cool,1=Warm,2=Hot", ordered=true]} +String Status "Status" (Washer) {alexa="Mode" [capabilityNames="Wash Status", supportedModes="Washing,Rinsing,Spinning", nonControllable=true]} +Switch Power "Power" (Washer) {alexa="PowerState"} ``` -Group Fan "Fan" {alexa="Endpoint.Fan"} -Number Speed "Speed" (Fan) {alexa="RangeController.rangeValue" [supportedRange="1:10:1",presets="1=@Value.Minimum:@Value.Low:Lowest,10=@Value.Maximum:@Value.High:Highest",friendlyNames="@Setting.FanSpeed,Speed"]} -Switch Rotate "Rotate" (Fan) {alexa="ToggleController.toggleState" [friendlyNames="@Setting.Oscillate,Rotate"]} -Switch Power "Power" (Fan) {alexa="PowerController.powerState"} + +A camera and its settings modeled with multiple range-type generic attributes. + +```xtend +Group Camera "Camera" {alexa="Camera"} +Number Pan "Pan" (Camera) {alexa="RangeValue" [capabilityNames="Pan,Rotate", supportedRange="-200:200:1", presets="-200=Far Left,0=Center,200=Far Right"]} +Number Tilt "Tilt" (Camera) {alexa="RangeValue" [capabilityNames="@Setting.Tilt", supportedRange="-50:50:1", presets="-50=@Value.Down,0=Center,50=@Value.Up"]} +Number Zoom "Zoom" (Camera) {alexa="RangeValue" [capabilityNames="Zoom", supportedRange="0:200:50", presets="0=@Value.Minimum,200=@Value.Maximum"]} +String Stream "Stream" (Camera) {alexa="CameraStream"} +Switch Power "Power" (Camera) {alexa="PowerState"} ``` -A router and its settings modeled with multiple toggle interface capabilities. +A fireplace and its settings modeled with a mix of range/mode-type generic attributes. +```xtend +Group Fireplace "Fireplace" {alexa="Other"} +Number Burners "Burners" (Fireplace) {alexa="RangeValue" [capabilityNames="@Setting.Preset", supportedRange="1:3:1", presets="1=@Value.Low:@Value.Minimum,2=@Value.Medium:Normal,3=@Value.High:@Value.Maximum"]} +String Flame "Flame" (Fireplace) {alexa="Mode" [capabilityNames="Flame Type", supportedModes="Campfire=:Normal,Candle,IceFlame=Ice Flame"]} +Color Color "Color" (Fireplace) {alexa="Color"} +Switch Power "Power" (Fireplace) {alexa="PowerState"} ``` -Group Router "Router" {alexa="Endpoint.NetworkHardware"} -Switch 2GGuestWiFi "2G Guest WiFi" (Router) {alexa="ToggleController.toggleState" [friendlyNames="@Setting.2GGuestWiFi"]} -Switch 5GGuestWiFi "5G Guest WiFi" (Router) {alexa="ToggleController.toggleState" [friendlyNames="@Setting.5GGuestWiFi"]} -Switch Power "Power" (Router) {alexa="PowerController.powerState"} + +A guitar amp and its settings modeled with a mix of range/mode/toggle-type generic attributes. + +```xtend +Group GuitarAmp "Guitar Amp" {alexa="Other"} +Switch Overdrive "Overdrive" (GuitarAmp) {alexa="ToggleState" [capabilityNames="Overdrive"]} +Switch Gain "Gain" (GuitarAmp) {alexa="RangeValue" [capabilityNames="Gain,Drive", supportedRange="1:10:1"]} +String Preset "Preset" (GuitarAmp) {alexa="Mode" [capabilityNames="@Setting.Preset,Effect", supportedModes="Normal=:Standard,LowGain=Low Gain,LeadBoost=Lead Boost,Metal"]} +Switch Volume "Volume" (GuitarAmp) {alexa="VolumeLevel"} +Switch Mute "Mute" (GuitarAmp) {alexa="MuteState"} +Number Bass "Bass" (GuitarAmp) {alexa="EqualizerBass"} +Number Midrange "Midrange" (GuitarAmp) {alexa="EqualizerMidrange"} +Number Treble "Treble" (GuitarAmp) {alexa="EqualizerTreble"} +Switch Power "Power" (GuitarAmp) {alexa="PowerState"} ``` -### Semantic Extensions -Semantic extensions are used to further customize how to interact with a device. This functionality is only supported by the [Mode](#modecontroller-mode), [Range](#rangecontroller-rangevalue) and [Toggle](#togglecontroller-togglestate) controllers. It currently provides "Close", "Open", "Lower" and "Raise" interactions, removing the need for the Alexa routine workaround to control certain devices such as blinds or doors. Each semantic is composed of action and state mappings. The actions are used for interacting with the device and the states for displaying its current semantic state in the Alexa app (Not available as of yet). The supported action and state names are listed in the [semantic catalog](#semantic-catalog). +A router and its settings modeled with a mix of mode/toggle-type generic attributes. -A standard blind with range interface capability (Metadata label: [`Blind`](#blind)). For example, requesting "Alexa, open the blind", the item state will be set to `100`. Likewise, asking "Alexa, lower the blind", the item state will be decreased by 10 from its current state. +```xtend +Group Router "Router" {alexa="Router"} +Switch 2GGuestWiFi "2G Guest WiFi" (Router) {alexa="ToggleState" [capabilityNames="@Setting.2GGuestWiFi"]} +Switch 5GGuestWiFi "5G Guest WiFi" (Router) {alexa="ToggleState" [capabilityNames="@Setting.5GGuestWiFi"]} +String Mode "Mode" (Router) {alexa="Mode" [capabilityNames="@Setting.Mode", supportedModes="Normal,Gaming,Streaming]} +``` + +A smart watch and its settings modeled with multiple read-only range-type generic attributes. +```xtend +Group SmartWatch "SmartWatch" {alexa="Wearable"} +Number Steps "Steps" (SmartWatch) {alexa="RangeValue" [capabilityNames="Steps", supportedRange="0:100000:1", nonControllable=true]} +Number Floors "Floors" (SmartWatch) {alexa="RangeValue" [capabilityNames="Floors", supportedRange="0:1000:1", nonControllable=true]} +Number Battery "Battery" (SmartWatch) {alexa="BatteryLevel"} ``` -Rollershutter Blind "Blind" {alexa="RangeController.rangeValue" [category="INTERIOR_BLIND", friendlyNames="@Setting.Opening", supportedRange="0:100:10", unitOfMeasure="Percent", actionMappings="Close=0,Open=100,Lower=(-10),Raise=(+10)", stateMappings="Closed=0,Open=1:100"]} + +## Semantic Extensions + +Semantic extensions are used to further customize how to interact with a device. This functionality is only supported by the [generic attributes](#generic-attributes). The Alexa API currently provides `Close`, `Open`, `Lower` and `Raise` interactions, removing the need for the Alexa routine workaround to control certain devices such as blinds or doors. Additionally, the skills now includes `Pause`, `Resume`, `Stop`, `TurnOff` and `TurnOn` custom interactions. Each semantic is composed of action and state mappings. The actions are used for interacting with the device and the states for displaying its current semantic state in the Alexa app (Not available as of yet). The supported action and state names are listed in the [semantic catalog](#semantic-catalog). + +The skill-based `Pause`, `Resume` and `Stop` semantics can only be set as action mappings. On the other side, the `TurnOn` and `TurnOff` semantics can be paired with `On` and `Off` state mappings to report a state if necessary (e.g. *Alexa, is `` `` on?*). These state mappings can also be set without action mappings for status purpose only, and can be defined, depending on the item type, as a specific value `On=ON`, a pipe-delimited list of values `On=LOW|MEDIUM|HIGH`, or a range `On=1:5`. + +It is important to note that besides `TurnOff` and `TurnOn` action and `Off`/`On` state semantics, only one semantic type is allowed per endpoint. Additionally, adjust action mappings (e.g `Raise=(+10)`) are only supported by Alexa API action semantics. + +Here is how some the [device attributes](#device-attributes) using semantic extensions are translating to: + +A window blind [position state](#position-state). For example, when requesting *Alexa, open the blind*, the item will receive command `UP`. Likewise, when asking *Alexa, lower the blind*, it will receive command `DOWN`. And when requesting *Alexa, stop the blind*, it will receive command `STOP`. For position request, since Rollershutter range value are inverted by default, when requesting *Alexa, set the blind to 40%*, the item state will be set to `60`. + +```xtend +Rollershutter Blind "Blind" {alexa="Blind.RangeValue" [capabilityNames="@Setting.Position", supportedCommands="UP=@Value.Up:@Value.Open,DOWN=@Value.Down:@Value.Close,STOP=@Value.Stop", supportedRange="0:100:1", unitOfMeasure="Percent", actionMappings="Close=DOWN,Open=UP,Lower=DOWN,Raise=UP", stateMappings="Closed=100,Open=0:99"]} ``` -A shutter with mode interface capability. For example, requesting "Alexa, open the shutter" or "Alexa, raise the shutter", the item state will be set to `Up`. +A window curtain [position state](#position-state). For example, when requesting *Alexa, open the curtain*, the item state will be set to `100`. Likewise, when asking *Alexa, close the blind*, it be set to `0`. +```xtend +Dimmer Curtain "Curtain" {alexa="Curtain.RangeValue" [capabilityNames="@Setting.Position", supportedRange="0:100:1", presets="0=@Value.Close,100=@Value.Open", unitOfMeasure="Percent", actionMappings="Close=0,Open=100", stateMappings="Closed=0,Open=1:100"]} ``` -String Shutter "Shutter" {alexa="ModeController.mode" [category="EXTERIOR_BLIND", friendlyNames="@Setting.Opening", supportedModes="Up=@Value.Open,Down=@Value.Close", actionMappings="Close=Down,Open=Up,Lower=Down,Raise=Up", stateMappings="Closed=Down,Open=Up"]} + +A door [open state](#open-state). For example, when requesting *Alexa, open the door*, the item state will be set to `ON`. + +```xtend +Switch Door "Door" {alexa="Door.Mode" [capabilityNames="@Setting.Opening", supportedModes="ON=@Value.Open,OFF=@Value.Close", actionMappings="Close=OFF,Open=ON,Lower=OFF,Raise=ON", stateMappings="Closed=OFF,Open=ON"]} ``` -A door with toggle interface capability (Metadata label: [`Door`](#door)). For example, requesting "Alexa, open the door", the item state will be set to `ON`. +A vacuum cleaner [mode](#vacuum-mode). For example, when requesting *Alexa, turn on the vacuum cleaner*, the item state will be set to `CLEAN`. Likewise, when asking *Alexa, pause the vacuum cleaner*, it be set to `PAUSE`. And when requesting *Alexa, resume the vacuum cleaner*, it will be set to `CLEAN` again. +```xtend +String VacuumCleaner "Vacuum Cleaner" {alexa="VacuumCleaner.Mode" [capabilityNames="@Setting.Mode", supportedModes="CLEAN=@Setting.Clean,DOCK=@Setting.Dock,SPOT=@Setting.Spot,PAUSE=@Setting.Pause,STOP=@Setting.Stop", actionMappings="Resume=DOCK,Pause=PAUSE,Stop=STOP,TurnOn=CLEAN,TurnOff=DOCK", stateMappings="Off=DOCK|PAUSE|STOP,On=CLEAN|SPOT"]} ``` -Switch Door "Door" {alexa="ToggleController.toggleState" [category="DOOR", friendlyNames="@Setting.Opening", actionMappings="Close=OFF,Open=ON", stateMappings="Closed=OFF,Open=ON"]} + +# Item Configuration + +In order to configure an Alexa endpoint, one or more device configuration, composed of a [type](#device-types) and an [attribute](#device-attributes) `{alexa="."}`, must be defined in the "Alexa" item metadata settings. Depending on the type of endpoint being configured, the device type or attribute can be omitted. + +For [single endpoints](#single-endpoint), when a device is only composed of a type, the default attribute(s) of that type are used. Using the single dimmer light shorthand example from above, the `Light` device type default attributes for a "Dimmer" item are [`PowerState`](#powerstate) and [`Brightness`](#brightness). The fully qualified definition would be: + +```xtend +Dimmer LightSwitch "Light Switch" {alexa="Light.PowerState,Light.Brightness"} // Equivalent to {alexa="Light"} ``` -### Item Sensor -Whenever, a device in openHAB uses a separate channel for its status, that item (called "sensor") can be mapped in the actionable item parameters. This feature is design to improve state reporting accuracy by allowing the property state of the sensor item to be reported over the actionable one. It is configured by adding the metadata parameter `itemSensor=`. +Likewise, when a device is only composed of an attribute, its type would be derived from the default category of each configured attribute. Using the same example again, using [`PowerState`](#powerstate) and [`Brightness`](#brightness) attributes, the categories would be respectively "SWITCH" and "LIGHT" with the former being the main endpoint display category. While not providing a device type is supported, it highly recommended to always specify one, when configuring a single endpoint, to prevent potential functionality limitations on the Alexa end. -It is important to note that sensor items need to be the same type than their parent item, except for LockController capable items. Additionally, since deferred reporting is not supported by the skill as of yet, their state will need to be available right away for the skill to report the device latest status. +```xtend +Dimmer LightSwitch "Light Switch" {alexa="PowerState,Brightness"} +``` -Below is an example of a lock device using an item sensor. +For [group endpoints](#group-endpoint), the metadata at the group item level can only be a device type. This defines the endpoint category for all the item capabilities part of it and the supported attributes. The associated items metadata configuration doesn't need to specify that same device type unless aiming to use the default attributes of that device type. Each attribute needs to be supported by the group device type, otherwise they would be ignored. Using the group smart color bulb example above, the fully qualified definition would be: +```xtend +Group Bulb "Bulb" {alexa="Light"} +Color Color "Color" (Bulb) {alexa="Light.PowerState,Light.Brightness,Light.Color"} +Dimmer Temperature "Temperature" (Bulb) {alexa="Light.ColorTemperature"} ``` -Switch LockControl "Lock" {alexa="LockController.lockState" [itemSensor="LockStatus"]} -Contact LockStatus "Status" + +A better way to configure this endpoint, since the `Light` device type default attributes for a "Color" item are [`PowerState`](#powerstate), [`Brightness`](#brightness) and [`Color`](#color), the device type with no attribute can be used as well at the item capability level: + +```xtend +Group Bulb "Bulb" {alexa="Light"} +Color Color "Color" (Bulb) {alexa="Light"} // Equivalent to {alexa="PowerState,Brightness,Color"} +Dimmer Temperature "Temperature" (Bulb) {alexa="ColorTemperature"} ``` -### Item State -Item states, reported back to Alexa, are formatted based on their [item state presentation](https://www.openhab.org/docs/configuration/items.html#state-presentation) definition if configured. This means you can control the precision of number values (e.g. `%.1f °C` will limit reported temperature value to one decimal point). + + -For items that don't have a state, these can be configured as not retrievable, automatically when the item [parameter `autoupdate`](https://www.openhab.org/docs/configuration/items.html#parameter-autoupdate) is set as `autoupdate=false` or by using metadata parameter `itemStateRetrievable=false`. In that case, Alexa will not retrieve the given item state, and when a command is issued against that item, the requested state will be returned back without checking the current state in openHAB. If using this feature in a group endpoint, keep in mind that all associated items will need to be configured to either report or not report a state, otherwise the Alexa integration for that endpoint will be broken. +## Device Types -### Item Unit of Measurement -With the introduction of the [unit of measurement](https://www.openhab.org/docs/concepts/units-of-measurement.html) concept, the item unit can be automatically determined for thermostat and temperature using that feature, removing the need of having to set the metadata scale parameter for each of the relevant items or groups. +A device type represents an [Alexa display category](https://developer.amazon.com/docs/device-apis/alexa-discovery.html#display-categories) that affects how the endpoint appears in the [Alexa app](https://developer.amazon.com/docs/smarthome/best-practices-for-the-alexa-app.html#how-smart-home-devices-display-in-the-alexa-app) and in some cases, the associated features. -Below are two examples; the scale on the first will be set to Fahrenheit based on how it is defined in the item state presentation pattern and the second one will be set based on your openHAB system regional settings (US=Fahrenheit; SI=Celsius). +It is important to note that all the below device types supports the [generic attributes](#generic-attributes). -``` -Number:Temperature Temperature1 "Temperature [%.1f °F]" {alexa="TemperatureSensor.temperature"} -Number:Temperature Temperature2 "Temperature" {alexa="TemperatureSensor.temperature"} -``` +Default attributes for each type are displayed in _italic_ and are depending on supported item types. -## Item Configuration +Device Types | Supported Attributes | Description +-------------|----------------------|------------ +`AirConditioner` | _[`HeatingCoolingMode`](#heatingcoolingmode)_, [`TargetTemperature`](#targettemperature), [`CurrentTemperature`](#currenttemperature), [`FanSpeed`](#fanspeed), [`FanDirection`](#fandirection), [`FanOscillate`](#fanoscillate) | A device that cools the air in interior spaces. +`AirFreshener` | Same as `Fan` | A device that emits pleasant odors and masks unpleasant odors in interior spaces. +`AirPurifier` | Same as `Fan` | A device that improves the quality of air in interior spaces. +`Automobile` | [`BatteryLevel`](#batterylevel), [`FanSpeed`](#fanspeed), [`LockState`](#lockstate), [`PowerState`](#powerstate), [`CurrentTemperature`](#currenttemperature) | A motor vehicle (automobile, car). +`AutomobileAccessory` | [`BatteryLevel`](#batterylevel), [`CameraStream`](#camerastream), [`FanSpeed`](#fanspeed), [`PowerState`](#powerstate) | A smart device in an automobile, such as a dash camera. +`Blind`, `Curtain`, `Shade` | _[`OpenState`](#openstate)_, _[`PositionState`](#positionstate)_, [`TiltAngle`](#tiltAngle), [`TargetOpenState`](#targetopenstate), [`CurrentOpenState`](#currentopenstate) | A window covering on the inside of a structure. +`BluetoothSpeaker` | _[`PowerState`](#powerstate)_, _[`VolumeLevel`](#volumelevel)_, [`MuteState`](#mutestate), [`EqualizerBass`](#equalizerbass), [`EqualizerMidrange`](#equalizermidrange), [`EqualizerTreble`](#equalizertreble), [`EqualizerMode`](#equalizermode), [`Channel`](#channel), [`Input`](#input), [`Playback`](#playback), [`PlaybackStop`](#playbackstop), [`Navigation`](#navigation), [`BatteryLevel`](#batterylevel) | A speaker that connects to an audio source over Bluetooth. +`Camera` | _[`PowerState`](#powerstate)_, _[`CameraStream`](#camerastream)_, [`BatteryLevel`](#batterylevel) | A security device with video or photo functionality. +`ChristmasTree` | Same as `Light` | A religious holiday decoration that often contains lights. +`CoffeeMaker` | _[`PowerState`](#powerstate)_ | A device that makes coffee. +`Computer` | _[`PowerState`](#powerstate)_, [`NetworkAccess`](#networkaccess) | A non-mobile computer, such as a desktop computer. +`ContactSensor` | _[`ContactDetectionState`](#contactdetectionstate)_, [`BatteryLevel`](#batterylevel) | An endpoint that detects and reports changes in contact between two surfaces. +`Dishwasher` | _[`PowerState`](#powerstate)_ | A device that cleans dishes. +`Door` | _[`OpenState`](#openstate)_, [`TargetOpenState`](#targetopenstate), [`CurrentOpenState`](#currentopenstate) | A door. +`Doorbell` | Same as `Camera` | A doorbell. +`Dryer` | _[`PowerState`](#powerstate)_ | A device that dries wet clothing. +`Fan` | _[`PowerState`](#powerstate)_, _[`FanSpeed`](#fanspeed)_, [`FanDirection`](#fandirection), [`FanOscillate`](#fanoscillate) | A fan. +`GameConsole` | _[`PowerState`](#powerstate)_, [`NetworkAccess`](#networkaccess) | A game console, such as Microsoft Xbox or Nintendo Switch. +`GarageDoor` | _[`OpenState`](#openstate)_, [`TargetOpenState`](#targetopenstate), [`CurrentOpenState`](#currentopenstate), [`ObstacleAlert`](#obstaclealert), [`SafetyBeamAlert`](#safetybeamalert) | A garage door. Supports unlock by voice code. Only supported in `en-US`. For other languages, use `Door` instead. +`Headphones` | Same as `BluetoothSpeaker` | A wearable device that transmits audio directly into the ear. +`Hub` | _[`PowerState`](#powerstate)_ | A smart-home hub. +`Laptop` | _[`PowerState`](#powerstate)_, [`BatteryLevel`](#batterylevel), [`NetworkAccess`](#networkaccess) | A laptop or other mobile computer. +`Light` | _[`PowerState`](#powerstate)_, _[`Brightness`](#brightness)_, _[`Color`](#color)_, [`ColorTemperature`](#colortemperature) | A light source or fixture. +`Lock` | _[`LockState`](#lockstate)_, [`TargetLockState`](#targetlockstate), [`CurrentLockState`](#currentlockstate), [`BatteryLevel`](#batterylevel) | An endpoint that locks. +`Microwave` | _[`PowerState`](#powerstate)_ | A microwave oven. +`MobilePhone` | _[`PowerState`](#powerstate)_, [`BatteryLevel`](#batterylevel), [`NetworkAccess`](#networkaccess) | A mobile phone. +`MotionSensor` | _[`MotionDetectionState`](#motiondetectionstate)_, [`BatteryLevel`](#batterylevel) | An endpoint that detects and reports movement in an area. +`MusicSystem` | Same as `StreamingDevice` | A network-connected music system. +`NetworkHardware` | _[`PowerState`](#powerstate)_ | A network router. +`Outlet` | Same as `Switch` | A module that is plugged into an existing electrical outlet, and then has a device plugged into it. +`Oven` | _[`PowerState`](#powerstate)_ | An oven cooking appliance. +`Phone` | _[`PowerState`](#powerstate)_ | A non-mobile phone, such as landline or an IP phone. +`Printer` | _[`PowerState`](#powerstate)_ | A device that prints. +`Router` | Same as `NetworkHardware` | A network router. +`Screen` | Same as `Television` | A projector screen. +`SecurityPanel` | _[`ArmState`](#armstate)_, [`BurglaryAlarm`](#burglaryalarm), [`CarbonMonoxideAlarm`](#carbonmonoxidealarm), [`FireAlarm`](#firealarm), [`WaterAlarm`](#wateralarm), [`AlarmAlert`](#alarmalert), [`ReadyAlert`](#readyalert), [`TroubleAlert`](#troublealert), [`ZonesAlert`](#zonealert) | A security panel. +`SecuritySystem` | Same as `SecurityPanel` | A security system. +`Shutter`, `Awning` | Same as `Blind` | A window covering on the outside of a structure. +`SlowCooker` | _[`PowerState`](#powerstate)_ | An electric cooking device that sits on a countertop, cooks at low temperatures, and is often shaped like a cooking pot. +`Speaker` | _[`PowerState`](#powerstate)_, _[`VolumeLevel`](#volumelevel)_, [`MuteState`](#mutestate), [`EqualizerBass`](#equalizerbass), [`EqualizerMidrange`](#equalizermidrange), [`EqualizerTreble`](#equalizertreble), [`EqualizerMode`](#equalizermode), [`Channel`](#channel), [`Input`](#input), [`Playback`](#playback), [`PlaybackStop`](#playbackstop), [`Navigation`](#navigation) | A speaker or speaker system. +`StreamingDevice` | _[`PowerState`](#powerstate)_, _[`Playback`](#playback)_, [`PlaybackStop`](#playbackstop), [`Navigation`](#navigation), [`Channel`](#channel), [`Input`](#input), [`VolumeLevel`](#volumelevel), [`MuteState`](#mutestate), [`EqualizerBass`](#equalizerbass), [`EqualizerMidrange`](#equalizermidrange), [`EqualizerTreble`](#equalizertreble), [`EqualizerMode`](#equalizermode) | A streaming device such as Apple TV, Chromecast, or Roku. +`Switch` | _[`PowerState`](#powerstate)_, _[`PowerLevel`](#powerlevel)_, _[`Percentage`](#percentage)_ | A switch wired directly to the electrical system. A switch can control a variety of devices. For lighting devices, use `Light` instead. +`Tablet` | _[`PowerState`](#powerstate)_, [`BatteryLevel`](#batterylevel), [`NetworkAccess`](#networkaccess) | A tablet computer. +`Television` | _[`PowerState`](#powerstate)_, _[`Channel`](#channel)_, [`Input`](#input), [`VolumeLevel`](#volumelevel), [`MuteState`](#mutestate), [`EqualizerBass`](#equalizerbass), [`EqualizerMidrange`](#equalizermidrange), [`EqualizerTreble`](#equalizertreble), [`EqualizerMode`](#equalizermode), [`Playback`](#playback), [`PlaybackStop`](#playbackstop), [`Navigation`](#navigation) | A television. +`TemperatureSensor` | _[`CurrentTemperature`](#currenttemperature)_, [`BatteryLevel`](#batterylevel) | An endpoint that reports temperature, but does not control it. The temperature data of the endpoint doesn't appear in the Alexa app. If your endpoint also controls temperature, use `Thermostat` instead. +`Thermostat` | _[`HeatingCoolingMode`](#heatingcoolingmode)_, [`TargetTemperature`](#targettemperature), [`CoolingSetpoint`](#coolingsetpoint), [`HeatingSetpoint`](#heatingsetpoint), [`EcoCoolingSetpoint`](#ecocoolingsetpoint), [`EcoHeatingSetpoint`](#ecoheatingsetpoint), [`ThermostatHold`](#thermostathold), [`ThermostatFan`](#thermostatfan), [`CurrentTemperature`](#currenttemperature), [`CurrentHumidity`](#currenthumidity), [`BatteryLevel`](#batterylevel) | An endpoint that controls temperature, stand-alone air conditioners, or heaters with direct temperature control. If your endpoint senses temperature but does not control it, use `TemperatureSensor` instead. +`VacuumCleaner` | _[`PowerState`](#powerstate)_, _[`VacuumMode`](#vacuummode)_, [`FanSpeed`](#fanspeed), [`BatteryLevel`](#batterylevel) | A vacuum cleaner. +`Washer` | _[`PowerState`](#powerstate)_ | A device that cleans clothing. +`WaterHeater` | _[`PowerState`](#powerstate)_, [`TargetTemperature`](#targettemperature), [`CurrentTemperature`](#currenttemperature) | A device that heats water, often consisting of a large tank. +`Wearable`| _[`PowerState`](#powerstate)_, [`BatteryLevel`](#batterylevel), [`NetworkAccess`](#networkaccess) | A network-connected wearable device, such as an Apple Watch, Fitbit, or Samsung Gear. +`Other`| [All attributes](#device-attributes), except [networking](#networking-attributes) and [scenes](#scene-attributes) | An endpoint that doesn't belong to one of the other categories. -### Supported Item Metadata -The following are a list of supported metadata. It is important to note that not all the capabilities listed below are [available](#regional-availability) globally. +## Device Attributes -#### `PowerController.powerState` -* Items that turn on or off such as light switches, power states, etc.. -* Supported item type: - * Color - * Dimmer - * Switch -* Default category: SWITCH +A device attribute represents one or more [Alexa Smart Home interface capabilities](https://developer.amazon.com/docs/device-apis/list-of-interfaces.html) that defines the supported functionalities of a given device. -#### `BrightnessController.brightness` -* Items which response to percentage level and brightness commands (dim, brighten, percent), typically lights. -* Supported item type: - * Color - * Dimmer -* Default category: LIGHT +For device attributes used in a [group endpoint](#group-endpoint), if multiple items with the same attribute are part of a group, only the first one will be considered while the others will be ignored. This doesn't apply to [generic attributes](#generic-attributes). -#### `PowerLevelController.powerLevel` -* Items which respond to a specific number setting -* Supported item type: - * Dimmer -* Default category: SWITCH +Any group level metadata parameters are passed to each members part of that group. This is useful when the same parameter is used across multiple item capabilities of a group endpoint. For example, the `scale` temperature/setpoint parameter in a `Thermostat` group. -#### `PercentageController.percentage` -* Items which respond to percentage commands such as roller shutters. -* Supported item type: - * Dimmer - * Rollershutter -* Default category: OTHER +It is important to note that not all the attributes listed below are [available](#regional-availability) globally. + +### Camera Attributes -#### `ThermostatController.targetSetpoint` -* Items that represent a target setpoint for a thermostat. The scale is determined based on: (1) value set in parameter `scale="Fahrenheit"`; (2) unit of item state presentation (`°F`=Fahrenheit; `°C`=Celsius); (3) your openHAB server regional measurement system or region settings (US=Fahrenheit; SI=Celsius); (4) defaults to Celsius. By default, the temperature range is limited to predefined setpoint values based on the scale parameter. If necessary, the temperature range can be customized using parameter `setpointRange="60:90"`. When paired with `ThermostatController.thermostatMode`, setpoint requests will be ignored when the thermostat mode is off. -* Supported item type: - * Number(:Temperature) +#### `CameraStream` + +Items that represent the feed from a security camera. + +It requires installing the [IP Camera binding](https://www.openhab.org/addons/bindings/ipcamera/) to create a [HLS live stream](https://www.openhab.org/addons/bindings/ipcamera/#hls-http-live-streaming), and running your [openHAB server behind a reverse proxy](https://www.openhab.org/docs/installation/security.html#running-openhab-behind-a-reverse-proxy) that can be accessed over HTTPS on your local network and port 443 using a valid SSL certificate. + +Once setup, configure the item linked to the binding `hlsUrl` channel and set the metadata parameter `proxyBaseUrl="https://openhab.myserver.tld"`. This will cause the skill to provide a stream URL to your Echo device, when requested, that should be accessible at `https://openhab.myserver.tld/ipcamera/camera1/ipcamera.m3u8` along with a static image URL, replacing the extension with `.jpg`. If your server requires basic authentication, set the `username` and `password` parameters. + +* Supported item types: + * String * Supported metadata parameters: - * scale=`` - * Celsius [4°C -> 32°C] - * Fahrenheit [40°F -> 90°F] - * setpointRange=`` - * defaults to defined scale range listed above if omitted -* Default category: THERMOSTAT + * proxyBaseUrl=`` + * required proxy base URL + * resolution=`` + * supported resolutions are `480p`, `720p`, `1080p` + * defaults to `1080p` + * username=`` + * defaults to no basic authentication. + * password=`` + * defaults to no basic authentication. +* Utterance examples: + * *Alexa, show the ``.* -#### `ThermostatController.upperSetpoint` -* Items that represent a upper or COOL setpoint for a thermostat. This needs to be paired with `ThermostatController.lowerSetpoint`. The scale is determined based on: (1) value set in parameter `scale="Fahrenheit"`; (2) unit of item state presentation (`°F`=Fahrenheit; `°C`=Celsius); (3) your openHAB server regional measurement system or region settings (US=Fahrenheit; SI=Celsius); (4) defaults to Celsius. By default, the temperature range is limited to predefined setpoint values based on the scale parameter. If necessary, the temperature range can be customized using parameter `setpointRange="60:90"`. When paired with `ThermostatController.thermostatMode`, setpoint requests and responses will be limited based on the current thermostat mode as follows: (1) thermostat mode cannot be off to set/adjust a setpoint temperature; (2) set/adjust upper or lower setpoint to single point target temperature in dual mode with, respectively, thermostat cooling or heating mode. (3) thermostat auto and eco mode will be considered in dual mode if setpoints defined, otherwise in single mode. Additionally, for integration that uses separate upper and lower setpoints for eco mode (e.g. Nest), suffix `#eco` can be appended to the metadata property `ThermostatController.upperSetpoint#eco` to differentiate that property from the standard ones. For triple mode support, the setpoint mode automation will need to be disabled by adding parameter `supportsSetpointMode=false` to the [thermostat mode](#thermostatcontroller-thermostatmode) item configuration. -* Supported item type: - * Number(:Temperature) -* Supported metadata parameters: - * scale=`` - * Celsius [4°C -> 32°C] - * Fahrenheit [40°F -> 90°F] - * comfortRange=`` - * used in dual setpoint mode to determine: - * the new upper/lower setpoints spread based on target setpoint - * the minimum temperature delta between requested upper/lower setpoints by adding relevant comfort range values - * defaults to 2°F or 1°C - * setpointRange=`` - * defaults to defined scale range listed above if omitted -* Default category: THERMOSTAT +### Cover Attributes -#### `ThermostatController.lowerSetpoint` -* Items that represent a lower or HEAT setpoint for a thermostat. This needs to be paired with `ThermostatController.upperSetpoint`. The scale is determined based on: (1) value set in parameter `scale="Fahrenheit"`; (2) unit of item state presentation (`°F`=Fahrenheit; `°C`=Celsius); (3) your openHAB server regional measurement system or region settings (US=Fahrenheit; SI=Celsius); (4) defaults to Celsius. By default, the temperature range is limited to predefined setpoint values based on the scale parameter. If necessary, the temperature range can be customized using parameter `setpointRange="60:90"`. When paired with `ThermostatController.thermostatMode`, setpoint requests and responses will be limited based on the current thermostat mode as follows: (1) thermostat mode cannot be off to set/adjust a setpoint temperature; (2) set/adjust upper or lower setpoint to single point target temperature in dual mode with, respectively, thermostat cooling or heating mode. (3) thermostat auto and eco mode will be considered in dual mode if setpoints defined, otherwise in single mode. Additionally, for integration that uses separate upper and lower setpoints for eco mode (e.g. Nest), suffix `#eco` can be appended to the metadata property `ThermostatController.lowerSetpoint#eco` to differentiate that property from the standard ones. For triple mode support, the setpoint mode automation will need to be disabled by adding parameter `supportsSetpointMode=false` to the [thermostat mode](#thermostatcontroller-thermostatmode) item configuration. -* Supported item type: - * Number(:Temperature) +#### `OpenState` + +Items that represent the open state of a door or window blind (ON open, OFF close). For decouple state support, use [`TargetOpenState`](#targetopenstate) and [`CurrentOpenState`](#currentopenstate) instead. For door contact sensors, use [`ContactDetectionState`](#contactdetectionstate) instead. + +* Supported item types: + * Switch * Supported metadata parameters: - * scale=`` - * Celsius [4°C -> 32°C] - * Fahrenheit [40°F -> 90°F] - * comfortRange=`` - * used in dual setpoint mode to determine: - * the new upper/lower setpoints spread based on target setpoint - * the minimum temperature delta between requested upper/lower setpoints by adding relevant comfort range values - * defaults to 2°F or 1°C - * setpointRange=`` - * defaults to defined scale range listed above if omitted -* Default category: THERMOSTAT + * inverted=`` + * set to true to invert state + * defaults to false +* Utterance examples: + * *Alexa, open the ``.* + * *Alexa, close the ``.* + * *Alexa, raise the ``.* + * *Alexa, lower the ``.* + * *Alexa, is the `` opened?* ([`GarageDoor`](#device-types) type only) + * *Alexa, what's the `` opening?* -#### `ThermostatController.thermostatMode` -* Items that represent the mode for a thermostat, default string values are `OFF="off",HEAT="heat",COOL="cool",ECO="eco",AUTO="auto"`, but these can be mapped to other values in the metadata. The mapping can be, in order of precedence, user-defined (AUTO=3,...) or preset-based related to the thermostat binding used (binding=``). For the binding parameter, it will be automatically determined if the associated item is using a 2.x addon (via channel metadata). If neither of these settings are provided, for thermostats that only support a subset of the standard modes, a comma delimited list of the Alexa supported modes should be set using the supportedModes parameter, otherwise, the supported list will be compiled based of the default mapping. -* Supported item type: - * Number - * String - * Switch (Heating only) +#### `TargetOpenState` + +Items that represent the target open state of a door or window blind with decouple state. This should be paired with [`CurrentOpenState`](#currentopenstate). + +Same configuration as [`OpenState`](#openstate). + +#### `CurrentOpenState` + +Items that represent the current open state of a door or window blind with decouple state. This needs to be paired with [`TargetOpenState`](#targetopenstate). The state of this item will be returned instead of the original actionable item. + +* Supported item types: + * Contact [CLOSED="CLOSED", OPEN="OPEN"] + * Number [CLOSED=0, OPEN=1] + * String [CLOSED="CLOSED", OPEN="OPEN"] + * Switch [CLOSED="OFF", OPEN="ON"] * Supported metadata parameters: - * OFF=`` - * HEAT=`` - * COOL=`` - * ECO=`` - * AUTO=`` - * binding=`` - * [daikin](https://www.openhab.org/addons/bindings/daikin/) [HEAT="HEAT", COOL="COLD", AUTO="AUTO"] - * [ecobee1](https://www.openhab.org/addons/bindings/ecobee1/) [OFF="off", HEAT="heat", COOL="cool", AUTO="auto"] - * [max](https://www.openhab.org/addons/bindings/max/) [HEAT="MANUAL", ECO="VACATION", AUTO="AUTOMATIC"] - * [nest](https://www.openhab.org/addons/bindings/nest/) [OFF="OFF", HEAT="HEAT", COOL="COOL", ECO="ECO", AUTO="HEAT_COOL"] - * [nest1](https://www.openhab.org/addons/bindings/nest1/) [OFF="off", HEAT="heat", COOL="cool", ECO="eco", AUTO="heat-cool"] - * [zwave](https://www.openhab.org/addons/bindings/zwave/) [OFF=0, HEAT=1, COOL=2, AUTO=3] - * [zwave1](https://www.openhab.org/addons/bindings/zwave1/) [OFF=0, HEAT=1, COOL=2, AUTO=3] - * defaults to [OFF="off", HEAT="heat", COOL="cool", ECO="eco", AUTO="auto"] if omitted - * supportedModes=`` - * defaults to, depending on the parameters provided, either user-based, preset-based or default item type-based mapping. - * supportsSetpointMode=`` - * set to false to disable the thermostat setpoint mode-aware feature (Refer to upper/lower setpoints documentation for more information) - * defaults to true -* Default category: THERMOSTAT + * CLOSED=`` (Number/String only) + * OPEN=`` (Number/String only) + * inverted=`` (Contact/Switch only) + * set to true to invert state + * defaults to false -#### `TemperatureSensor.temperature` -* Items that represent the current temperature. The scale is determined based on: (1) value set in parameter `scale="Fahrenheit"`; (2) unit of item state presentation (`°F`=Fahrenheit; `°C`=Celsius); (3) your openHAB server regional measurement system or region settings (US=Fahrenheit; SI=Celsius); (4) defaults to Celsius. -* Supported item type: - * Number(:Temperature) +#### `ObstacleAlert` + +Items that represent the alert state when an obstacle is detected preventing closing a garage door. This needs to be paired with [`OpenState`](#openstate). This attribute only works with [`GarageDoor`](#device-types) type. When in alert state, close requests will trigger an error response. + +* Supported item types: + * Contact [OK="CLOSED", ALERT="OPEN"] + * Switch [OK="OFF", ALERT="ON"] * Supported metadata parameters: - * scale=`` - * Celsius - * Fahrenheit -* Default category: TEMPERATURE_SENSOR + * inverted=`` + * set to true to invert item state + * defaults to false -#### `LockController.lockState` -* Items that represent the state of a lock (ON lock, OFF unlock). When associated to an [item sensor](#item-sensor), the state of that item will be returned instead of the original actionable item. Additionally, when linking to such item, multiple properties to one state can be mapped with column delimiter (e.g. for a Z-Wave lock: `LOCKED="1:3",UNLOCKED="2:4",JAMMED=11`). -* Supported item type: - * Switch -* Supported sensor type: - * Contact [LOCKED="CLOSED", UNLOCKED="OPEN"] - * Number [LOCKED=1, UNLOCKED=2, JAMMED=3] - * String [LOCKED="locked", "UNLOCKED"="unlocked", JAMMED="jammed"] - * Switch [LOCKED="ON", UNLOCKED="OFF"] +#### `SafetyBeamAlert` + +Items that represent the alert state when a safety beam was breached preventing closing a garage door. This needs to be paired with [`OpenState`](#openstate). This attribute only works with [`GarageDoor`](#device-types) type. When in alert state, close requests will trigger an error response. + +* Supported item types: + * Contact [OK="CLOSED", ALERT="OPEN"] + * Switch [OK="OFF", ALERT="ON"] * Supported metadata parameters: - * LOCKED=`` - * UNLOCKED=`` - * JAMMED=`` - * defaults based on item sensor type if omitted -* Default category: SMARTLOCK - -#### `ColorController.color` -* Items that represent a color -* Supported item type: - * Color -* Default category: LIGHT + * inverted=`` + * set to true to invert item state + * defaults to false -#### `ColorTemperatureController.colorTemperatureInKelvin` -* Items that represents a color temperature, default increment value may be specified in metadata parameters. For dimmer typed items adjustments, INCREASE/DECREASE commands will be sent instead if increment value not defined, while number typed items will default to 500K increments. Optionally, the supported temperature range in Kelvin can be provided using parameter `range="2700:6500"`. Preset-based range values will automatically be used based on the binding name and thing type (to differentiate color/white ranges), if the associated item is linked to one of the addons listed below (via channel metadata). Otherwise, to use these preset settings, use the parameter `binding=hue` or `binding=hue:white`. By default, the color type preset-based range values are used if the binding name is provided and the device/thing type cannot be determined. It is important to note that temperature adjustment requests for endpoints including a color item, will be rejected if the endpoint is in color mode (Dimmer => undefined temperature or color saturation > 0; Number => undefined temperature or temperature = 0). In that event, set the initial white level before requesting subsequent adjustments. -* Supported item type: - * Dimmer: colder (0%) to warmer (100%) based on defined temperature range [bindings integration] - * Number: color temperature value in Kelvin [custom integration] +#### `PositionState` + +Items that represent the position state of window blind. + +If paired with [`TiltAngle`](#tiltangle), the primary controls (open/close/stop) can be defined as position-based or tilt-based setting metadata parameter `primaryControl="position"` at the group level. It is important to note that raise/lower controls aren't affected by these settings and will remain position-based. + +* Supported item types: + * Dimmer + * Rollershutter * Supported metadata parameters: - * increment=`` - * value in % for dimmer item/in Kelvin for number item - * defaults to increment=INCREASE/DECREASE (Dimmer) or increment=500 (Number) if omitted - * range=`` - * values in Kelvin - * defaults to `1000:10000` if omitted or no binding preset-based range values found - * binding=`` - * [hue](https://www.openhab.org/addons/bindings/hue/) [color=`2000:6500`, white=`2200:6500`] - * [lifx](https://www.openhab.org/addons/bindings/lifx/) [color=`2500:9000`, white=`2700:6500`] - * [milight](https://www.openhab.org/addons/bindings/milight/) [color=`2700:6500`, white=`2700:6500`] - * [tradfri](https://www.openhab.org/addons/bindings/tradfri/) [color=`1780:6000`, white=`2200:4000`] - * [yeelight](https://www.openhab.org/addons/bindings/yeelight/) [color=`1700:6500`, white=`2700:6500`] -* Default category: LIGHT - -#### `SceneController.scene` -* Items that represent a scene or an activity depending on defined category and may be set not to support deactivation requests based on metadata parameters. -* Supported item type: - * Switch + * inverted=`` + * set to true to invert state + * defaults to true for Rollershutter, otherwise false for Dimmer + * primaryControl=`` + * supported types are `position` or `tilt` + * only relevant when part of a [group endpoint](#group-endpoint) + * defaults to `position` + * presets=`` + * each preset formatted as `=<@assetIdOrName1>:...` (e.g. `presets="20=Morning,60=Afternoon,80=Evening:@Setting.Night"`) + * predefined [asset ids](#asset-catalog) + * defaults to item state description options `presets="value1=label1,..."` if defined, otherwise supported controls presets + * language=`` + * text-based preset name language support + * two-letter language code: `de`, `en`, `es`, `fr`, `hi`, `it`, `ja`, `pt` + * defaults to your server [regional settings](#regional-settings) if defined, otherwise `en` +* Utterance examples: + * *Alexa, open the ``.* + * *Alexa, close the ``.* + * *Alexa, raise the ``.* + * *Alexa, lower the ``.* + * *Alexa, stop the ``.* (Rollershutter only) + * *Alexa, set the `` position to 50 percent.* + * *Alexa, set the `` position to ``.* + * *Alexa, set the `` position to open.* + * *Alexa, set the `` position to close.* + * *Alexa, set the `` position to up.* (Rollershutter only) + * *Alexa, set the `` position to down.* (Rollershutter only) + * *Alexa, set the `` position to stop.* (Rollershutter only) + * *Alexa, increase the `` position by 10 percent.* + * *Alexa, decrease the `` position by 25 percent.* + * *Alexa, what's the `` position?* + +#### `TiltAngle` + +Items that represent the title angle of a window blind. + +If paired with [`PositionState`](#positionstate), the primary controls (open/close/stop) can be defined as position-based or tilt-based setting metadata parameter `primaryControl="tilt"` at the group level. + +* Supported item types: + * Dimmer (Percentage) + * Number(:Angle) (Angle degree from -90 to 90) + * Rollershutter (Percentage) * Supported metadata parameters: - * supportsDeactivation=`` - * true (default if omitted) - * false -* Default category: SCENE_TRIGGER - -#### `ChannelController.channel` -* Items that represent a channel. A channel mapping may be specified in metadata parameters allowing channel request by name. It is important to note only well-known channel names can be used as these are validated against a database on the Alexa side when requested. Unfortunately, Amazon doesn't provide a list of supported channel names. -* Supported item type: + * inverted=`` + * set to true to invert state + * defaults to true for Rollershutter, otherwise false for Dimmer/Number + * primaryControl=`` + * supported types are `position` or `tilt` + * only relevant when part of a [group endpoint](#group-endpoint) + * defaults to `position` + * presets=`` + * each preset formatted as `=<@assetIdOrName1>:...` (e.g. `presets="20=Morning,60=Afternoon,80=Evening:@Setting.Night"`) + * predefined [asset ids](#asset-catalog) + * defaults to item state description options `presets="value1=label1,..."` if defined, otherwise supported controls presets + * language=`` + * text-based preset name language support + * two-letter language code: `de`, `en`, `es`, `fr`, `hi`, `it`, `ja`, `pt` + * defaults to your server [regional settings](#regional-settings) if defined, otherwise `en` +* Utterance examples: + * *Alexa, open the ``.* + * *Alexa, close the ``.* + * *Alexa, stop the ``.* (Rollershutter only) + * *Alexa, set the `` tilt to 30 degrees.* (Number only) + * *Alexa, set the `` tilt to 50 percent.* (Dimmer/Rollershutter only) + * *Alexa, set the `` tilt to ``.* + * *Alexa, set the `` tilt to open.* + * *Alexa, set the `` tilt to close.* + * *Alexa, set the `` tilt to up.* (Rollershutter only) + * *Alexa, set the `` tilt to down.* (Rollershutter only) + * *Alexa, set the `` tilt to stop.* (Rollershutter only) + * *Alexa, increase the `` tilt by 5 degrees.* (Number only) + * *Alexa, decrease the `` tilt by 10 percent.* (Dimmer/Rollershutter only) + * *Alexa, what's the `` tilt?* + +### Entertainment Attributes + + + + +#### `Channel` + +Items that represent a channel. It is important to note only well-known channel names can be used as these are validated against a database on the Alexa side when requested. Unfortunately, Amazon doesn't provide a list of supported channel names. + +* Supported item types: * Number * String * Supported metadata parameters: - * ``=`` - * ``=`` - * ... -* Default category: TV - -#### `InputController.input` -* Items that represent a source input (e.g. "HDMI 1", or "TUNER" on a stereo). A list of [supported input values](https://developer.amazon.com/en-US/docs/alexa/device-apis/alexa-inputcontroller.html#input-values) needs to be provided using the supportedInputs parameter. The space between the input name and number is not sent to OH (e.g. "HDMI 1" [alexa] => "HDMI1" [OH]). That space can also be omitted in the supported list as well. -* Supported item type: + * channelMappings=`` + * each mapping formatted as `=` (e.g. `channelMappings="CBS=2,NBC=4,ABC=7,PBS=13"`) + * allows channel requests by name and incrementally otherwise only channel requests by number are supported if not defined + * defaults to no mappings +* Utterance examples: + * *Alexa, change the channel to `` on the ``.* + * *Alexa, change the channel to `` on the ``.* + * *Alexa, next channel on the ``.* + * *Alexa, channel up on the ``.* + * *Alexa, channel down on the ``.* + + + + +#### `Input` + +Items that represent an input source (e.g. "HDMI 1" or "TUNER" on a stereo). + +* Supported item types: + * Number * String * Supported metadata parameters: * supportedInputs=`` - * required list of supported input values (e.g. `"HMDI1,TV,XBOX"`) -* Default category: TV + * each input formatted as `=:...` (e.g. `supportedInputs="HDMI1=Cable:Comcast,HDMI2=Kodi"`) + * requires at least two inputs to be specified + * input value used as name if not provided (e.g. `supportedInputs="HDMI1,DVD"` <=> `supportedInputs="HDMI1=HDMI1,DVD=DVD`) + * defaults to item state description options `supportedInputs="value1=label1,..."`, if defined, otherwise no supported inputs + * language=`` + * input name language support + * two-letter language code: `de`, `en`, `es`, `fr`, `hi`, `it`, `ja`, `pt` + * defaults to your server [regional settings](#regional-settings) if defined, otherwise `en` +* Utterance examples: + * *Alexa, change the input to `` on the ``.* + * *Alexa, set the `` input to ``.* + * *Alexa, what's the `` input?* + + + + + +#### `VolumeLevel` -#### `Speaker.volume` -* Items that represent a volume level, default increment may be specified in metadata parameters -* Supported item type: +Items that represent a volume level. + +* Supported item types: * Dimmer * Number * Supported metadata parameters: * increment=`` - * defaults to increment=10 (standard value provided by Alexa) if omitted. -* Default category: SPEAKER + * defaults to 10 (standard value provided by Alexa) + * stepSpeaker=`` (Number only) + * set to true for volume controlled in steps only and its state cannot be tracked by openHAB. + * defaults to false +* Utterance examples: + * *Alexa, set the volume of `` to 50.* + * *Alexa, turn the volume up on ``.* + * *Alexa, turn the volume down on `` by 20.* + * *Alexa, lower the volume on the ``.* (Step-speaker) + * *Alexa, volume up 20 on the ``.* (Step-speaker) -#### `Speaker.muted` -* Items that represent a muted state (ON muted, OFF unmuted) -* Supported item type: - * Switch -* Default category: SPEAKER + + + -#### `StepSpeaker.volume` -* Items that represent a volume controlled in steps only (e.g. +1, -1), such as a button on a remote control. This should only be used if the current volume level state cannot be tracked in openHAB otherwise just use `Speaker.volume`. Default increment may be specified in metadata parameters. -* Supported item type: - * Number -* Supported metadata parameters: - * increment=`` - * defaults to increment=10 (standard value provided by Alexa) if omitted. -* Default category: SPEAKER +#### `MuteState` -#### `StepSpeaker.muted` -* Items that represent a muted state (ON muted, OFF unmuted). This should only be used if the current muted state cannot be tracked in openHAB otherwise just use `Speaker.muted`. -* Supported item type: +Items that represent a muted state (ON muted, OFF unmuted). + +* Supported item types: * Switch -* Default category: SPEAKER +* Supported metadata parameters: + * inverted=`` + * set to true to invert state + * defaults to false + * stepSpeaker=`` + * set to true if current muted state cannot be tracked by openHAB. + * defaults to false +* Utterance examples: + * *Alexa, mute ``.* + * *Alexa, unmute ``.* -#### `PlaybackController.playback` -* Items that represent the playback controls of a AV device. (Supported commands: Play, Pause, Next, Previous, Rewind, Fast Forward) -* Supported item type: - * Player -* Default category: OTHER + + +#### `EqualizerBass` -#### `EqualizerController.bands:{bass,midrange,treble}` -* Items that represent the different equalizer bands and their ranges supported by an audio system. Use specific capability component (`bass`, `midrange` or `treble`) when configuring a band (e.g. `EqualizerController.bands:bass`). Add the band range values in the `range="-10:10"` parameter. For the reset default value, provide the setting in `default=0` parameter or it will be calculated by using midpoint range spread. Additionally, default adjust increment can be configured in `increment=2` parameter. When configuring multiple bands, make sure to synchronize the range parameter across relevant items as the same range values will be used for all bands due to Alexa restriction. However, the reset and increment default values can be different between bands. -* Supported item type: +Items that represent the bass equalizer band range supported by an audio system. + +* Supported item types: * Dimmer * Number * Supported metadata parameters: * range=`` - * defaults to `"0:100"` for Dimmer and `"-10:10"` for Number item types if omitted - * default=`` - * defaults to midpoint range spread if omitted + * range values should be synced across different bands if configured since same values used for all bands due to Alexa restriction. + * defaults to `"0:100"` for Dimmer, otherwise `"-10:10"` for Number + * defaultLevel=`` + * defaults to range midpoint * increment=`` - * defaults to increment=INCREASE/DECREASE (Dimmer) or increment=1 (Number) if omitted -* Default category: SPEAKER + * defaults to INCREASE/DECREASE for Dimmer, otherwise 1 for Number +* Utterance examples: + * *Alexa, set bass to -2 on the ``.* + * *Alexa, increase bass on the ``.* + * *Alexa, decrease bass by 3 on the ``.* + * *Alexa, reset bass on the ``.* + * *Alexa, reset equalizer on the ``.* + +#### `EqualizerMidrange` + +Items that represent the midrange equalizer band range supported by an audio system. + +Same configuration as [`EqualizerBass`](#equalizerbass). + +#### `EqualizerTreble` + +Items that represent the treble equalizer band range supported by an audio system. + +Same configuration as [`EqualizerBass`](#equalizerbass). + + -#### `EqualizerController.mode` -* Items that represent a list of equalizer modes supported by an audio system. Set supported modes using `supportedModes="MOVIE,MUSIC,TV"` parameter. The mode listed in additional properties (MOVIE, MUSIC, NIGHT, SPORT, TV) are the only ones supported by the Alexa API currently. For the mapping, default item type mapping (listed below) can be used or if necessary, add each state to the parameters similar to how it is done with other interfaces. -* Supported item type: +#### `EqualizerMode` + +Items that represent a list of equalizer modes supported by an audio system. + +* Supported item types: * Number [MOVIE=1, MUSIC=2, NIGHT=3, SPORT=4, TV=5] * String [MOVIE="movie", MUSIC="music", NIGHT="night", SPORT="sport", TV="tv"] * Supported metadata parameters: @@ -535,683 +880,1234 @@ The following are a list of supported metadata. It is important to note that not * SPORT=`` * TV=`` * supportedModes=`` - * defaults to, depending on the parameters provided, either user-based or default item type-based mapping. -* Default category: SPEAKER + * comma delimited list (e.g. `supportedModes="MOVIE,MUSIC,TV"`) + * supported modes are MOVIE, MUSIC, NIGHT, SPORT, TV + * defaults to, depending on the parameters provided, either user-based or item type-based default mappings. +* Utterance examples: + * *Alexa, set mode to movie on the ``.* -#### `ContactSensor.detectionState` -* Items that represent a contact sensor that can be used to trigger Alexa routines. (Currently not usable as proactive reporting not supported yet) -* Supported item type: - * Contact - * Switch -* Default category: CONTACT_SENSOR + + -#### `MotionSensor.detectionState` -* Items that represent a motion sensor that can be used to trigger Alexa routines. (Currently not usable as proactive reporting not supported yet) -* Supported item type: - * Contact - * Switch -* Default category: MOTION_SENSOR +#### `Playback` -#### `SecurityPanelController.armState` -* Items that represent a device that controls a security system. Set supported arm states using `supportedArmStates="DISARMED,ARMED_STAY,ARMED_AWAY"` parameter. For the mapping, default item type mapping (listed below) can be used or if necessary, add each state to the parameters similar to how it is done with other interfaces. If using a String item type, supports for pin codes (ability to have the disarm pin code verification done in openHAB) can be configured using `supportsPinCodes=true`. For system that have an exit delay, provide the delay in seconds using parameter `exitDelay=180`. If defined, the delay is provided to Alexa during arm away requests only. For the pin code, you will need to enable voice pin in the Alexa app for the relevant device. If pin codes support is set to true, disarm request will include the pin code in item command delimited by a column sign (e.g. `disarm:1234`), otherwise, the verification is done by Alexa based on the voice pin code you configured. When the pin code is attached to the item command, it is your responsibility to validate the code on the openHAB side and change the item status to UNAUTHORIZED corresponding state in order to indicate that the code is invalid. Otherwise, if no action is taken, the skill will consider the request successful. Other errors state can also be used based on the list of additional properties below. These should only be used when arm/disarm commands are received. When associated to an [item sensor](#item-sensor), the item command and state can be decoupled. Although at this time, the skill doesn't support delayed responses, so there should be no delay in updating the relevant item state. -* Supported item type: - * Number [DISARMED=0, ARMED_STAY=1, ARMED_AWAY=2, ARMED_NIGHT=3, NOT_READY=4, UNCLEARED_ALARM=5, UNCLEARED_TROUBLE=6, BYPASS_NEEDED=7] - * String [DISARMED="disarm", ARMED_STAY="stay", ARMED_AWAY="away", ARMED_NIGHT="night", AUTHORIZATION_REQUIRED="authreq", UNAUTHORIZED="unauth", NOT_READY="notrdy", UNCLEARED_ALARM="alarm", UNCLEARED_TROUBLE="trouble", BYPASS_NEEDED="bypass"] - * Switch [DISARMED="OFF", ARMED_STAY="ON"] -* Supported metadata parameters: - * DISARMED=`` - * ARMED_STAY=`` - * ARMED_AWAY=`` - * ARMED_NIGHT=`` - * AUTHORIZATION_REQUIRED=`` - * error state when in arm away mode while arm request in stay or night - * UNAUTHORIZED=`` - * error state when provided disarm pin code is incorrect (Only used with pin codes support) - * NOT_READY=`` - * error state when system not ready for arming or disarming - * UNCLEARED_ALARM=`` - * error state when system has uncleared alarm preventing arming - * UNCLEARED_TROUBLE=`` - * error state when system has uncleared trouble condition preventing arming - * BYPASS_NEEDED=`` - * error state when system has open zones preventing arming - * supportedArmStates=`` - * supported arm states should only be a list of DISARMED and ARMED_* states; do not put error states in that parameter. - * defaults to, depending on the parameters provided, either user-based or default item type-based mapping. - * supportsPinCodes=`` (optional) - * only supported with String item type - * defaults to false - * exitDelay=`` (optional) - * maximum delay Alexa restriction up to 255 seconds. - * defaults to no value -* Default category: SECURITY_PANEL - -#### `SecurityPanelController.burglaryAlarm` -* Items that represent the current state of the burglary alarm part of a security system -* Supported item type: - * Contact - * Switch -* Default category: SECURITY_PANEL +Items that represent the playback controls of a AV device. For stop command support, use [`PlaybackStop`](#playbackstop). -#### `SecurityPanelController.fireAlarm` -* Items that represent the current state of the fire alarm part of a security system -* Supported item type: - * Contact +* Supported item types: + * Player +* Supported metadata parameters: + * supportedOperations=`` + * comma delimited list (e.g. `supportedOperations="Play,Pause,Next,Previous"`) + * defaults to Play, Pause, Next, Previous, FastForward, Rewind. +* Utterance examples: + * *Alexa, play ``.* + * *Alexa, resume ``.* + * *Alexa, pause ``.* + * *Alexa, next on ``.* + * *Alexa, previous on ``.* + * *Alexa, fast forward on ``.* + * *Alexa, rewind on ``.* + +#### `PlaybackStop` + +Items that represent the playback stop command of a AV device. This needs to be paired with [`Playback`](#playback). + +* Supported item types: * Switch -* Default category: SECURITY_PANEL +* Supported metadata parameters: + * inverted=`` + * set to true to send `OFF` command instead of `ON` + * defaults to false +* Utterance examples: + * *Alexa, stop ``.* -#### `SecurityPanelController.carbonMonoxideAlarm` -* Items that represent the current state of the carbon monoxide alarm part of a security system -* Supported item type: - * Contact - * Switch -* Default category: SECURITY_PANEL +#### `Navigation` -#### `SecurityPanelController.waterAlarm` -* Items that represent the current state of the water alarm part of a security system -* Supported item type: - * Contact - * Switch -* Default category: SECURITY_PANEL +Items that represent the onscreen navigation of a AV device. -#### `ModeController.mode` -* Items that represent components of a device that have more than one setting. Multiple instances can be configured in a group endpoint. By default, to ask for a specific mode, the item label will be used as the friendly name. To configure it, use `friendlyNames` parameter and provide a comma delimited list of different labels (Keep in mind that some names are [not allowed](#friendly-names-not-allowed)). Additionally, pre-defined [asset ids](#asset-catalog) can be used to label a mode as well prefixing with an @ sign (e.g. `friendlyNames="Wash Temperature,@Setting.WaterTemperature"`). If the component isn't controllable through openHAB, set parameter `nonControllable=true`, that way only status requests will be processed. In regards to supported modes and their mappings, by default if omitted, the openHAB item state description options, if defined, are used to determine these configurations. To configure it, use `supportedModes` parameter and provide a comma delimited list of mode mappings composed of openHAB item states and the associated names/asset ids they should be called, delimited by equal and column signs (e.g. `supportedModes="0=Cold:Cool,1=Warm,2=Hot"`). For string based modes, if the mapping state value and name are the same (case sensitive), a shortened format can be used, where the name doesn't need to be added to the list by either leaving the first element empty or not providing the names at all (e.g. `supportedModes="Normal=:Cottons,Whites"` <=> `supportedModes="Normal=Normal:Cottons,Whites=Whites`). Additionally, if the mode can be adjusted incrementally (e.g. temperature control), set parameter `ordered=true`, otherwise only requests to set a specific mode will be accepted. For text-based name language support, your server [regional settings](#regional-settings) should be setup, otherwise, you can optionally set the language in parameter `language="en"`. For [semantic extensions](#semantic-extensions) support, set actions in parameter `actionMappings="Close=Down,Open=Up,Lower=Down,Raise=Up"` and states in parameter `stateMappings="Closed=Down,Open=Up"`. For actions, you can configure a set request by providing the mode or an adjust request, if `ordered=true`, by providing the delta value in parentheses. -* Supported item type: - * Number - * String +* Supported item types: + * String [UP="up", DOWN="down", LEFT="left", RIGHT="right", SELECT="select", PAGE_UP="pageup", PAGE_DOWN="pagedown", PAGE_LEFT="pageleft", PAGE_RIGHT="pageright", INFO="info", MORE="more", BACK="back"] * Supported metadata parameters: - * friendlyNames=`` - * each name formatted as `<@assetIdOrName>` - * defaults to item label name - * nonControllable=`` - * defaults to false - * supportedModes=`` - * each mode formatted as `=<@assetIdOrName1>:<@assetIdOrName2>:...` - * requires two modes to be specified at least - * defaults to item state description options `supportedModes="value1=label1,..."`, if defined, otherwise no supported modes - * ordered=`` - * defaults to false - * language=`` - * two letter language code [`de`, `en`, `es`, `fr`, `hi`, `it`, `ja`, `pt`] - * defaults to your server [regional settings](#regional-settings), if defined, otherwise `en` - * actionMappings=`` - * each mapping formatted as, based on action type: - * set => `=` - * adjust => `=()` (Supported only if `ordered=true`) - * stateMappings=`` - * each mapping formatted as `=` -* Default category: OTHER - -#### `RangeController.rangeValue` -* Items that represent components of a device that are characterized by numbers within a minimum and maximum range. Multiple instances can be configured in a group endpoint. By default, to ask for a specific range, the item label will be used as the friendly name. To configure it, use `friendlyNames` parameter and provide a comma delimited list of different labels (Keep in mind that some names are [not allowed](#friendly-names-not-allowed)). Additionally, pre-defined [asset ids](#asset-catalog) can be used to label a mode as well prefixing with an @ sign (e.g. `friendlyNames="@Setting.FanSpeed,Speed"`). If the component isn't controllable through openHAB, set parameter `nonControllable=true`, that way only status requests will be processed. To set the supported range, provide a column delimited list including minimum, maximum and precision values (e.g. `supportedRange="0:100:1"`). The latter value will be use as default increment when requesting adjusted range values. Optionally, named presets can be defined, by providing a list of comma delimited preset mappings composed of a range value and its friendly names/asset ids column delimited (e.g. fan speeds => `presets="1=@Value.Minimum:@Value.Low:Lowest,10=@Value.Maximum:@Value.High:Highest"`). Another optional settings is `unitOfMeasure` parameter which gives a unit of measure to the range values. It is determined based on: (1) [unit id](#unit-of-measurement-catalog) set in parameter `unitOfMeasure=Angle.Degrees`; (2) supported unit of item state presentation; (3) default unit of measurement for item type with dimension based on your openHAB server regional settings; (4) defaults to empty. For text-based name language support, your server [regional settings](#regional-settings) should be setup, otherwise, you can optionally set the language in parameter `language="en"`. For [semantic extensions](#semantic-extensions) support, set actions in parameter `actionMappings="Close=0,Open=100,Lower=(-10),Raise=(+10)"` and states in parameter `stateMappings="Closed=0,Open=1:100"`. For actions, you can configure a set request by providing the number value or an adjust request by providing the delta value in parentheses. For states, you can configure a specific number value or a range by providing a column delimited list including minimum and maximum values. -* Supported item type: + * UP=`` + * DOWN=`` + * LEFT=`` + * RIGHT=`` + * SELECT=`` + * PAGE_UP=`` + * PAGE_DOWN=`` + * PAGE_LEFT=`` + * PAGE_RIGHT=`` + * INFO=`` + * MORE=`` + * BACK=`` + * supportedKeys=`` + * comma delimited list (e.g. `supportedKeys="UP,DOWN,LEFT,RIGHT,SELECT"`) + * supported keys are UP, DOWN, LEFT, RIGHT, SELECT, PAGE_UP, PAGE_DOWN, PAGE_LEFT, PAGE_RIGHT, INFO, MORE, BACK + * defaults to, depending on the parameters provided, either user-based or item type-based default mappings. +* Utterance examples: + * *Alexa, go left on ``.* + * *Alexa, move down on ``.* + * *Alexa, scroll right on ``.* + * *Alexa, page up on ``.* + * *Alexa, select this on ``.* + * *Alexa, navigate back on ``.* + * *Alexa, show details on ``.* + * *Alexa, show info on ``.* + +### Fan Attributes + +#### `FanSpeed` + +Items that represent the speed of a fan. + +* Supported item types: * Dimmer * Number - * Number:Angle - * Number:Dimensionless - * Number:Length - * Number:Mass - * Number:Temperature - * Number:Volume - * Rollershutter + * String [OFF="OFF", LOW="LOW", MEDIUM="MEDIUM", HIGH="HIGH"] * Supported metadata parameters: - * friendlyNames=`` - * each name formatted as `<@assetIdOrName>` - * defaults to item label name - * nonControllable=`` + * OFF=`` (String only) + * LOW=`` (String only) + * MEDIUM=`` (String only) + * HIGH=`` (String only) + * inverted=`` (Dimmer only) + * set to true to invert item state * defaults to false - * supportedRange=`` - * defaults to `"0:100:1"` for Dimmer/Rollershutter, `"0:10:1"` for Number* item types - * presets=`` (optional) - * each preset formatted as `=<@assetIdOrName1>:<@assetIdOrName2>:...` - * unitOfMeasure=`` (optional) - * defaults to unit of item state presentation or default unit of measurement for the Number:* item types listed below: - * Number:Angle [`Angle.Degrees`] - * Number:Length [`Distance.Meters` (SI); `Distance.Inches` (US)] - * Number:Temperature [`Temperature.Celsius` (SI); `Temperature.Fahrenheit` (US)] - * language=`` - * two letter language code [`de`, `en`, `es`, `fr`, `hi`, `it`, `ja`, `pt`] - * defaults to your server [regional settings](#regional-settings), if defined, otherwise `en` - * actionMappings=`` - * each mapping formatted as, based on action type: - * set => `=` - * adjust => `=()` - * stateMappings=`` - * each mapping formatted as, based on state type: - * range => `=:` - * value => `=` -* Default category: OTHER + * speedLevels=`` (Number only) + * requires at least 2-speed + * defaults to 3 +* Utterance examples: + * *Alexa, set the `` speed to off.* + * *Alexa, set the `` speed to low.* + * *Alexa, set the `` speed to medium.* + * *Alexa, set the `` speed to high.* + * *Alexa, set the `` speed to minimum.* + * *Alexa, set the `` speed to maximum.* + * *Alexa, set the `` speed to 30 percent.* (Dimmer only) + * *Alexa, set the `` speed to 2.* (Number only) + * *Alexa, increase the `` speed.* + * *Alexa, decrease the `` speed.* + * *Alexa, increase the `` speed by 10 percent.* (Dimmer only) + * *Alexa, decrease the `` speed by 2.* (Number only) + * *Alexa, what's the speed of ``?* + +#### `FanDirection` + +Items that represent a direction setting of a fan. + +* Supported item types: + * String [FORWARD="FORWARD", REVERSE="REVERSE"] + * Switch [FORWARD="ON", REVERSE="OFF"] +* Supported metadata parameters: + * FORWARD=`` (String only) + * REVERSE=`` (String only) + * inverted=`` (Switch only) + * set to true to invert item state + * defaults to false +* Utterance examples: + * *Alexa, set the `` direction to forward.* + * *Alexa, set the `` direction to reverse.* + * *Alexa, what's the direction of ``?* -#### `ToggleController.toggleState` -* Items that represent components of a device that can be turned on or off. Multiple instances can be configured in a group endpoint. By default, to ask for a specific range, the item label will be used as the friendly name. To configure it, use `friendlyNames` parameter and provide a comma delimited list of different labels (Keep in mind that some names are [not allowed](#friendly-names-not-allowed)). Additionally, pre-defined [asset ids](#asset-catalog) can be used to label a mode as well with an @ sign prefix (e.g. `friendlyNames="@Setting.Oscillate,Rotate"`). If the component isn't controllable through openHAB, set parameter `nonControllable=true`, that way only status requests will be processed. For text-based name language support, your server [regional settings](#regional-settings) should be setup, otherwise, you can optionally set the language in parameter `language="en"`. For [semantic extensions](#semantic-extensions) support, set actions in parameter `actionMappings="Close=OFF,Open=ON"` and states in parameter `stateMappings="Closed=OFF,Open=ON"`. Actions and states values must be set to either `ON` or `OFF`. -* Supported item type: - * Color - * Dimmer +#### `FanOscillate` + +Items that represent an oscillate setting of a fan. + +* Supported item types: * Switch * Supported metadata parameters: - * friendlyNames=`` - * each name formatted as `<@assetIdOrName>` - * defaults to item label name - * nonControllable=`` + * inverted=`` + * set to true to invert item state * defaults to false - * language=`` - * two letter language code [`de`, `en`, `es`, `fr`, `hi`, `it`, `ja`, `pt`] - * defaults to your server [regional settings](#regional-settings), if defined, otherwise `en` - * actionMappings=`` - * each mapping formatted as `=ON` or `=OFF` - * stateMappings=`` - * each mapping formatted as `=ON` or `=OFF` -* Default category: OTHER +* Utterance examples: + * *Alexa, turn on the `` oscillation.* + * *Alexa, turn off the `` oscillation.* + * *Alexa, is the `` oscillation on?* -### Supported Group Metadata -* Functional groups (no group type) can be labelled with one of Alexa [display categories](#display-categories). It can be set using one of the two formats: `Endpoint.` or `` (e.g `{alexa="Endpoint.Thermostat"}` or `{alexa="Thermostat"}`). -* Display categories with underscores can be defined in camel cased format (e.g. `{alexa="Endpoint.SecurityPanel"}` => `SECURITY_PANEL`). -* Child item categories are ignored and only the group category is used to represent the endpoint. -* Case is ignored on the category part of the metadata and any value will be made all uppercase before its passed to the Alexa API. +### Lighting Attributes -### Supported Metadata Labels -Item metadata labels translate to a set of capabilities and can be used as a convenience to using the longer meta data format configuration. These add additional functions and provide the ability to add customization through additional parameters which take precedence over the default ones. Here are some examples: -``` -Switch TelevisionPower "Television Power" {alexa="Switchable" [category="TV"]} + -Color LightColor "Light Color" {alexa="Lighting"} -``` +#### `Brightness` -Here are the labels currently supported and what they translate to. Each example shows using the meta data label and the full translated metadata. +Items that represent a lighting device responding to brightness commands. -#### Switchable -_(capabilities depending on item type)_ -``` -Switch DeviceSwitch "Device Switch" {alexa="Switchable"} -Rollershutter ShutterSwitch "Shutter Switch" {alexa="Switchable"} +* Supported item types: + * Color + * Dimmer +* Utterance examples: + * *Alexa, set the `` to 50 percent.* + * *Alexa, brighten the `` by 25 percent.* + * *Alexa, dim the ``.* -Switch DeviceSwitch "Device Switch" {alexa="PowerController.powerState" [category="SWITCH"]} -Rollershutter ShutterSwitch "Shutter Switch" {alexa="PercentageController.percentage" [category="SWITCH"]} -``` -#### Lighting -_(capabilities depending on item type)_ -``` -Dimmer LightDimmer "Light Dimmer" {alexa="Lighting"} -Color LightColor "Light Color" {alexa="Lighting"} + -Dimmer LightDimmer "Light Dimmer" {alexa="PowerController.powerState,BrightnessController.brightness" [category="LIGHT"]} -Color LightColor "Light Color" {alexa="PowerController.powerState,BrightnessController.brightness,ColorController.color" [category="LIGHT"]} -``` -#### Blind -``` -Rollershutter Blind "Blind" {alexa="Blind"} +#### `Color` -Rollershutter Blind "Blind" {alexa="RangeController.rangeValue" [category="INTERIOR_BLIND", friendlyNames="@Setting.Opening", supportedRange="0:100:10", unitOfMeasure="Percent", actionMappings="Close=0,Open=100,Lower=(-10),Raise=(+10)", stateMappings="Closed=0,Open=1:100"]} -``` -#### Door -``` -Switch Door "Door" {alexa="Door"} +Items that represent a lighting device responding to color commands. -Switch Door "Door" {alexa="ToggleController.toggleState" [category="DOOR", friendlyNames="@Setting.Opening", actionMappings="Close=OFF,Open=ON", stateMappings="Closed=OFF,Open=ON"]} -``` -#### Lock -``` -Switch DoorLock "Door Lock" {alexa="Lock"} +* Supported item types: + * Color +* Utterance examples: + * *Alexa, set the `` to red.* -Switch DoorLock "Door Lock" {alexa="LockController.lockState"} -``` -#### Outlet -``` -Switch OutletPlug "Outlet Plug" {alexa="Outlet"} + -Switch OutletPlug "Outlet Plug" {alexa="PowerController.powerState" [category="SMARTPLUG"]} -``` -#### CurrentHumidity -``` -Number CurrentHumidity "Current Humidity" {alexa="CurrentHumidity"} +#### `ColorTemperature` -Number CurrentHumidity "Current Humidity" {alexa="RangeController.rangeValue" [friendlyNames="@Setting.Humidity", nonControllable=true, supportedRange="0:100:1", unitOfMeasure="Percent"]} -``` -#### CurrentTemperature -``` -Number CurrentTemperature "Current Temperature" {alexa="CurrentTemperature"} +Items that represents a color temperature. It is important to note that temperature adjustment requests for endpoints including a color item, will be rejected if the endpoint is in color mode (Dimmer => _undefined_ temperature or color saturation > 0; Number => _undefined_ temperature or temperature = 0). In that event, set the initial white level before requesting subsequent adjustments. -Number CurrentTemperature "Current Temperature" {alexa="TemperatureSensor.temperature" [scale="Celsius"]} -``` -#### TargetTemperature -``` -Number TargetTemperature "Target Temperature" {alexa="TargetTemperature"} +* Supported item types: + * Dimmer (Colder `0%` to warmer `100%` based on defined temperature range for bindings integration) + * Number (Color temperature value in Kelvin for custom integration) +* Supported binding presets: + * [hue](https://www.openhab.org/addons/bindings/hue/) [color=`2000:6500`, white=`2200:6500`] + * [lifx](https://www.openhab.org/addons/bindings/lifx/) [color=`2500:9000`, white=`2700:6500`] + * [milight](https://www.openhab.org/addons/bindings/milight/) [color=`2700:6500`, white=`2700:6500`] + * [tradfri](https://www.openhab.org/addons/bindings/tradfri/) [color=`1780:6000`, white=`2200:4000`] + * [tplinksmarthome](https://www.openhab.org/addons/bindings/tplinksmarthome/) [color=`2500:9000`, white=`2700:6500`] + * [yeelight](https://www.openhab.org/addons/bindings/yeelight/) [color=`1700:6500`, white=`2700:6500`] +* Supported metadata parameters: + * binding=`` + * id formatted as: + * color type => `(:color)` (e.g. `binding="hue"` or `binding="hue:color"`) + * white type => `:white` (e.g. `binding="hue:white"`) + * only for [GUI-based configuration](https://www.openhab.org/docs/configuration/) + * defaults to channel metadata value for items configured via text files + * range=`` + * range formatted as `:` in Kelvin (e.g. `range="2700:6500"`) + * defaults to, depending on the parameters provided in order of precedence: + * preset-based using the binding linked name and thing type to differentiate color/white ranges, defaulting to color range + * defaults to `1000:10000` + * increment=`` + * expressed in % (Dimmer); in Kelvin (Number) + * defaults to INCREASE/DECREASE for Dimmer, otherwise 500 for Number +* Utterance examples: + * *Alexa, make the `` warm white.* + * *Alexa, set the `` to daylight.* + * *Alexa, make the `` warmer.* + * *Alexa, set the `` softer.* + * *Alexa, make the `` whiter.* + * *Alexa, set the `` cooler.* -Number TargetTemperature "Target Temperature" {alexa="ThermostatController.targetSetpoint" [scale="Celsius"]} -``` -#### LowerTemperature -``` -Number LowerTemperature "Lower Temperature" {alexa="LowerTemperature"} +### Networking Attributes -Number LowerTemperature "Lower Temperature" {alexa="ThermostatController.lowerSetpoint" [scale="Celsius"]} -``` -#### UpperTemperature -``` -Number UpperTemperature "Upper Temperature" {alexa="UpperTemperature"} +#### `HomeNetwork` -Number UpperTemperature "Upper Temperature" {alexa="ThermostatController.upperSetpoint" [scale="Celsius"]} -``` -#### HeatingCoolingMode -``` -String HeatingCoolingMode "Thermostat Mode" {alexa="HeatingCoolingMode"} +Items that represent a network router. This attribute cannot be specified by name. It is automatically added when configuring a [group endpoint](#group-endpoint) as one of the supported [device types](#device-types). -String HeatingCoolingMode "Thermostat Mode" {alexa="ThermostatController.thermostatMode"} -``` -#### ColorTemperature -``` -Dimmer ColorTemperature "Color Temperature" {alexa="ColorTemperature"} +* Supported device types: + * `NetworkHardware` + * `Router` -Dimmer ColorTemperature "Color Temperature" {alexa="ColorTemperatureController.colorTemperatureInKelvin"} -``` -#### Activity -``` -Switch Activity "Activity" {alexa="Activity"} +#### `ConnectedDevice` -Switch Activity "Activity" {alexa="SceneController.scene" [category="ACTIVITY_TRIGGER"]} -``` -#### Scene -``` -Switch Scene "Scene" {alexa="Scene"} +Items that represent a network device, such as a computer or mobile phone, connected to a router. This attribute cannot be specified by name. It is automatically added when configuring a [group endpoint](#group-endpoint) as one of the supported [device types](#device-types), that is a member of the group representing the router, as [`HomeNetwork`](#homenetwork), where the device is connected to, and having at least the metadata parameter `macAddress` defined. -Switch Scene "Scene" {alexa="SceneController.scene" [category="SCENE_TRIGGER"]} -``` -#### EntertainmentChannel -``` -String EntertainmentChannel "Entertainment Channel" {alexa="EntertainmentChannel"} +* Supported device types: + * `Computer` + * `GameConsole` + * `Laptop` + * `MobilePhone` + * `Tablet` + * `Wearable` +* Supported metadata parameters: + * hostname=`` + * defaults to `N/A` + * macAddress=`
` + * formatted as EUI-48 or EUI-64 address with colon or dash separators (e.g. `macAddress="00:21:86:B5:6E:10"`) -String EntertainmentChannel "Entertainment Channel" {alexa="ChannelController.channel"} -``` -#### EntertainmentInput -``` -String EntertainmentInput "Entertainment Input" {alexa="EntertainmentInput"} +#### `NetworkAccess` -String EntertainmentInput "Entertainment Input" {alexa="InputController.input"} -``` -#### EqualizerBass -``` -Number EqualizerBass "Equalizer Bass" {alexa="EqualizerBass"} +Items that represent the internet/network access control of a Wi-Fi/Ethernet connection to a router. This needs to be paired with [`ConnectedDevice`](#connecteddevice). To enable the access control by voice, you will need to select the configured device in your Alexa app, by going to Devices > Wi-Fi Access > Add a device. To limit the control based on voice profiles, turn on the option in the Wi-Fi Access settings. -Number EqualizerBass "Equalizer Bass" {alexa="EqualizerController.bands:bass} -``` -#### EqualizerMidrange -``` -Number EqualizerMidrange "Equalizer Midrange" {alexa="EqualizerMidrange"} +* Supported item types: + * Switch [ALLOWED="ON", BLOCKED="OFF"] +* Supported metadata parameters: + * inverted=`` + * set to true to invert item state + * defaults to false +* Utterance examples: + * *Alexa, pause the Internet for ``.* + * *Alexa, resume the Wi-Fi for ``.* + * *Alexa, enable the Internet for ``.* + * *Alexa, disable the Wi-Fi for ``.* + * *Alexa, turn on the Internet for ``.* + * *Alexa, turn off the Wi-Fi for ``.* -Number EqualizerMidrange "Equalizer Midrange" {alexa="EqualizerController.bands:midrange"} -``` -#### EqualizerTreble -``` -Number EqualizerTreble "Equalizer Treble" {alexa="EqualizerTreble"} +### Scene Attributes -Number EqualizerTreble "Equalizer Treble" {alexa="EqualizerController.bands:treble"} -``` -#### EqualizerMode -``` -String EqualizerMode "Equalizer Mode" {alexa="EqualizerMode"} + -String EqualizerMode "Equalizer Mode" {alexa="EqualizerController.mode"} -``` -#### MediaPlayer -``` -Player MediaPlayer "Media Player" {alexa="MediaPlayer"} +#### `Scene` -Player MediaPlayer "Media Player" {alexa="PlaybackController.playback"} -``` -#### SpeakerMute -``` -Switch SpeakerMute "Speaker Mute" {alexa="SpeakerMute"} +Items that represent a combination of devices set to a specific state. Use scene triggers for scenes when the order of the state change is not important. For example, for a scene named "bedtime" you might turn off the lights and lower the thermostat, in any order. -Switch SpeakerMute "Speaker Mute" {alexa="Speaker.muted"} -``` -#### SpeakerVolume -``` -Number SpeakerVolume "Speaker Volume" {alexa="SpeakerVolume"} +* Supported item types: + * Switch +* Supported metadata parameters: + * supportsDeactivation=`` + * defaults to true +* Utterance examples: + * *Alexa, turn on ``.* + * *Alexa, turn off ``.* -Number SpeakerVolume "Speaker Volume" {alexa="Speaker.volume"} -``` -#### ContactSensor -``` -Contact ContactSensor "Contact Sensor" {alexa="ContactSensor"} +#### `Activity` -Contact ContactSensor "Contact Sensor" {alexa="ContactSensor.detectionState"} -``` -#### MotionSensor -``` -Contact MotionSensor "Motion Sensor" {alexa="MotionSensor"} +Items that represent a combination of devices set to a specific state. Use activity triggers for scenes when the state changes must occur in a specific order. For example, for a scene named "watch Netflix" you might power on the TV first, and then set the input to HDMI1. -Contact MotionSensor "Motion Sensor" {alexa="MotionSensor.detectionState"} -``` -#### SecurityAlarmMode -``` -String SecurityAlarmMode "Security Alarm Mode" {alexa="SecurityAlarmMode"} +* Supported item types: + * Switch +* Supported metadata parameters: + * supportsDeactivation=`` + * defaults to true +* Utterance examples: + * *Alexa, turn on ``.* + * *Alexa, turn off ``.* -String SecurityAlarmMode "Security Alarm Mode" {alexa="SecurityPanelController.armState"} -``` -#### BurglaryAlarm -``` -Contact BurglaryAlarm "Burglary Alarm" {alexa="BurglaryAlarm"} +### Security Attributes -Contact BurglaryAlarm "Burglary Alarm" {alexa="SecurityPanelController.burglaryAlarm"} -``` -#### FireAlarm -``` -Contact FireAlarm "Fire Alarm" {alexa="FireAlarm"} + -Contact FireAlarm "Fire Alarm" {alexa="SecurityPanelController.fireAlarm"} -``` -#### CarbonMonoxideAlarm -``` -Contact CarbonMonoxideAlarm "Carbon Monoxide Alarm" {alexa="CarbonMonoxideAlarm"} +#### `LockState` -Contact CarbonMonoxideAlarm "Carbon Monoxide Alarm" {alexa="SecurityPanelController.carbonMonoxideAlarm"} -``` -#### WaterAlarm -``` -Contact WaterAlarm "Water Alarm" {alexa="WaterAlarm"} +Items that represent the state of a lock (ON lock, OFF unlock). For decouple state support, use [`TargetLockState`](#targetlockstate) and [`CurrentLockState`](#currentlockstate) instead. -Contact WaterAlarm "Water Alarm" {alexa="SecurityPanelController.waterAlarm"} -``` -#### ModeComponent -``` -String ModeComponent "Mode Component" {alexa="ModeComponent"} +* Supported item types: + * Switch +* Supported metadata parameters: + * inverted=`` + * set to true to invert item state + * defaults to false +* Utterance examples: + * *Alexa, lock the ``.* + * *Alexa, unlock the ``.* (Requires the unlock feature to be enabled in the Alexa app) + * *Alexa, is the `` locked?* -String ModeComponent "Mode Component" {alexa="ModeController.mode"} -``` -#### RangeComponent -``` -Number RangeComponent "Range Component" {alexa="RangeComponent"} +#### `TargetLockState` -Number RangeComponent "Range Component" {alexa="RangeController.rangeValue"} -``` -#### ToggleComponent -``` -Switch ToggleComponent "Toggle Component" {alexa="ToggleComponent"} +Items that represent the target state of a lock with decouple state. This should be paired with [`CurrentLockState`](#currentlockstate). -Switch ToggleComponent "Toggle Component" {alexa="ToggleController.toggleState"} -``` +Same configuration as [`LockState`](#lockstate). -### Regional Availability - * The availability of a given capability depends on the location setting of your Amazon account under which your echo devices are registered to. Here is the latest list of interface capabilities and their supported locales from [Alexa Skill API](https://developer.amazon.com/docs/device-apis/list-of-interfaces.html): - -| Interfaces | AUS | CAN | DEU | ESP | FRA | GBR | IND | ITA | JPN | USA | -| ---------- | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | -| BrightnessController | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| ChannelController | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | -| ColorController | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| ColorTemperatureController | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| ContactSensor | :x: | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :heavy_check_mark: | -| EqualizerController | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :heavy_check_mark: | -| InputController | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | -| LockController (lock) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| LockController (unlock) | :x: | :x: | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | -| ModeController | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| MotionSensor | :x: | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :heavy_check_mark: | -| PercentageController | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| PlaybackController | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | -| PowerController | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| PowerLevelController | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| RangeController | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| SceneController | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | -| SecurityPanelController | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :x: | :x: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | -| Speaker | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | -| StepSpeaker | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | -| TemperatureSensor | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| ThermostatController | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| ToggleController | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | - -### Display Categories - * Alexa has certain categories that effect how voice control and their mobile/web UI's display or control endpoints. An example of this is when you create "Smart Device Groups" in the Alex app and associate a specific Echo or Dot to that Group (typically a room). When a user asks to turn the lights ON, Alexa looks for devices in that group that have the category "LIGHT" to send the command to. - * You can override this default value on items by adding it as a parameter to the metadata (e.g. `Switch LightSwitch "Light Switch" {alexa="PowerController.powerState" [category="OTHER"]}`). - * List of Alexa categories currently supported from [Alexa Skill API](https://developer.amazon.com/docs/device-apis/alexa-discovery.html#display-categories) docs: - -Category | Description ----------|------------ -ACTIVITY_TRIGGER | A combination of devices set to a specific state. Use activity triggers for scenes when the state changes must occur in a specific order. For example, for a scene named "watch Netflix" you might power on the TV first, and then set the input to HDMI1. -CAMERA | A media device with video or photo functionality. -COMPUTER | A non-mobile computer, such as a desktop computer. -CONTACT_SENSOR | An endpoint that detects and reports changes in contact between two surfaces. -DOOR | A door. -DOORBELL | A doorbell. -EXTERIOR_BLIND | A window covering on the outside of a structure. -FAN | A fan. -GAME_CONSOLE | A game console, such as Microsoft Xbox or Nintendo Switch -GARAGE_DOOR | A garage door. Garage doors must implement the [ModeController](#modecontroller-mode) interface to open and close the door. -INTERIOR_BLIND | A window covering on the inside of a structure. -LAPTOP | A laptop or other mobile computer. -LIGHT | A light source or fixture. -MICROWAVE | A microwave oven. -MOBILE_PHONE | A mobile phone. -MOTION_SENSOR | An endpoint that detects and reports movement in an area. -MUSIC_SYSTEM | A network-connected music system. -NETWORK_HARDWARE | A network router. -OTHER | An endpoint that doesn't belong to one of the other categories. -OVEN | An oven cooking appliance. -PHONE | A non-mobile phone, such as landline or an IP phone. -SCENE_TRIGGER | A combination of devices set to a specific state. Use scene triggers for scenes when the order of the state change is not important. For example, for a scene named "bedtime" you might turn off the lights and lower the thermostat, in any order. -SCREEN | A projector screen. -SECURITY_PANEL | A security panel. -SMARTLOCK | An endpoint that locks. -SMARTPLUG | A module that is plugged into an existing electrical outlet, and then has a device plugged into it. For example, a user can plug a smart plug into an outlet, and then plug a lamp into the smart plug. A smart plug can control a variety of devices. -SPEAKER | A speaker or speaker system. -STREAMING_DEVICE | A streaming device such as Apple TV, Chromecast, or Roku. -SWITCH | A switch wired directly to the electrical system. A switch can control a variety of devices. -TABLET | A tablet computer. -TEMPERATURE_SENSOR | An endpoint that reports temperature, but does not control it. The temperature data of the endpoint is not shown in the Alexa app. -THERMOSTAT | An endpoint that controls temperature, stand-alone air conditioners, or heaters with direct temperature control. -TV | A television. -WEARABLE | A network-connected wearable device, such as an Apple Watch, Fitbit, or Samsung Gear. - -### Asset Catalog - * List of Alexa asset catalog from [Alexa Skill API](https://developer.amazon.com/docs/device-apis/resources-and-assets.html#global-alexa-catalog) docs: +#### `CurrentLockState` -Asset Identifier | Supported Friendly Names ------------------|------------------------- -DeviceName.AirPurifier | Air Purifier
Air Cleaner
Clean Air Machine -DeviceName.Fan | Fan
Blower -DeviceName.Router | Router
Internet Router
Network Router
Wifi Router
Net Router -DeviceName.Shade | Shade
Blind
Curtain
Roller
Shutter
Drape
Awning
Window shade
Interior blind -DeviceName.Shower | Shower -DeviceName.SpaceHeater | Space Heater
Portable Heater -DeviceName.Washer | Washer
Washing Machine -Setting.2GGuestWiFi | 2.4G Guest Wi-Fi
2.4G Guest Network
Guest Network 2.4G
2G Guest Wifi -Setting.5GGuestWiFi | 5G Guest Wi-Fi
5G Guest Network
Guest Network 5G
5G Guest Wifi -Setting.Auto | Auto
Automatic
Automatic Mode
Auto Mode -Setting.Direction | Direction -Setting.DryCycle | Dry Cycle
Dry Preset
Dry Setting
Dryer Cycle
Dryer Preset
Dryer Setting -Setting.FanSpeed | Fan Speed
Airflow speed
Wind Speed
Air speed
Air velocity -Setting.GuestWiFi | Guest Wi-fi
Guest Network
Guest Net -Setting.Heat | Heat -Setting.Mode | Mode -Setting.Night | Night
Night Mode -Setting.Opening | Opening
Height
Lift
Width -Setting.Oscillate | Oscillate
Swivel
Oscillation
Spin
Back and forth -Setting.Preset | Preset
Setting -Setting.Quiet | Quiet
Quiet Mode
Noiseless
Silent -Setting.Temperature | Temperature
Temp -Setting.WashCycle | Wash Cycle
Wash Preset
Wash setting -Setting.WaterTemperature | Water Temperature
Water Temp
Water Heat -Shower.HandHeld | Handheld Shower
Shower Wand
Hand Shower -Shower.RainHead | Rain Head
Overhead shower
Rain Shower
Rain Spout
Rain Faucet -Value.Close | Close -Value.Delicate | Delicates
Delicate -Value.High | High -Value.Low | Low -Value.Maximum | Maximum
Max -Value.Medium | Medium
Mid -Value.Minimum | Minimum
Min -Value.Open | Open -Value.QuickWash | Quick Wash
Fast Wash
Wash Quickly
Speed Wash - - * List of custom asset catalog defined by skill: +Items that represent the current state of a lock with decouple state. This needs to be paired with [`TargetLockState`](#targetlockstate). The state of this item will be returned instead of the original actionable item. For Number and String, the state mappings can be provided in the metadata parameters and, if necessary, multiple properties to one state can be mapped with column delimiter (e.g. for a Z-Wave lock: `LOCKED="1:3",UNLOCKED="2:4",JAMMED="11"`). -Asset Identifier | Supported Friendly Names ------------------|------------------------- -Setting.Humidity | Humidity +* Supported item types: + * Contact [LOCKED="CLOSED", UNLOCKED="OPEN"] + * Number [LOCKED=1, UNLOCKED=2, JAMMED=3] + * String [LOCKED="locked", "UNLOCKED"="unlocked", JAMMED="jammed"] + * Switch [LOCKED="ON", UNLOCKED="OFF"] +* Supported metadata parameters: + * LOCKED=`` (Number/String only) + * UNLOCKED=`` (Number/String only) + * JAMMED=`` (Number/String only) + * inverted=`` (Contact/Switch only) + * set to true to invert item state + * defaults to false -### Semantic Catalog - * List of Alexa semantic catalog from [Alexa Skill API](https://developer.amazon.com/docs/device-apis/alexa-discovery.html#semantics-object) docs: + + -Semantic Type | Identifiers ---------------|------------ -Actions | Close
Open
Lower
Raise -States | Closed
Open +#### `ArmState` -### Unit of Measurement Catalog - * List of Alexa unit of measurement catalog from [Alexa Skill API](https://developer.amazon.com/docs/device-apis/alexa-property-schemas.html#units-of-measure) docs: +Items that represent the arm state of a security panel. Multiple properties to one state can be mapped with column delimiter (e.g. for DSC alarm system, combining standard mode with no delay equivalent: `DISARMED="0",ARMED_AWAY="1:3",ARMED_STAY="2:4"`). To disarm by voice, you will need to set up a voice code in your Alexa app for that device. For security panel errors handling, add [`AlarmAlert`](#alarmalert), [`ReadyAlert`](#readyalert), [`TroubleAlert`](#troublealert) and [`ZonesAlert`](#zonealert) attributes to your security panel group endpoint. -Unit Identifier | -----------------| -Angle.Degrees | -Angle.Radians | -Distance.Yards | -Distance.Inches | -Distance.Meters | -Distance.Feet | -Distance.Miles | -Distance.Kilometers | -Mass.Kilograms | -Mass.Grams | -Percent | -Temperature.Degrees | -Temperature.Celsius | -Temperature.Fahrenheit | -Temperature.Kelvin | -Volume.Gallons | -Volume.Pints | -Volume.Quarts | -Volume.Liters | -Volume.CubicMeters | -Volume.CubicFeet | -Weight.Pounds | -Weight.Ounces | - -### Friendly Names Not Allowed - * List of Alexa friendly names that cannot be used from [Alexa Skill API](https://developer.amazon.com/docs/device-apis/resources-and-assets.html#names-you-cannot-use) docs: +* Supported item types: + * Number [DISARMED=0, ARMED_STAY=1, ARMED_AWAY=2, ARMED_NIGHT=3] + * String [DISARMED="disarmed", ARMED_STAY="stay", ARMED_AWAY="away", ARMED_NIGHT="night"] + * Switch [DISARMED="OFF", ARMED_STAY="ON"] +* Supported metadata parameters: + * DISARMED=`` + * ARMED_STAY=`` + * ARMED_AWAY=`` + * ARMED_NIGHT=`` + * supportedArmStates=`` + * comma delimited list (e.g. `supportedArmStates="DISARMED,ARMED_STAY,ARMED_AWAY"`) + * requires DISARMED and at least one ARMED state to be specified + * defaults to, depending on the parameters provided, either user-based or item type-based default mappings. + * pinCodes=`` + * each code formatted as 4-digit pin (e.g. `pinCodes="1234,9876"`) + * pin codes if configured, are validated by the skill on disarm requests + * defaults to only using the Alexa voice code for disarming verification + * exitDelay=`` + * maximum delay restricted to 255 seconds + * defaults to no delay +* Utterance examples: + * *Alexa, arm my home in away mode.* + * *Alexa, arm my home.* + * *Alexa, disarm my home.* + * *Alexa, is my home armed?* + + + +#### `BurglaryAlarm` + +Items that represent the burglary alarm state of a security panel. + +* Supported item types: + * Contact [OK="CLOSED", ALARM="OPEN"] + * Switch [OK="OFF", ALARM="ON"] +* Supported metadata parameters: + * inverted=`` + * set to true to invert item state + * defaults to false -Friendly Names | ----------------| -alarm | -alarms | -all alarms | -away mode | -bass | -camera | -date | -date today | -day | -do not disturb | -drop in | -music | -night light | -notification | -playing | -sleep sounds | -time | -timer | -today in music | -treble | -volume | -way f. m. | + -## Item Tag v2 Support - -Version 2 (v2) of the Alexa skill used openHAB [HomeKit](https://www.openhab.org/addons/integrations/homekit/#item-configuration) style tags to expose items to Alexa. -Version 3 (v3) of the skill supports this by translating v2 style tags to v3 [metadata labels](#supported-metadata-labels) internally. These tags are still required if the items are being exposed to the [HomeKit](https://www.openhab.org/addons/integrations/homekit/#item-configuration) or [Google Assistant](https://www.openhab.org/docs/ecosystem/google-assistant/#item-configuration) integrations. Below is the translation of v2 tags to v3 labels. - -### Supported v2 Item Tags - -| v2 Item Tag | v3 Metadata Label | -|-------------|-------------------| -| Lighting | Lighting | -| Switchable | Switchable | -| ContactSensor | ContactSensor | -| CurrentTemperature | CurrentTemperature | -| CurrentHumidity | CurrentHumidity | -| Thermostat | Thermostat | -| └ CurrentTemperature | CurrentTemperature | -| └ homekit:HeatingCoolingMode | HeatingCoolingMode | -| └ homekit:TargetHeatingCoolingMode | HeatingCoolingMode | -| └ homekit:TargetTemperature | TargetTemperature | -| └ TargetTemperature | TargetTemperature | -| WindowCovering | Blind | - -### Example v2 Items -``` -Switch KitchenLights "Kitchen Lights" (gKitchen) [ "Lighting" ] -Dimmer BedroomLights "Bedroom Lights" (gBedroom) [ "Lighting" ] -Number BedroomTemperature "Bedroom Temperature" (gBedroom) [ "CurrentTemperature" ] -Group gDownstairsThermostat "Downstairs Thermostat" (gFF) [ "Thermostat" ] -Number DownstairsThermostatCurrentTemp "Downstairs Thermostat Current Temperature" (gDownstairsThermostat) [ "CurrentTemperature" ] -Number DownstairsThermostatTargetTemperature "Downstairs Thermostat Target Temperature" (gDownstairsThermostat) [ "TargetTemperature" ] -String DownstairsThermostatHeatingCoolingMode "Downstairs Thermostat Heating/Cooling Mode" (gDownstairsThermostat) [ "homekit:HeatingCoolingMode" ] -``` +#### `CarbonMonoxideAlarm` + +Items that represent the carbon monoxide alarm state of a security panel. + +* Supported item types: + * Contact [OK="CLOSED", ALARM="OPEN"] + * Switch [OK="OFF", ALARM="ON"] +* Supported metadata parameters: + * inverted=`` + * set to true to invert item state + * defaults to false + + + +#### `FireAlarm` + +Items that represent the fire alarm state of a security panel. + +* Supported item types: + * Contact [OK="CLOSED", ALARM="OPEN"] + * Switch [OK="OFF", ALARM="ON"] +* Supported metadata parameters: + * inverted=`` + * set to true to invert item state + * defaults to false + + + +#### `WaterAlarm` + +Items that represent the water alarm state of a security panel. + +* Supported item types: + * Contact [OK="CLOSED", ALARM="OPEN"] + * Switch [OK="OFF", ALARM="ON"] +* Supported metadata parameters: + * inverted=`` + * set to true to invert item state + * defaults to false + +#### `AlarmAlert` + +Items that represent the alert state of a security panel when it has uncleared alarm preventing arming. This needs to be paired with [`ArmState`](#armstate). + +* Supported item types: + * Contact [OK="CLOSED", ALERT="OPEN"] + * Switch [OK="OFF", ALERT="ON"] +* Supported metadata parameters: + * inverted=`` + * set to true to invert item state + * defaults to false + +#### `ReadyAlert` + +Items that represent the alert state of a security panel when it is not ready for arming or disarming. This needs to be paired with [`ArmState`](#armstate). + +* Supported item types: + * Contact [OK="CLOSED", ALERT="OPEN"] + * Switch [OK="OFF", ALERT="ON"] +* Supported metadata parameters: + * inverted=`` + * set to true to invert item state + * defaults to false + +#### `TroubleAlert` + +Items that represent the alert state of a security panel when it has uncleared trouble condition preventing arming. This needs to be paired with [`ArmState`](#armstate). + +* Supported item types: + * Contact [OK="CLOSED", ALERT="OPEN"] + * Switch [OK="OFF", ALERT="ON"] +* Supported metadata parameters: + * inverted=`` + * set to true to invert item state + * defaults to false + +#### `ZonesAlert` + +Items that represent the alert state of a security panel when it has open zones, that must be bypassed, preventing arming. This needs to be paired with [`ArmState`](#armstate). + +* Supported item types: + * Contact [OK="CLOSED", ALERT="OPEN"] + * Switch [OK="OFF", ALERT="ON"] +* Supported metadata parameters: + * inverted=`` + * set to true to invert item state + * defaults to false + +### Sensor Attributes + +#### `BatteryLevel` + +Items that represent a battery level percentage of a device. + +* Supported item types: + * Dimmer + * Number(:Dimensionless) +* Utterance examples: + * *Alexa, what's the `` battery level?* + +#### `CurrentHumidity` + +Items that represent a humidity sensor that provides the ambient humidity. + +* Supported item types: + * Dimmer + * Number(:Dimensionless) +* Utterance examples: + * *Alexa, what’s the `` humidity?* + + + +#### `CurrentTemperature` + +Items that represent a temperature sensor that provides the ambient temperature. + +* Supported item types: + * Number(:Temperature) +* Supported metadata parameters: + * scale=`` + * Celsius or Fahrenheit + * defaults to [item unit of measurement](#item-unit-of-measurement), otherwise Celsius +* Utterance examples: + * *Alexa, what’s the `` temperature?* + * *Alexa, what’s the temperature in ``?* + + + +#### `ContactDetectionState` + +Items that represent a contact sensor state. Currently not usable in routines as proactive reporting not supported yet. + +* Supported item types: + * Contact [DETECTED="OPEN", NOT_DETECTED="CLOSED"] + * Switch [DETECTED="ON", NOT_DETECTED="OFF"] +* Supported metadata parameters: + * inverted=`` + * set to true to invert item state + * defaults to false +* Utterance examples: + * *Alexa, is the `` open?* + + + +#### `MotionDetectionState` + +Items that represent a motion sensor state. Currently not usable in routines as proactive reporting not supported yet. + +* Supported item types: + * Contact [DETECTED="OPEN", NOT_DETECTED="CLOSED"] + * Switch [DETECTED="ON", NOT_DETECTED="OFF"] +* Supported metadata parameters: + * inverted=`` + * set to true to invert item state + * defaults to false + +### Switchable Attributes + + + +#### `PowerState` + +Items that represent a general device responding to on/off commands. For Number and String, the state mappings must be provided in the metadata parameters. + +* Supported item types: + * Color + * Dimmer + * Number (Requires state mappings) + * String (Requires state mappings) + * Switch +* Supported metadata parameters: + * OFF=`` (Number/String only) + * ON=`` (Number/String only) +* Utterance examples: + * *Alexa, turn on the ``.* + * *Alexa, turn off the ``.* + + + +#### `PowerLevel` + +Items that represent a general device responding to power level commands. + +* Supported item types: + * Dimmer +* Utterance examples: + * *Alexa, set the power to 40 percent on the ``.* + * *Alexa, increase the power level by 12 on the ``.* + * *Alexa, decrease the power level by 6 on the ``.* + + + +#### `Percentage` + +Items that represent a general device responding to percentage commands. + +* Supported item types: + * Dimmer + * Rollershutter +* Supported metadata parameters: + * inverted=`` + * set to true to invert item state + * defaults to true for Rollershutter, otherwise false for Dimmer +* Utterance examples: + * *Alexa, set the `` to 30 percent.* + * *Alexa, increase the `` by 10 percent.* + * *Alexa, decrease the `` by 5 percent.* + +### Thermostat Attributes + + + +#### `TargetTemperature` + +Items that represent a target setpoint for a thermostat. + +* Supported item types: + * Number(:Temperature) +* Supported metadata parameters: + * scale=`` + * Celsius or Fahrenheit + * defaults to [item unit of measurement](#item-unit-of-measurement), otherwise Celsius + * setpointRange=`` + * range formatted as `:` (e.g. `setpointRange="60:90"`) + * defaults to 4°C -> 32°C or 40°F -> 90°F +* Utterance examples: + * *Alexa, set the `` to 70.* + * *Alexa, make it warmer in here.* + * *Alexa, make it cooler in here.* + * *Alexa, what's the `` set to?* + + + + +#### `CoolingSetpoint` + +Items that represent an upper or cooling setpoint for a thermostat. This needs to be paired with [`HeatingSetpoint`](#heatingsetpoint). + +By default, if the target, cooling and heating setpoints along with the thermostat mode are defined, the setpoint mode automation will be enabled limiting to dual mode interactions. For true triple mode support, set parameter `supportsSetpointMode=false` on the [`HeatingCoolingMode`](#heatingcoolingmode) item. It is important to note that only the target setpoint can be requested by voice. Therefore, when the thermostat is in dual mode, the cooling and heating setpoints will be updated based on the `comfortRange` parameter. + +* Supported item types: + * Number(:Temperature) +* Supported metadata parameters: + * scale=`` + * Celsius or Fahrenheit + * defaults to [item unit of measurement](#item-unit-of-measurement), otherwise Celsius + * comfortRange=`` + * used in dual setpoint mode to determine: + * the adjusted cooling/heating setpoints spread based on target setpoint + * the minimum temperature delta between requested cooling/heating setpoints by adding relevant comfort range values + * defaults to 2°F or 1°C + * setpointRange=`` + * range formatted as `:` (e.g. `setpointRange="60:90"`) + * defaults to 4°C -> 32°C or 40°F -> 90°F + + + + +#### `HeatingSetpoint` + +Items that represent a lower or heating setpoint for a thermostat. This needs to be paired with [`CoolingSetpoint`](#coolingsetpoint). + +Same configuration as [`CoolingSetpoint`](#coolingsetpoint). + +#### `EcoCoolingSetpoint` + +Items that represent an upper or cooling setpoint for a thermostat integration that uses separate cooling/heating setpoints in ECO mode (e.g. Nest). This needs to be paired with [`EcoHeatingSetpoint`](#ecoheatingsetpoint). + +Same configuration as [`CoolingSetpoint`](#coolingsetpoint). + +#### `EcoHeatingSetpoint` + +Items that represent an lower or heating setpoint for a thermostat integration that uses separate cooling/heating setpoints in ECO mode (e.g. Nest). This needs to be paired with [`EcoCoolingSetpoint`](#ecocoolingsetpoint). + +Same configuration as [`CoolingSetpoint`](#coolingsetpoint). + + + +#### `HeatingCoolingMode` + +Items that represent the heating/cooling mode of a thermostat. + +* Supported item types: + * Number [OFF=0, HEAT=1, COOL=2, AUTO=3, ECO=4] + * String [OFF="off", HEAT="heat", COOL="cool", AUTO="auto", ECO="eco"] + * Switch [OFF="OFF", HEAT="ON"] +* Supported binding presets: + * [broadlinkthermostat](https://www.openhab.org/addons/bindings/broadlinkthermostat/) [HEAT="manual", AUTO="auto"] + * [daikin](https://www.openhab.org/addons/bindings/daikin/) [HEAT="HEAT", COOL="COLD", AUTO="AUTO"] + * [ecobee](https://www.openhab.org/addons/bindings/ecobee/) [OFF="off", HEAT="heat", COOL="cool", AUTO="auto"] + * [insteon](https://www.openhab.org/addons/bindings/insteon/) [OFF=0, HEAT=1, COOL=2, AUTO=3] + * [max](https://www.openhab.org/addons/bindings/max/) [HEAT="MANUAL", AUTO="AUTOMATIC", ECO="VACATION"] + * [nest](https://www.openhab.org/addons/bindings/nest/) [OFF="OFF", HEAT="HEAT", COOL="COOL", AUTO="HEAT_COOL", ECO="ECO"] + * [radiothermostat](https://www.openhab.org/addons/bindings/radiothermostat/) [OFF=0, HEAT=1, COOL=2, AUTO=3] + * [venstarthermostat](https://www.openhab.org/addons/bindings/venstarthermostat/) [OFF="off", HEAT="heat", COOL="cool", AUTO="auto"] + * [zwave](https://www.openhab.org/addons/bindings/zwave/) [OFF=0, HEAT=1, COOL=2, AUTO=3] +* Supported metadata parameters: + * OFF=`` + * HEAT=`` + * COOL=`` + * ECO=`` + * AUTO=`` + * binding=`` + * id formatted as `` (e.g. `binding="nest"`) + * only for [GUI-based configuration](https://www.openhab.org/docs/configuration/) + * defaults to channel metadata value for items configured via text files + * supportedModes=`` + * comma delimited list (e.g. `supportedModes="OFF,HEAT,COOL,AUTO"`) + * defaults to, depending on the parameters provided in order of precedence: + * user-defined mappings (e.g `OFF=0,HEAT=1,COOL=2`) + * preset-based related to the thermostat binding linked + * item type-based default mappings + * supportsSetpointMode=`` + * set to false to disable the thermostat setpoint mode-aware feature (Refer to [cooling/heating setpoints](#coolingsetpoint)) + * defaults to true +* Utterance examples: + * *Alexa, set the `` to heat.* + * *Alexa, set the `` to cool.* + * *Alexa, set the `` to auto.* + * *Alexa, set the `` to eco.* + * *Alexa, set the `` to off.* + * *Alexa, turn on the ``.* (Switch only) + * *Alexa, turn off the ``.* (Switch only) + * *Alexa, what's the `` set to?* + +#### `ThermostatHold` + +Items that represent the hold setting of a thermostat. This needs to be paired with [`HeatingCoolingMode`](#heatingcoolingmode). Only requests to resume schedule (turn off hold) are supported. + +* Supported item types: + * Number [RESUME=0] + * String [RESUME="off"] + * Switch [RESUME="OFF"] +* Supported metadata parameters: + * RESUME=`` +* Utterance examples: + * *Alexa, resume the `` schedule.* + +#### `ThermostatFan` + +Items that represent the fan mode of a thermostat. Due to a limitation on the Alexa end, the "Auto" fan mode is named "Default" to prevent a conflict between the thermostat heating/cooling and fan modes when requesting by voice. + +* Supported item types: + * String [AUTO="AUTO", ON="ON"] + * Switch (on/off control) +* Supported metadata parameters: + * AUTO=`` (String only) + * ON=`` (String only) + * inverted=`` (Switch only) + * set to true to invert state + * defaults to false +* Utterance examples: + * *Alexa, set the `` fan to on.* (String only) + * *Alexa, set the `` fan to default.* (String only) + * *Alexa, turn on the `` fan.* (Switch only) + * *Alexa, turn off the `` fan.* (Switch only) + +### Vacuum Attributes + +#### `VacuumMode` + +Items that represent a vacuum mode. At least the clean and dock modes must be defined. The resume/pause controls are depending on pause mode being defined. For stop control, if stop mode not defined, it will fallback to dock mode. + +* Supported item types: + * Number [CLEAN=1, DOCK=2, SPOT=3, PAUSE=4, STOP=5] + * String [CLEAN="CLEAN", DOCK="DOCK", SPOT="SPOT", PAUSE="PAUSE", STOP="STOP"] +* Supported metadata parameters: + * CLEAN=`` + * DOCK=`` + * SPOT=`` + * PAUSE=`` + * STOP=`` +* Utterance examples: + * *Alexa, turn on the ``.* (Clean mode) + * *Alexa, turn off the ``.* (Dock mode) + * *Alexa, pause the ``.* (Pause mode) + * *Alexa, resume the ``.* (Clean mode) + * *Alexa, stop the ``.* (Stop/Dock mode) + * *Alexa, set the `` mode to spot.* (Spot mode) + * *Alexa, what's the `` mode?* + +### Generic Attributes + + + + +#### `Mode` + +Items that represent components of a device that have more than one setting. Multiple instances can be configured in a [group endpoint](#group-endpoint). + +* Supported item types: + * Number + * String + * Switch +* Supported metadata parameters: + * capabilityNames=`` + * each name formatted as `<@assetIdOrName>` (e.g. `capabilityNames="Wash Temperature,@Setting.WaterTemperature"`) + * predefined [asset ids](#asset-catalog) + * list of text-based names [not allowed](#capability-names-not-allowed) + * defaults to `@Setting.Mode` if [single endpoint](#single-endpoint), otherwise item label and synonyms metadata if part of [group endpoint](#group-endpoint) + * nonControllable=`` + * set to true for state reporting support only + * defaults to item state description read only property if defined, otherwise false + * supportedModes=`` + * each mode formatted as `=<@assetIdOrName1>:...` (e.g. `supportedModes="0=Cold:Cool,1=Warm,2=Hot"`) + * requires at least two modes to be specified + * shortened format available for string-based modes by either leaving the first element empty or not providing the mode name at all (e.g. `supportedModes="Normal=:Cottons,Whites"` <=> `supportedModes="Normal=Normal:Cottons,Whites=Whites`) + * defaults to item state description options `supportedModes="value1=label1,..."`, if defined, otherwise no supported modes + * ordered=`` + * set to true if modes can be adjusted incrementally (e.g. temperature control) + * defaults to false + * language=`` + * text-based name language support + * two-letter language code: `de`, `en`, `es`, `fr`, `hi`, `it`, `ja`, `pt` + * defaults to your server [regional settings](#regional-settings) if defined, otherwise `en` + * actionMappings=`` + * each [semantic](#semantic-extensions) mapping formatted as, based on action type: (e.g. `actionMappings="Close=DOWN,Open=UP,Lower=DOWN,Raise=UP,Stop=STOP"`) + * set => `=` + * adjust => `=()` (Supported only if `ordered=true`) + * [supported action semantics](#semantic-catalog) + * only one specific action semantic allowed per endpoint, except for `TurnOn` and `TurnOff` + * no support for `TurnOn` and `TurnOff` semantics on Switch, use [`ToggleState`](#togglestate) instead + * defaults to no actions + * stateMappings=`` + * each [semantic](#semantic-extensions) mapping formatted as `=` (e.g. `stateMappings="Closed=CLOSED,Open=OPEN"`) + * [supported state semantics](#semantic-catalog) + * only one specific state semantic allowed per endpoint, except for `On` and `Off` + * no support for `On` and `Off` semantics on Switch, use [`ToggleState`](#togglestate) instead + * defaults to no states +* Utterance examples: + * *Alexa, set the `` `` to ``.* + * *Alexa, increase the `` ``.* (if `ordered=true`) + * *Alexa, decrease the `` ``.* (if `ordered=true`) + * *Alexa, what's the `` ``?* + * *Alexa, open the ``.* (if `Open` action defined) + * *Alexa, close the ``.* (if `Close` action defined) + * *Alexa, raise the ``.* (if `Raise` action defined) + * *Alexa, lower the ``.* (if `Lower` action defined) + * *Alexa, resume the ``.* (if `Resume` action defined) + * *Alexa, pause the ``.* (if `Pause` action defined) + * *Alexa, stop the ``.* (if `Stop` action defined) + * *Alexa, turn on the `` ``.* (if `TurnOn` action defined) + * *Alexa, turn off the `` ``.* (if `TurnOff` action defined) + + + + +#### `RangeValue` + +Items that represent components of a device that are characterized by numbers within a minimum and maximum range. Multiple instances can be configured in a [group endpoint](#group-endpoint). + +* Supported item types: + * Dimmer + * Number + * Number:Angle + * Number:Dimensionless + * Number:Length + * Number:Mass + * Number:Temperature + * Number:Volume + * Rollershutter +* Supported metadata parameters: + * capabilityNames=`` + * each name formatted as `<@assetIdOrName>` (e.g. `capabilityNames="@Setting.FanSpeed,Speed"`) + * predefined [asset ids](#asset-catalog) + * list of text-based names [not allowed](#capability-names-not-allowed) + * defaults to `@Setting.RangeValue` if [single endpoint](#single-endpoint), otherwise item label and synonyms metadata if part of [group endpoint](#group-endpoint) + * nonControllable=`` + * set to true for state reporting support only + * defaults to item state description read only property if defined, otherwise false + * inverted=`` + * set to true to invert item state + * defaults to true for Rollershutter, otherwise false for other supported item types. + * supportedCommands=`` (Dimmer/Rollershutter only) + * each command formatted as: + * default name => `` (e.g. `supportedCommands="INCREASE,DECREASE"`) + * custom name => `=<@assetIdOrName1>:...` (e.g. `supportedCommands="INCREASE=@Value.Up,DECREASE=@Value.Down"`) + * supported commands are ON, OFF, INCREASE, DECREASE (Dimmer); UP, DOWN, MOVE, STOP (Rollershutter) + * defaults to no support + * supportedRange=`` + * range formatted as `::` (e.g. `supportedRange="0:100:1"`) + * precision value used as default increment for adjusted range value request. + * defaults to item state description min, max & step values, if defined, otherwise `"0:100:1"` (Dimmer/Rollershutter); `"0:10:1"` (Number) + * presets=`` + * each preset formatted as `=<@assetIdOrName1>:...` (e.g. `presets="1=@Value.Low:Lowest,10=@Value.High:Highest"`) + * requires to be a multiple of the supported range precision + * defaults to item state description options `presets="value1=label1,..."` if defined, otherwise no presets + * unitOfMeasure=`` + * supported [unid id](#unit-of-measurement-catalog) + * defaults to unit of item state presentation, if available, or item type-based default unit as follow: + * Dimmer => `Percent` + * Number:Angle => `Angle.Degrees` + * Number:Length => `Distance.Meters` (SI); `Distance.Inches` (US) + * Number:Temperature => `Temperature.Celsius` (SI); `Temperature.Fahrenheit` (US) + * Rollershutter => `Percent` + * language=`` + * text-based name language support + * two-letter language code: `de`, `en`, `es`, `fr`, `hi`, `it`, `ja`, `pt` + * defaults to your server [regional settings](#regional-settings) if defined, otherwise `en` + * actionMappings=`` + * each [semantic](#semantic-extensions) mapping formatted as, based on action type: (e.g. `actionMappings="Close=0,Open=100,Lower=(-10),Raise=(+10)"`) + * set => `=` + * adjust => `=()` + * supported commands can be mapped as well (e.g. `actionMappings="Close=DOWN,Open=UP,Lower=DOWN,Raise=UP,Stop=STOP"`) + * [supported action semantics](#semantic-catalog) + * only one specific action semantic allowed per endpoint, except for `TurnOn` and `TurnOff` + * no support for: + * any [custom semantics](#custom-semantic-catalog) on Number with defined dimension + * `TurnOn` and `TurnOff` semantics on Rollershutter + * defaults to no actions + * stateMappings=`` + * each [semantic](#semantic-extensions) mapping formatted as, based on state type: (e.g. `stateMappings="Closed=0,Open=1:100"`) + * range => `=:` + * value => `=` + * [supported state semantics](#semantic-catalog) + * only one specific state semantic allowed per endpoint, except for `On` and `Off` + * no support for: + * any [custom semantics](#custom-semantic-catalog) on Number with defined dimension + * `On` and `Off` semantics on Rollershutter + * defaults to no states +* Utterance examples: + * *Alexa, set the `` `` to 10.* + * *Alexa, set the `` `` to 50 percent.* (if `unitOfMeasure="Percent"`) + * *Alexa, set the `` `` to ``.* (if `presets` defined) + * *Alexa, set the `` `` to ``.* (if `supportedCommands` defined) + * *Alexa, increase the `` `` by 5.* + * *Alexa, decrease the `` ``.* + * *Alexa, what's the `` ``?* + * *Alexa, open the ``.* (if `Open` action defined) + * *Alexa, close the ``.* (if `Close` action defined) + * *Alexa, raise the ``.* (if `Raise` action defined) + * *Alexa, lower the ``.* (if `Lower` action defined) + * *Alexa, resume the ``.* (if `Resume` action defined) + * *Alexa, pause the ``.* (if `Pause` action defined) + * *Alexa, stop the ``.* (if `Stop` action defined) + * *Alexa, turn on the `` ``.* (if `TurnOn` action defined) + * *Alexa, turn off the `` ``.* (if `TurnOff` action defined) + + + + +#### `ToggleState` + +Items that represent components of a device that can be toggled on or off. Multiple instances can be configured in a [group endpoint](#group-endpoint). + +* Supported item types: + * Switch +* Supported metadata parameters: + * capabilityNames=`` + * each name formatted as `<@assetIdOrName>` (e.g. `capabilityNames="@Setting.Oscillate,Rotate"`) + * predefined [asset ids](#asset-catalog) + * list of text-based names [not allowed](#capability-names-not-allowed) + * defaults to `@Setting.ToggleState` if [single endpoint](#single-endpoint), otherwise item label and synonyms metadata if part of [group endpoint](#group-endpoint) + * nonControllable=`` + * set to true for state reporting support only + * defaults to item state description read only property if defined, otherwise false + * inverted=`` + * set to true to invert item state + * defaults to false + * language=`` + * text-based name language support + * two-letter language code: `de`, `en`, `es`, `fr`, `hi`, `it`, `ja`, `pt` + * defaults to your server [regional settings](#regional-settings) if defined, otherwise `en` + * actionMappings=`` + * each [semantic](#semantic-extensions) mapping formatted as `=ON` or `=OFF` (e.g. `actionMappings="Close=OFF,Open=ON"`) + * [supported action semantics](#semantic-catalog) + * only one specific action semantic allowed per endpoint + * defaults to no actions + * stateMappings=`` + * each [semantic](#semantic-extensions) mapping formatted as `=ON` or `=OFF` (e.g. `stateMappings="Closed=OFF,Open=ON"`) + * [supported state semantics](#semantic-catalog) + * only one specific state semantic allowed per endpoint + * defaults to no states +* Utterance examples: + * *Alexa, turn on the `` ``.* + * *Alexa, turn off the `` ``.* + * *Alexa, what's the `` ``?* + * *Alexa, is the `` `` on?* + * *Alexa, open the ``.* (if `Open` action defined) + * *Alexa, close the ``.* (if `Close` action defined) + * *Alexa, raise the ``.* (if `Raise` action defined) + * *Alexa, lower the ``.* (if `Lower` action defined) + * *Alexa, resume the ``.* (if `Resume` action defined) + * *Alexa, pause the ``.* (if `Pause` action defined) + * *Alexa, stop the ``.* (if `Stop` action defined) # Troubleshooting -Here are some of the most common generic errors you may encounter while using this skill: +## Response Errors ### Command Not Working -* Alexa will respond with "That command doesn't work on _device_" + +* Alexa will respond with "That command doesn't work on _device_". * It indicates that the command that Alexa is trying to send to openHAB doesn't work, either because the intended device is not configured properly to support that command or because your openHAB items configuration has changed and a previously discovered item may longer accept certain commands. For example, a dimmer item type that was initially setup and was changed to a switch type, will cause Alexa brightness control commands to fail. * To resolve this error, make sure to update your openHAB items configuration accordingly and run a discovery update either through the Alexa app or just by asking "Alexa, discover" on your echo device. ### Device Not Found -* Alexa will respond with "I couldn't find a device or group named _device_ in your profile" + +* Alexa will respond with "I couldn't find a device or group named _device_ in your profile". * It indicates that, either a device currently setup in your Alexa account, no longer exists in your openHAB server, or vice-versa. * To resolve this error, make sure to run a discovery update either through the Alexa app or just by asking "Alexa, discover" on your echo device. Keep in mind that previously discovered devices that have been removed from the openHAB configuration will show as offline under your Alexa account and not be automatically removed. To prevent potential device name conflicts, it is highly recommended to remove these devices through the Alexa app. * If all your Alexa-enabled devices in openHAB aren't discovered or getting updated: * Check that your [server is available](#server-not-accessible). * Look for any relevant errors in your openHAB server logs. + * Check the spelling of your Alexa metadata configuration. It is case sensitive. * If only new devices aren't found, make sure your last Alexa-related config changes are valid. * If necessary, stagger the discovery process by adding a couple devices at a time to isolate the culprit. ### Device Not Responding + * Alexa will respond with "_device_ isn't responding, please check its network connection and power supply", and in some rare occasions, no response or acknowledgement will be given. * It indicates that the state of one or more of the endpoint properties retrieved from the openHAB server are considered invalid, mostly because it is in either uninitialized `NULL` or undefined `UNDEF` state. -* To resolve this error, make sure that all items interfacing with Alexa have a defined state. If necessary, use [item sensors](#item-sensor), or if the state is not available in openHAB, set the [item state](#item-state) to not be retrievable. -* For group endpoints, partial properties responses will be send back to Alexa excluding items with invalid state. This will allow Alexa to acknowledge a command request assuming that the relevant item state is accurate. However, it will cause Alexa to generate this error when requesting the status of a device configured with an interface supporting that feature. For example, using a thermostat group endpoint, a request to set its mode will succeed but requesting its mode status will fail if one of its property state, such as its temperature sensor, is not defined in openHAB. +* To resolve this error, make sure that all items interfacing with Alexa have a defined state. If the state is not available in openHAB, set the [item state](#item-state) to not be retrievable. +* For group endpoints, partial properties responses will be send back to Alexa excluding items with invalid state. This will allow Alexa to acknowledge a command request assuming that the relevant item state is accurate. However, it will cause Alexa to generate this error when requesting the status of a device configured with an attribute supporting these requests. For example, using a thermostat group endpoint, a request to set its mode will succeed but requesting its mode status will fail if one of its property state, such as its temperature sensor, is not defined in openHAB. * This is the default error. ### Duplicate Device Names -* Alexa will respond with "A few things share the name _device_, which one did you want?" + +* Alexa will respond with "A few things share the name _device_, which one did you want?". * It indicates that more than one device on your Alexa account matches the device name requested. * To resolve this error, make sure that all the [item labels](#item-labels) related to your Alexa-enabled items are unique. Additionally, check your Alexa account for discovered devices from other skills or local integrations (e.g. Philips Hue bridge), that may have overlapping names. +### Request Error + +* Alexa will respond with "I'm not sure what went wrong". +* It indicates that a requested command caused an error preventing the Alexa Smart Home API from handling it. This is usually due to either a given capability not supported in your language or a bug in the Alexa API handling the request. +* If you have confirmed that the requested capability should be [available in your region](#regional-availability), please search in the [community forum](https://community.openhab.org/c/apps-services/amazon-alexa) for an existing related post and, if necessary, open a new topic including all the details to replicate this error. + ### Request Not Supported -* Alexa will respond with "_device_ doesn't support that" -* It indicates that a requested command is not supported by any of the device configured interfaces. -* To resolve this error, make sure that the relevant interfaces are configured properly on the given device. If this is the case, the response implies a limitation on the Alexa side. This will happen for a device with specific interfaces that don't support certain voice requests as of yet, such as the state of a PowerController or BrightnessController interface. + +* Alexa will respond with "_device_ doesn't support that". +* It indicates that a requested command is not supported by any of the device configured attributes. +* To resolve this error, make sure that the relevant attributes are configured properly on the given device. If this is the case, the response implies a limitation on the Alexa side. This will happen for a device with specific attributes that don't support certain voice requests as of yet, such as the state of a `Switch` or `Light` capable item. ### Server Authentication Issue -* Alexa will respond with "Sorry something wrong, to control _device_ try disabling the skill and re-enabling it from your Alexa app" + +* Alexa will respond with "Sorry something wrong, to control _device_ try disabling the skill and re-enabling it from your Alexa app". * It indicates that Alexa isn't able to control the given device because of an authentication issue. -* To resolve this error, for users that are using the official skill, just disable and re-enable it through the Alexa app. For users that have setup their own custom skill, make sure that the proper credentials were added to the lambda function config.js. +* To resolve this error, for users that are using the official skill, just disable and re-enable it through the Alexa app. For users that have setup their own custom skill, make sure that the proper credentials were added to the lambda function config.js. If running an openHAB 3.x server, make sure that the API Security Implicit User Role setting is enabled. ### Server Not Accessible -* Alexa will respond with "Sorry the hub that _device_ is connected to is not responding, please check its network connection and power supply" + +* Alexa will respond with "Sorry the hub that _device_ is connected to is not responding, please check its network connection and power supply". * It indicates that your openHAB server is not accessible through [myopenHAB](https://myopenhab.org) cloud service. * To resolve this error, make sure that your server is running, your openHAB cloud service is configured with mode set to "Notifications & Remote Access", and showing online under your myopenHAB account. For users that have setup their own custom skill, make sure that the proper server base URL was added to the lambda function config.js. -* For users running openHAB 2.4, there is a known issue when running the [Amazon Echo Control](https://www.openhab.org/addons/bindings/amazonechocontrol/) binding, associated to that release, that affects the server accessibility. The workaround is to use the latest stable [release candidate](https://community.openhab.org/t/release-candidate-and-support-amazon-echo-control-binding/37844) version of that binding instead. +* For users running openHAB 2.4, there is a known issue when running the [Amazon Echo Control](https://www.openhab.org/addons/bindings/amazonechocontrol/) binding, associated to that release, that affects the server accessibility. In this instance, make sure to upgrade your server to 2.5 or above. ### Temperature Out Of Range -* Alexa will respond with "I can only set the temperature between _minValue_ and _maxValue_" -* It indicates that a requested target temperature is out of range, based on the [target](#thermostatcontroller-targetsetpoint), [upper](#thermostatcontroller-uppersetpoint), or [lower](#thermostatcontroller-lowersetpoint) setpoint default range values. + +* Alexa will respond with "I can only set the temperature between _minValue_ and _maxValue_". +* It indicates that a requested target temperature is out of range, based on the [target](#targettemperature), [cooling](#coolingsetpoint), or [heating](#heatingsetpoint) temperature setpoints default range values. * To resolve this error, add the metadata parameter `setpointRange=":"` on your relevant thermostat setpoint items to customize your range values and run a discovery update either through the Alexa app or just by asking "Alexa, discover" on your echo device. -# Example Voice Commands +# Additional Information + +## Regional Availability + +The availability of a given capability depends on the location setting of your Amazon account under which your echo devices are registered to. Here is the latest list of Alexa interface capabilities with their associated supported device attributes and languages from the [Alexa Skill API](https://developer.amazon.com/docs/device-apis/list-of-interfaces.html) documentation: + +Alexa Interfaces | Supported Attributes | Supported Languages +-----------------|------------------------|-------------------- +BrightnessController | [`Brightness`](#brightness) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `fr-FR`, `hi-IN`, `it-IT`, `ja-JP`, `pt-BR` +CameraStreamController | [`CameraStream`](#camerastream) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `es-MX`, `fr-FR`, `hi-IN`, `it-IT`, `ja-JP`, `pt-BR` +ChannelController | [`Channel`](#channel) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `es-MX`, `fr-FR`, `hi-IN`, `it-IT`, `ja-JP`, `pt-BR` +ColorController | [`Color`](#color) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `fr-FR`, `hi-IN`, `it-IT`, `ja-JP`, `pt-BR` +ColorTemperatureController | [`ColorTemperature`](#colortemperature) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `fr-FR`, `hi-IN`, `it-IT`, `ja-JP`, `pt-BR` +ContactSensor | [`ContactDetectionState`](#contactdetectionstate) | `de-DE`, `en-AU`, `en-CA`, `en-IN`, `en-US`, `es-ES`, `it-IT`, `ja-JP` +EqualizerController | [`EqualizerBass`](#equalizerbass), [`EqualizerMidrange`](#equalizermidrange), [`EqualizerTreble`](#equalizertreble), [`EqualizerMode`](#equalizermode) | `de-DE`, `en-IN`, `en-US`, `es-ES`, `it-IT`, `ja-JP`, `pt-BR` +KeypadController | [`Navigation`](#navigation) | `en-GB`, `en-US`, `es-MX` +LockController | [`LockState`](#lockstate) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `es-MX`, `es-US`, `fr-CA`, `fr-FR`, `hi-IN`, `it-IT`, `ja-JP`, `pt_BR` +ModeController | [`Mode`](#mode), [`FanDirection`](#fandirection), [`FanSpeed`](#fanspeed), [`Input`](#input), [`OpenState`](#openstate), [`PositionState`](#positionstate), [`TiltAngle`](#tiltangle), [`ThermostatFan`](#thermostatfan), [`VacuumMode`](#vacuummode) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `es-MX`, `fr-CA`, `fr-FR`, `it-IT`, `ja-JP` +MotionSensor | [`MotionDetectionState`](#motiondetectionstate) | `de-DE`, `en-AU`, `en-CA`, `en-IN`, `en-US`, `es-ES`, `it-IT`, `ja-JP`, `pt-BR` +Networking | [`HomeNetwork`](#homenetwork), [`ConnectedDevice`](#connecteddevice), [`NetworkAccess`](#networkaccess) | `en-US` +PercentageController | [`Percentage`](#percentage) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `fr-FR`, `it-IT`, `ja-JP` +PlaybackController | [`Playback`](#playback), [`PlaybackStop`](#playbackstop) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `fr-FR` +PowerController | [`PowerState`](#powerstate) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `es-MX`, `fr-FR`, `it-IT`, `ja-JP` +PowerLevelController | [`PowerLevel`](#powerlevel) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `fr-FR`, `it-IT`, `ja-JP` +RangeController | [`RangeValue`](#rangevalue), [`BatteryLevel`](#batterylevel), [`CurrentHumidity`](#currenthumidity), [`FanSpeed`](#fanspeed), [`PositionState`](#positionstate), [`TiltAngle`](#tiltangle) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `es-MX`, `fr-CA`, `fr-FR`, `it-IT`, `ja-JP` +Safety | [`ObstacleAlert`](#obstaclealert), [`SafetyBeamAlert`](#safetybeamalert) | `en-US` +SceneController | [`Scene`](#scene), [`Activity`](#activity) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `fr-FR`, `it-IT`, `ja-JP` +SecurityPanelController | [`ArmState`](#armstate), [`BurglaryAlarm`](#burglaryalarm), [`CarbonMonoxideAlarm`](#carbonmonoxidealarm), [`FireAlarm`](#firealarm), [`WaterAlarm`](#wateralarm) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `es-MX`, `es-US`, `fr-CA`, `fr-FR`, `it-IT`, `ja-JP`, `pt-BR` +Speaker | [`VolumeLevel`](#volumelevel), [`MuteState`](#mutestate) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `es-MX`, `it-IT`, `ja-JP` +StepSpeaker | [`VolumeLevel`](#volumelevel), [`MuteState`](#mutestate) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `it-IT` +TemperatureSensor | [`CurrentTemperature`](#currenttemperature) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `fr-FR`, `it-IT`, `ja-JP` +ThermostatController | [`TargetTemperature`](#targettemperature), [`CoolingSetpoint`](#coolingsetpoint), [`HeatingSetpoint`](#heatingsetpoint), [`HeatingCoolingMode`](#heatingcoolingmode), [`ThermostatHold`](#thermostathold) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `fr-FR`, `it-IT`, `ja-JP`, `pt-BR` +ToggleController | [`ToggleState`](#togglestate), [`FanOscillate`](#fanoscillate), [`ThermostatFan`](#thermostatfan) | `de-DE`, `en-AU`, `en-CA`, `en-GB`, `en-IN`, `en-US`, `es-ES`, `es-MX`, `fr-CA`, `fr-FR`, `it-IT`, `ja-JP` + +## Asset Catalog + +### Alexa Asset Catalog + +List of Alexa asset catalog from the [Alexa Skill API](https://developer.amazon.com/docs/device-apis/resources-and-assets.html#global-alexa-catalog) documentation: -Here are some example voice commands: +Asset Identifier | Supported Friendly Names +-----------------|------------------------- +`@DeviceName.AirPurifier` | Air Purifier
Air Cleaner
Clean Air Machine +`@DeviceName.Camera` | Camera +`@DeviceName.Fan` | Fan
Blower +`@DeviceName.Router` | Router
Internet Router
Network Router
Wi-Fi Router
Net Router +`@DeviceName.Shade` | Shade
Blind
Curtain
Roller
Shutter
Drape
Awning
Window Shade
Interior blind +`@DeviceName.Shower` | Shower +`@DeviceName.SpaceHeater` | Space Heater
Portable Heater +`@DeviceName.Washer` | Washer
Washing Machine +`@Setting.2GGuestWiFi` | 2.4G Guest Wi-Fi
2.4G Guest Network
Guest Network 2.4G
2G Guest Wi-Fi +`@Setting.5GGuestWiFi` | 5G Guest Wi-Fi
5G Guest Network
Guest Network 5G
5G Guest Wi-Fi +`@Setting.Auto` | Auto
Automatic
Automatic Mode
Auto Mode +`@Setting.Direction` | Direction +`@Setting.DryCycle` | Dry Cycle
Dry Preset
Dry Setting
Dryer Cycle
Dryer Preset
Dryer Setting +`@Setting.FanSpeed` | Fan Speed
Airflow Speed
Wind Speed
Air Speed
Air Velocity +`@Setting.GuestWiFi` | Guest Wi-Fi
Guest Network
Guest Net +`@Setting.Heat` | Heat +`@Setting.Mode` | Mode +`@Setting.Night` | Night
Night Mode +`@Setting.Opening` | Opening
Height
Lift
Width +`@Setting.Oscillate` | Oscillate
Swivel
Oscillation
Spin
Back and Forth +`@Setting.Preset` | Preset
Setting +`@Setting.Quiet` | Quiet
Quiet Mode
Noiseless
Silent +`@Setting.Temperature` | Temperature
Temp +`@Setting.WashCycle` | Wash Cycle
Wash Preset
Wash setting +`@Setting.WaterTemperature` | Water Temperature
Water Temp
Water Heat +`@Shower.HandHeld` | Handheld Shower
Shower Wand
Hand Shower +`@Shower.RainHead` | Rain Head
Overhead Shower
Rain Shower
Rain Spout
Rain Faucet +`@Value.Close` | Close +`@Value.Delicate` | Delicates
Delicate +`@Value.High` | High +`@Value.Low` | Low +`@Value.Maximum` | Maximum
Max +`@Value.Medium` | Medium
Mid +`@Value.Minimum` | Minimum
Min +`@Value.Open` | Open +`@Value.QuickWash` | Quick Wash
Fast Wash
Wash Quickly
Speed Wash + +### Custom Asset Catalog + +List of custom asset catalog defined by the skill: + +Asset Identifier | Supported Friendly Names +-----------------|------------------------- +`@Setting.Angle` | Angle +`@Setting.BatteryLevel` | Battery Level +`@Setting.Clean` | Clean +`@Setting.Dock` | Dock +`@Setting.Forward` | Forward +`@Setting.Humidity` | Humidity +`@Setting.Input` | Input +`@Setting.Position` | Position +`@Setting.RangeValue` | Range Value +`@Setting.Reverse` | Reverse +`@Setting.Speed` | Speed +`@Setting.Spot` | Spot +`@Setting.Tilt` | Tilt +`@Setting.ToggleState` | Toggle State +`@Value.Decrease` | Decrease +`@Value.Default` | Default +`@Value.Down` | Down +`@Value.Increase` | Increase +`@Value.Left` | Left +`@Value.Move` | Move +`@Value.Off` | Off +`@Value.On` | On +`@Value.Pause` | Pause +`@Value.Resume` | Resume +`@Value.Right` | Right +`@Value.Start` | Start +`@Value.Stop` | Stop +`@Value.Up` | Up + +## Semantic Catalog + +### Alexa Semantic Catalog + +List of Alexa semantic catalog from the [Alexa Skill API](https://developer.amazon.com/docs/alexa-voice-service/generic-controllers.html#semantics-syntax) documentation: + +Semantic Type | Identifiers +--------------|------------ +Actions | `Close`
`Open`
`Lower`
`Raise` +States | `Closed`
`Open` + +### Custom Semantic Catalog + +List of custom semantic catalog defined by skill: + +Semantic Type | Identifiers +--------------|------------ +Actions | `Pause`
`Resume`
`Stop`
`TurnOff`
`TurnOn` +States | `Off`
`On` + +## Unit of Measurement Catalog + +List of Alexa unit of measurement catalog from the [Alexa Skill API](https://developer.amazon.com/docs/device-apis/alexa-property-schemas.html#units-of-measure) documentation: + +Unit Identifier | +----------------| +`Angle.Degrees` | +`Angle.Radians` | +`Distance.Yards` | +`Distance.Inches` | +`Distance.Meters` | +`Distance.Feet` | +`Distance.Miles` | +`Distance.Kilometers` | +`Mass.Kilograms` | +`Mass.Grams` | +`Percent` | +`Temperature.Degrees` | +`Temperature.Celsius` | +`Temperature.Fahrenheit` | +`Temperature.Kelvin` | +`Volume.Gallons` | +`Volume.Pints` | +`Volume.Quarts` | +`Volume.Liters` | +`Volume.CubicMeters` | +`Volume.CubicFeet` | +`Weight.Pounds` | +`Weight.Ounces` | + + + +## Capability Names Not Allowed + +List of Alexa friendly names that cannot be used from the [Alexa Skill API](https://developer.amazon.com/docs/device-apis/resources-and-assets.html#reserved-words) documentation: + +Friendly Names | +---------------| +alarm | +alarms | +all alarms | +away mode | +bass | +camera | +date | +date today | +day | +do not disturb | +drop in | +music | +night light | +notification | +playing | +sleep sounds | +time | +timer | +today in music | +treble | +volume | +way f. m. | - * Alexa turn on Office Lights - * Alexa turn off Pool Waterfall - * Alexa turn on House Fan - * Alexa turn on Home Theater Scene - * Alexa dim Kitchen Lights to 30 percent - * Alexa set house temperature to 70 degrees + -# Other openHAB Alexa Integrations +## Other openHAB Integrations for Amazon Alexa -openHAB has two other Alexa integrations that can be used in conjunction with or independently of this skill. +openHAB has two other integrations for Amazon Alexa that can be used in conjunction with or independently of this skill. ### Amazon Echo Control Binding diff --git a/ask-resources.json b/ask-resources.json new file mode 100644 index 00000000..52553cf1 --- /dev/null +++ b/ask-resources.json @@ -0,0 +1,30 @@ +{ + "askcliResourcesVersion": "2020-03-31", + "profiles": { + "default": { + "skillMetadata": { + "src": "./skill-package" + }, + "code": { + "default": { + "src": "./lambda" + } + }, + "skillInfrastructure": { + "type": "@ask-cli/cfn-deployer", + "userConfig": { + "awsRegion": "us-east-1", + "runtime": "nodejs14.x", + "handler": "index.handler", + "templatePath": "./infrastructure/cfn-deployer/skill-stack.yml", + "cfn": { + "parameters": { + "LambdaFunctionName": "alexa-openhab", + "LambdaLogLevel": "info" + } + } + } + } + } + } +} diff --git a/hooks/post_new_hook.ps1 b/hooks/post_new_hook.ps1 deleted file mode 100755 index a9ad1208..00000000 --- a/hooks/post_new_hook.ps1 +++ /dev/null @@ -1,53 +0,0 @@ -# Powershell script for ask-cli post-new hook for Node.js -# Script Usage: post_new_hook.ps1 - -# SKILL_NAME is the preformatted name passed from the CLI, after removing special characters. -# DO_DEBUG is boolean value for debug logging - -# Run this script one level outside of the skill root folder - -# The script does the following: -# - Run "npm install" in each sourceDir in skill.json - -param( - [string] $SKILL_NAME, - [bool] $DO_DEBUG = $False -) - -if ($DO_DEBUG) { - Write-Output "###########################" - Write-Output "###### post-new hook ######" - Write-Output "###########################" -} - -function install_dependencies ($CWD, $SOURCE_DIR) { - $INSTALL_PATH = $SKILL_NAME + "\" +$SOURCE_DIR - Set-Location $INSTALL_PATH - Invoke-Expression "npm install --production" 2>&1 | Out-Null - $EXEC_RESULT = $? - Set-Location $CWD - return $EXEC_RESULT -} - -$SKILL_FILE_PATH = $SKILL_NAME + "\skill.json" -$ALL_SOURCE_DIRS = Get-Content -Path $SKILL_FILE_PATH | select-string -Pattern "sourceDir" -CaseSensitive -Foreach ($SOURCE_DIR in $ALL_SOURCE_DIRS) { - $FILTER_SOURCE_DIR = $SOURCE_DIR -replace "`"", "" -replace "\s", "" -replace ",","" -replace "sourceDir:", "" - $CWD = (Get-Location).Path - if (install_dependencies $CWD $FILTER_SOURCE_DIR) { - if ($DO_DEBUG) { - Write-Output "Codebase ($FILTER_SOURCE_DIR) built successfully." - } - } else { - if ($DO_DEBUG) { - Write-Output "There was a problem installing dependencies for ($FILTER_SOURCE_DIR)." - } - exit 1 - } -} - -if ($DO_DEBUG) { - Write-Output "###########################" -} - -exit 0 diff --git a/hooks/post_new_hook.sh b/hooks/post_new_hook.sh deleted file mode 100755 index f68c3476..00000000 --- a/hooks/post_new_hook.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -# Shell script for ask-cli post-new hook for Node.js -# Script Usage: post_new_hook.sh - -# SKILL_NAME is the preformatted name passed from the CLI, after removing special characters. -# DO_DEBUG is boolean value for debug logging - -# Run this script one level outside of the skill root folder - -# The script does the following: -# - Run "npm install" in each sourceDir in skill.json - -SKILL_NAME=$1 -DO_DEBUG=${2:-false} - -if [ $DO_DEBUG == false ] -then - exec > /dev/null 2>&1 -fi - -install_dependencies() { - npm install --production --prefix "$SKILL_NAME/$1" >/dev/null 2>&1 - return $? -} - -echo "###########################" -echo "###### post-new hook ######" -echo "###########################" - -grep "sourceDir" $SKILL_NAME/skill.json | cut -d: -f2 | sed 's/"//g' | sed 's/,//g' | while read -r SOURCE_DIR; do - if install_dependencies $SOURCE_DIR; then - echo "Codebase ($SOURCE_DIR) built successfully." - else - echo "There was a problem installing dependencies for ($SOURCE_DIR)." - exit 1 - fi -done -echo "###########################" - -exit 0 diff --git a/hooks/pre_deploy_hook.ps1 b/hooks/pre_deploy_hook.ps1 deleted file mode 100755 index f1134005..00000000 --- a/hooks/pre_deploy_hook.ps1 +++ /dev/null @@ -1,95 +0,0 @@ -# Powershell script for ask-cli pre-deploy hook for Node.js -# Script Usage: pre_deploy_hook.ps1 - -# SKILL_NAME is the preformatted name passed from the CLI, after removing special characters. -# DO_DEBUG is boolean value for debug logging -# TARGET is the deploy TARGET provided to the CLI. (eg: all, skill, lambda etc.) - -# Run this script under the skill root folder - -# The script does the following: -# - Run "npm install" in each sourceDir in skill.json - -param( - [string] $SKILL_NAME, - [bool] $DO_DEBUG = $False, - [string] $TARGET = "all" -) - -function install_dependencies ($CWD, $SOURCE_DIR) { - Set-Location $SOURCE_DIR - Invoke-Expression "npm install --production" 2>&1 | Out-Null - $EXEC_RESULT = $? - Set-Location $CWD - return $EXEC_RESULT -} - -function update_skill_catalog () { - Invoke-Expression "node tools\updateSkillCatalog.js" 2>&1 | Out-Null - return $? -} - -function update_skill_manifest () { - Invoke-Expression "node tools\updateSkillManifest.js" 2>&1 | Out-Null - return $? -} - -if ($DO_DEBUG) { - Write-Output "###########################" - Write-Output "##### pre-deploy hook #####" - Write-Output "###########################" -} - -if (Test-Path .env) { - Get-Content -Path ".env" ` - | Select-String -Pattern "^[^#]\w+" ` - | ForEach-Object {$_ -replace "`"", ""} ` - | ConvertFrom-String -Delimiter "=" -PropertyNames key, value ` - | ForEach-Object {[Environment]::SetEnvironmentVariable($_.key, $_.value)} -} - -if ($TARGET -eq "all" -Or $TARGET -eq "lambda") { - $ALL_SOURCE_DIRS = Get-Content -Path "skill.json" ` - | Select-String -Pattern "sourceDir" -CaseSensitive ` - | ForEach-Object {$_ -replace ".*:\s*`"([^`"]+)`".*", "`$1" -replace "/", "\"} ` - | Sort ` - | Get-Unique - Foreach ($SOURCE_DIR in $ALL_SOURCE_DIRS) { - $CWD = (Get-Location).Path - if (install_dependencies $CWD $SOURCE_DIR) { - if ($DO_DEBUG) { - Write-Output "Codebase ($SOURCE_DIR) built successfully." - } - } else { - if ($DO_DEBUG) { - Write-Output "There was a problem installing dependencies for ($SOURCE_DIR)." - } - exit 1 - } - } - if (update_skill_catalog) { - if ($DO_DEBUG) { - Write-Output "Skill catalog updated successfully." - } - } else { - if ($DO_DEBUG) { - Write-Output "There was a problem updating the skill catalog." - } - exit 1 - } - if (update_skill_manifest) { - if ($DO_DEBUG) { - Write-Output "Skill manifest updated successfully." - } - } else { - if ($DO_DEBUG) { - Write-Output "There was a problem updating the skill manifest." - } - exit 1 - } - if ($DO_DEBUG) { - Write-Output "###########################" - } -} - -exit 0 diff --git a/hooks/pre_deploy_hook.sh b/hooks/pre_deploy_hook.sh deleted file mode 100755 index 306ea606..00000000 --- a/hooks/pre_deploy_hook.sh +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/bash -# Shell script for ask-cli pre-deploy hook for Node.js -# Script Usage: pre_deploy_hook.sh - -# SKILL_NAME is the preformatted name passed from the CLI, after removing special characters. -# DO_DEBUG is boolean value for debug logging -# TARGET is the deploy TARGET provided to the CLI. (eg: all, skill, lambda etc.) - -# Run this script under skill root folder - -# The script does the following: -# - Run "npm install" in each sourceDir in skill.json - -SKILL_NAME=$1 -DO_DEBUG=${2:-false} -TARGET=${3:-"all"} - -if [ $DO_DEBUG == false ] -then - exec > /dev/null 2>&1 -fi - -install_dependencies() { - npm install --production --prefix "$1" >/dev/null 2>&1 - return $? -} - -update_skill_catalog() { - node ./tools/updateSkillCatalog.js >/dev/null 2>&1 - return $? -} - -update_skill_manifest() { - node ./tools/updateSkillManifest.js >/dev/null 2>&1 - return $? -} - -echo "###########################" -echo "##### pre-deploy hook #####" -echo "###########################" - -if [ -f .env ]; then - set -o allexport - source .env - set +o allexport -fi - -if [[ $TARGET == "all" || $TARGET == "lambda" ]]; then - grep "sourceDir" ./skill.json | sed -E 's/.*:[[:space:]]*"([^"]+)".*/\1/g' | sort -u | while read -r SOURCE_DIR; do - if install_dependencies $SOURCE_DIR; then - echo "Codebase ($SOURCE_DIR) built successfully." - else - echo "There was a problem installing dependencies for ($SOURCE_DIR)." - exit 1 - fi - done - if update_skill_catalog; then - echo "Skill catalog updated successfully." - else - echo "There was a problem updating the skill catalog." - exit 1 - fi - if update_skill_manifest; then - echo "Skill manifest updated successfully." - else - echo "There was a problem updating the skill manifest." - exit 1 - fi - echo "###########################" -fi - -exit 0 diff --git a/infrastructure/cfn-deployer/skill-stack.yml b/infrastructure/cfn-deployer/skill-stack.yml new file mode 100644 index 00000000..c5033ee3 --- /dev/null +++ b/infrastructure/cfn-deployer/skill-stack.yml @@ -0,0 +1,98 @@ +AWSTemplateFormatVersion: 2010-09-09 +Parameters: + OpenHABBaseUrl: + Type: String + Default: '' + OpenHABUsername: + Type: String + Default: '' + OpenHABPassword: + Type: String + Default: '' + OpenHABCertFile: + Type: String + Default: '' + OpenHABCertPassphrase: + Type: String + Default: '' + SkillId: + Type: String + LambdaFunctionName: + Type: String + Default: alexa-openhab + LambdaLogLevel: + Type: String + Default: info + AllowedValues: [error, warn, info, debug] + LambdaRuntime: + Type: String + LambdaHandler: + Type: String + CodeBucket: + Type: String + CodeKey: + Type: String + CodeVersion: + Type: String +Resources: + AlexaSkillIAMRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: + - lambda.amazonaws.com + Action: + - sts:AssumeRole + Path: / + Policies: + - PolicyName: AlexaOpenHABSkillPolicy + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - logs:CreateLogStream + - logs:PutLogEvents + Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${LambdaFunctionName}:* + AlexaSkillFunction: + Type: AWS::Lambda::Function + Properties: + Code: + S3Bucket: !Ref CodeBucket + S3Key: !Ref CodeKey + S3ObjectVersion: !Ref CodeVersion + FunctionName: !Ref LambdaFunctionName + Description: openHAB Skill for Amazon Alexa + Handler: !Ref LambdaHandler + Runtime: !Ref LambdaRuntime + Role: !GetAtt AlexaSkillIAMRole.Arn + MemorySize: 128 + Timeout: 10 + Environment: + Variables: + LOG_LEVEL: !Ref LambdaLogLevel + OPENHAB_BASE_URL: !Ref OpenHABBaseUrl + OPENHAB_USERNAME: !Ref OpenHABUsername + OPENHAB_PASSWORD: !Ref OpenHABPassword + OPENHAB_CERT_FILE: !Ref OpenHABCertFile + OPENHAB_CERT_PASSPHRASE: !Ref OpenHABCertPassphrase + AlexaSkillFunctionEventPermission: + Type: AWS::Lambda::Permission + Properties: + Action: lambda:invokeFunction + FunctionName: !GetAtt AlexaSkillFunction.Arn + Principal: alexa-connectedhome.amazon.com + EventSourceToken: !Ref SkillId + AlexaSkillFunctionLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub /aws/lambda/${AlexaSkillFunction} + RetentionInDays: 30 +Outputs: + SkillEndpoint: + Description: LambdaARN for the regional endpoint + Value: !GetAtt AlexaSkillFunction.Arn diff --git a/lambda/.eslintrc.json b/lambda/.eslintrc.json new file mode 100644 index 00000000..c631ae9e --- /dev/null +++ b/lambda/.eslintrc.json @@ -0,0 +1,14 @@ +{ + "extends": [ + "eslint:recommended", + "plugin:node/recommended", + "plugin:prettier/recommended" + ], + "parserOptions": { + "ecmaVersion": 2022 + }, + "rules": { + "no-console": "warn", + "node/no-missing-require": "off" + } +} diff --git a/lambda/alexa/smarthome/capabilities/alexa.js b/lambda/alexa/smarthome/capabilities/alexa.js new file mode 100644 index 00000000..bf31ec64 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/alexa.js @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const { Interface } = require('../constants'); + +/** + * Defines Alexa interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-interface.html + * @extends AlexaCapability + */ +class Alexa extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA; + } +} + +module.exports = Alexa; diff --git a/lambda/alexa/smarthome/capabilities/brightnessController.js b/lambda/alexa/smarthome/capabilities/brightnessController.js new file mode 100644 index 00000000..630ae903 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/brightnessController.js @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { Brightness } = require('../properties'); + +/** + * Defines Alexa.BrightnessController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-brightnesscontroller.html + * @extends AlexaCapability + */ +class BrightnessController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_BRIGHTNESS_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.BRIGHTNESS]: Brightness + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.LIGHT]; + } +} + +module.exports = BrightnessController; diff --git a/lambda/alexa/smarthome/capabilities/cameraStreamController.js b/lambda/alexa/smarthome/capabilities/cameraStreamController.js new file mode 100644 index 00000000..7e33dcb1 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/cameraStreamController.js @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { CameraStream } = require('../properties'); + +/** + * Defines Alexa.CameraStreamController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-camerastreamcontroller.html + * @extends AlexaCapability + */ +class CameraStreamController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_CAMERA_STREAM_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.CAMERA_STREAM]: CameraStream + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.CAMERA]; + } + + /** + * Returns if supports endpoint health + * @return {Boolean} + */ + get supportsEndpointHealth() { + return true; + } + + /** + * Returns alexa interface + * @return {Object} + */ + getAlexaInterface() { + // Get capability interface from parent method + const capability = super.getAlexaInterface(); + const cameraStream = this.getProperty({ name: Property.CAMERA_STREAM }); + const { protocol, resolution, authorizationType, videoCodec, audioCodec } = cameraStream; + + // Add capability camera stream configurations + capability.cameraStreamConfigurations = [ + { + protocols: [protocol], + resolutions: [resolution], + authorizationTypes: [authorizationType], + videoCodecs: [videoCodec], + audioCodecs: [audioCodec] + } + ]; + + return capability; + } +} + +module.exports = CameraStreamController; diff --git a/lambda/alexa/smarthome/capabilities/capability.js b/lambda/alexa/smarthome/capabilities/capability.js new file mode 100644 index 00000000..485f1b03 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/capability.js @@ -0,0 +1,333 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const { DecoupleState } = require('../properties'); +const { AlexaCapabilityResources } = require('../resources'); + +/** + * Defines alexa base capability class + */ +class AlexaCapability { + /** + * Constructor + * @param {String} name + * @param {String} instance + */ + constructor(name, instance) { + this.name = name; + if (this.isMultiInstance) this.instance = instance; + this._properties = []; + } + + /** + * Returns interface + * @return {String} + */ + get interface() { + return undefined; + } + + /** + * Returns version + * @return {String} + */ + get version() { + return '3'; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return {}; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return []; + } + + /** + * Returns required linked capabilities + * @return {Array} + */ + get requiredLinkedCapabilities() { + return []; + } + + /** + * Returns if is multi-instance + * @return {Boolean} + */ + get isMultiInstance() { + return false; + } + + /** + * Returns if is discoverable + * @return {Boolean} + */ + get isDiscoverable() { + return true; + } + + /** + * Returns properties + * @return {Array} + */ + get properties() { + return this._properties + .filter((property) => property.isValid) + .filter((property, _, array) => property.hasRequiredLinkedProperties(array)); + } + + /** + * Returns if has configured properties + * @return {Boolean} + */ + get hasConfiguredProperties() { + return this.properties.length > 0; + } + + /** + * Returns if has supported properties + * @return {Boolean} + */ + get hasSupportedProperties() { + return Object.keys(this.supportedProperties).length > 0; + } + + /** + * Returns if has proactively reported properties + * @return {Boolean} + */ + get hasProactivelyReportedProperties() { + return this.properties.some((property) => property.isReportable && property.isProactivelyReported); + } + + /** + * Returns if has retrievable properties + * @return {Boolean} + */ + get hasRetrievableProperties() { + return this.properties.some((property) => property.isReportable && property.isRetrievable); + } + + /** + * Returns if has non-controlable properties + * @return {Boolean} + */ + get hasNonControllableProperties() { + return this.properties.every((property) => property.isReportable && property.isNonControllable); + } + + /** + * Returns if is valid + * @return {Boolean} + */ + get isValid() { + return !this.hasSupportedProperties || this.hasConfiguredProperties; + } + + /** + * Returns if supports endpoint health + * @return {Boolean} + */ + get supportsEndpointHealth() { + return this.hasRetrievableProperties; + } + + /** + * Returns if has required linked capabilities + * @param {Array} capabilities + * @return {Boolean} + */ + hasRequiredLinkedCapabilities(capabilities) { + return this.requiredLinkedCapabilities.every(({ name, instance }) => + capabilities.find((capability) => capability.name === name && capability.instance === instance) + ); + } + + /** + * Returns alexa interface + * @return {Object} + */ + getAlexaInterface() { + // Define capability properties + const properties = this.getCapabilityProperties(); + // Define capability resources + const capabilityResources = this.getCapabilityResources(); + // Define capability configuration + const configuration = this.getCapabilityConfiguration(); + // Define capability semantics + const semantics = this.getCapabilitySemantics(); + + return { + type: 'AlexaInterface', + interface: this.interface, + ...(this.instance && { instance: this.instance }), + version: this.version, + ...(properties.supported.length > 0 && { properties }), + ...(Object.keys(capabilityResources).length > 0 && { capabilityResources }), + ...(Object.keys(configuration).length > 0 && { configuration }), + ...(Object.keys(semantics).length > 0 && { semantics }) + }; + } + + /** + * Returns capability properties + * @return {Object} + */ + getCapabilityProperties() { + // Determine capability supported properties based on reportable and unique named properties + const supported = this.properties + .filter( + (property, index, array) => + property.isReportable && array.findIndex(({ name }) => name === property.name) === index + ) + .map((property) => ({ name: property.name })); + + // Return capability properties object including non-controllable property if instance defined + return { + supported, + proactivelyReported: this.hasProactivelyReportedProperties, + retrievable: this.hasRetrievableProperties, + ...(this.instance && { nonControllable: this.hasNonControllableProperties }) + }; + } + + /** + * Returns capability resources + * @return {Object} + */ + getCapabilityResources() { + // Determine capability resources labels and language + const { friendlyNames: labels, language } = + this.properties.find(({ friendlyNames, language }) => friendlyNames && language) || {}; + + // Return capability resources object based on labels and language + return { ...(labels && AlexaCapabilityResources.getResources(labels, language)) }; + } + + /** + * Returns capability configuration + * @return {Object} + */ + getCapabilityConfiguration() { + return {}; + } + + /** + * Returns capability semantics + * @return {Object} + */ + getCapabilitySemantics() { + return {}; + } + + /** + * Returns relationship + * @return {Object} + */ + getRelationship() { + return {}; + } + + /** + * Returns context properties + * @return {Array} + */ + getContextProperties() { + return this.properties.filter( + // Filter decouple state tagged property if defined, otherwise fallback to standard property + (property) => (this.getProperty({ ...property, tag: DecoupleState.TAG_NAME }) || property) === property + ); + } + + /** + * Returns reportable properties + * @return {Array} + */ + getReportableProperties() { + return this.getContextProperties().filter((property) => property.isReportable); + } + + /** + * Adds property for a given config object + * @param {Object} config [name, component, tag, parameters, item, metadata, settings] + */ + addProperty(config) { + const { name } = config; + // Add property if is supported + if (typeof this.supportedProperties[name] === 'function') { + const property = this.supportedProperties[name].build(config); + // Add property to list if defined and not already added + if (property && !this.hasProperty(property)) { + this._properties.push(property); + } + } + } + + /** + * Returns property for a given config object + * @param {String} name + * @param {String} component + * @param {String} tag + * @return {Object} + */ + getProperty({ name, component, tag }) { + return this.properties.find( + (property) => property.name === name && property.component === component && property.tag === tag + ); + } + + /** + * Returns property map + * @return {Object} + */ + getPropertyMap() { + return Object.fromEntries( + this.properties.map((property) => [ + property.name + (property.component ? `:${property.component}` : '') + (property.tag ? `#${property.tag}` : ''), + property + ]) + ); + } + + /** + * Returns if property defined for a given config object + * @param {Object} config [name, component, tag] + * @return {Boolean} + */ + hasProperty(config) { + return !!this.getProperty(config); + } + + /** + * Returns serialized capability object + * @return {Array} + */ + toJSON() { + return this.properties.map((property) => ({ + name: this.name, + ...(this.instance && { instance: this.instance }), + ...property.toJSON() + })); + } +} + +module.exports = AlexaCapability; diff --git a/lambda/alexa/smarthome/capabilities/channelController.js b/lambda/alexa/smarthome/capabilities/channelController.js new file mode 100644 index 00000000..18d9345e --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/channelController.js @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { Channel } = require('../properties'); + +/** + * Defines Alexa.ChannelController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-channelcontroller.html + * @extends AlexaCapability + */ +class ChannelController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_CHANNEL_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.CHANNEL]: Channel + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.TV]; + } +} + +module.exports = ChannelController; diff --git a/lambda/alexa/smarthome/capabilities/colorController.js b/lambda/alexa/smarthome/capabilities/colorController.js new file mode 100644 index 00000000..65aa3116 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/colorController.js @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { Color } = require('../properties'); + +/** + * Defines Alexa.ColorController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-colorcontroller.html + * @extends AlexaCapability + */ +class ColorController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_COLOR_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.COLOR]: Color + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.LIGHT]; + } + + /** + * Returns reportable properties + * @param {Array} items + * @param {Object} properties + * @return {Array} + */ + getReportableProperties(items, properties) { + const color = properties[Property.COLOR]; + const temperature = properties[Property.COLOR_TEMPERATURE]; + + if (color && temperature) { + const colorItem = items.find((item) => item.name === color.item.name) || {}; + const temperatureItem = items.find((item) => item.name === temperature.item.name) || {}; + + // Exclude color property if not in color mode + if (!temperature.isInColorMode(colorItem.state, temperatureItem.state)) { + return this.properties.filter((property) => !(property instanceof Color)); + } + } + + // Return reportable properties from parent method otherwise + return super.getReportableProperties(items, properties); + } +} + +module.exports = ColorController; diff --git a/lambda/alexa/smarthome/capabilities/colorTemperatureController.js b/lambda/alexa/smarthome/capabilities/colorTemperatureController.js new file mode 100644 index 00000000..f79611a3 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/colorTemperatureController.js @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { ColorTemperature } = require('../properties'); + +/** + * Defines Alexa.ColorTemperatureController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-colortemperaturecontroller.html + * @extends AlexaCapability + */ +class ColorTemperatureController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_COLOR_TEMPERATURE_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.COLOR_TEMPERATURE]: ColorTemperature + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.LIGHT]; + } + + /** + * Returns reportable properties + * @param {Array} items + * @param {Object} properties + * @return {Array} + */ + getReportableProperties(items, properties) { + const color = properties[Property.COLOR]; + const temperature = properties[Property.COLOR_TEMPERATURE]; + + if (color && temperature) { + const colorItem = items.find((item) => item.name === color.item.name) || {}; + const temperatureItem = items.find((item) => item.name === temperature.item.name) || {}; + + // Exclude color temperature property if in color mode + if (temperature.isInColorMode(colorItem.state, temperatureItem.state)) { + temperatureItem.state = 0; // Set temperature item state to zero to exclude item from health check + return this.properties.filter((property) => !(property instanceof ColorTemperature)); + } + } + + // Return reportable properties from parent method otherwise + return super.getReportableProperties(items, properties); + } +} + +module.exports = ColorTemperatureController; diff --git a/lambda/alexa/smarthome/capabilities/contactSensor.js b/lambda/alexa/smarthome/capabilities/contactSensor.js new file mode 100644 index 00000000..38c82c41 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/contactSensor.js @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { DetectionState } = require('../properties'); + +/** + * Defines Alexa.ContactSensor interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-contactsensor.html + * @extends AlexaCapability + */ +class ContactSensor extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_CONTACT_SENSOR; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.DETECTION_STATE]: DetectionState + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.CONTACT_SENSOR]; + } +} + +module.exports = ContactSensor; diff --git a/lambda/alexa/smarthome/capabilities/endpointHealth.js b/lambda/alexa/smarthome/capabilities/endpointHealth.js new file mode 100644 index 00000000..661d1e32 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/endpointHealth.js @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const { Interface, Property } = require('../constants'); +const { Connectivity } = require('../properties'); + +/** + * Defines Alexa.EndpointHealth interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-endpointhealth.html + * @extends AlexaCapability + */ +class EndpointHealth extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_ENDPOINT_HEALTH; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.CONNECTIVITY]: Connectivity + }; + } +} + +module.exports = EndpointHealth; diff --git a/lambda/alexa/smarthome/capabilities/equalizerController.js b/lambda/alexa/smarthome/capabilities/equalizerController.js new file mode 100644 index 00000000..8f9dab30 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/equalizerController.js @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { EqualizerBands, EqualizerMode } = require('../properties'); + +/** + * Defines Alexa.EqualizerController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-equalizercontroller.html + * @extends AlexaCapability + */ +class EqualizerController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_EQUALIZER_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.EQUALIZER_BANDS]: EqualizerBands, + [Property.EQUALIZER_MODE]: EqualizerMode + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.SPEAKER]; + } + + /** + * Returns alexa interface + * @return {Object} + */ + getAlexaInterface() { + // Get capability interface from parent method + const capability = super.getAlexaInterface(); + + // Initialize capability configurations object + capability.configurations = {}; + + // Iterate over properties + for (const property of this.properties) { + const { component, range, supportedModes } = property; + + if (property instanceof EqualizerBands) { + capability.configurations.bands = capability.configurations.bands || { supported: [] }; + capability.configurations.bands.supported.push({ name: component.toUpperCase() }); + capability.configurations.bands.range = { minimum: range[0], maximum: range[1] }; + } else { + capability.configurations.modes = { supported: supportedModes.map((mode) => ({ name: mode })) }; + } + } + + return capability; + } +} + +module.exports = EqualizerController; diff --git a/lambda/alexa/smarthome/capabilities/index.js b/lambda/alexa/smarthome/capabilities/index.js new file mode 100644 index 00000000..c12dc9cb --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/index.js @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const { Capability } = require('../constants'); + +/** + * Defines supported capability classes + * @type {Object} + */ +module.exports = { + [Capability.ALEXA]: require('./alexa'), + [Capability.BRIGHTNESS_CONTROLLER]: require('./brightnessController'), + [Capability.CAMERA_STREAM_CONTROLLER]: require('./cameraStreamController'), + [Capability.CHANNEL_CONTROLLER]: require('./channelController'), + [Capability.COLOR_CONTROLLER]: require('./colorController'), + [Capability.COLOR_TEMPERATURE_CONTROLLER]: require('./colorTemperatureController'), + [Capability.CONTACT_SENSOR]: require('./contactSensor'), + [Capability.ENDPOINT_HEALTH]: require('./endpointHealth'), + [Capability.EQUALIZER_CONTROLLER]: require('./equalizerController'), + [Capability.INPUT_CONTROLLER]: require('./inputController'), + [Capability.KEYPAD_CONTROLLER]: require('./keypadController'), + [Capability.LOCK_CONTROLLER]: require('./lockController'), + [Capability.MODE_CONTROLLER]: require('./modeController'), + [Capability.MOTION_SENSOR]: require('./motionSensor'), + [Capability.NETWORKING_ACCESS_CONTROLLER]: require('./networkingAccessController'), + [Capability.NETWORKING_CONNECTED_DEVICE]: require('./networkingConnectedDevice'), + [Capability.NETWORKING_HOME_NETWORK_CONTROLLER]: require('./networkingHomeNetworkController'), + [Capability.PERCENTAGE_CONTROLLER]: require('./percentageController'), + [Capability.PLAYBACK_CONTROLLER]: require('./playbackController'), + [Capability.POWER_CONTROLLER]: require('./powerController'), + [Capability.POWER_LEVEL_CONTROLLER]: require('./powerLevelController'), + [Capability.RANGE_CONTROLLER]: require('./rangeController'), + [Capability.SAFETY]: require('./safety'), + [Capability.SCENE_CONTROLLER]: require('./sceneController'), + [Capability.SECURITY_PANEL_CONTROLLER]: require('./securityPanelController'), + [Capability.SPEAKER]: require('./speaker'), + [Capability.STEP_SPEAKER]: require('./stepSpeaker'), + [Capability.TEMPERATURE_SENSOR]: require('./temperatureSensor'), + [Capability.THERMOSTAT_CONTROLLER]: require('./thermostatController'), + [Capability.TOGGLE_CONTROLLER]: require('./toggleController') +}; + +/** + * Returns new capability object for a given name and instance + * @param {String} name + * @param {String} instance + * @return {Object} + */ +module.exports.build = function (name, instance) { + if (typeof this[name] === 'function') { + return new this[name](name, instance); + } +}; diff --git a/lambda/alexa/smarthome/capabilities/inputController.js b/lambda/alexa/smarthome/capabilities/inputController.js new file mode 100644 index 00000000..e9fae8c4 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/inputController.js @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { Input } = require('../properties'); + +/** + * Defines Alexa.InputController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-inputcontroller.html + * @extends AlexaCapability + */ +class InputController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_INPUT_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.INPUT]: Input + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.TV]; + } + + /** + * Returns alexa interface + * @return {Object} + */ + getAlexaInterface() { + // Get capability interface from parent method + const capability = super.getAlexaInterface(); + const { supportedInputs } = this.getProperty({ name: Property.INPUT }); + + capability.inputs = supportedInputs.map((input) => ({ name: input })); + + return capability; + } +} + +module.exports = InputController; diff --git a/lambda/alexa/smarthome/capabilities/keypadController.js b/lambda/alexa/smarthome/capabilities/keypadController.js new file mode 100644 index 00000000..4d90eed8 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/keypadController.js @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { Keystroke } = require('../properties'); + +/** + * Defines Alexa.KeypadController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-keypadcontroller.html + * @extends AlexaCapability + */ +class KeypadController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_KEYPAD_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.KEYSTROKE]: Keystroke + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.STREAMING_DEVICE]; + } + + /** + * Returns alexa interface + * @return {Object} + */ + getAlexaInterface() { + // Get capability interface from parent method + const capability = super.getAlexaInterface(); + const { supportedKeys } = this.getProperty({ name: Property.KEYSTROKE }); + + capability.keys = supportedKeys; + + return capability; + } +} + +module.exports = KeypadController; diff --git a/lambda/alexa/smarthome/capabilities/lockController.js b/lambda/alexa/smarthome/capabilities/lockController.js new file mode 100644 index 00000000..b9a86e41 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/lockController.js @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { LockState } = require('../properties'); + +/** + * Defines Alexa.LockController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-lockcontroller.html + * @extends AlexaCapability + */ +class LockController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_LOCK_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.LOCK_STATE]: LockState + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.SMARTLOCK]; + } +} + +module.exports = LockController; diff --git a/lambda/alexa/smarthome/capabilities/modeController.js b/lambda/alexa/smarthome/capabilities/modeController.js new file mode 100644 index 00000000..e4b40839 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/modeController.js @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const ModeControllerHandler = require('../handlers/modeController'); +const { Mode } = require('../properties'); +const { AlexaModeResources } = require('../resources'); +const AlexaSemantics = require('../semantics'); + +/** + * Defines Alexa.ModeController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-modecontroller.html + * @extends AlexaCapability + */ +class ModeController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_MODE_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.MODE]: Mode + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.OTHER]; + } + + /** + * Returns if is multi-instance + * @return {Boolean} + */ + get isMultiInstance() { + return true; + } + + /** + * Returns capability configuration + * @return {Object} + */ + getCapabilityConfiguration() { + const configuration = {}; + const { supportedModes, ordered, language } = this.getProperty({ name: Property.MODE }); + + configuration.ordered = ordered; + configuration.supportedModes = Object.entries(supportedModes).map(([mode, labels]) => ({ + value: mode, + modeResources: AlexaModeResources.getResources(labels, language) + })); + + return configuration; + } + + /** + * Returns capability semantics + * @return {Object} + */ + getCapabilitySemantics() { + const semantics = new AlexaSemantics(); + const { actionMappings, stateMappings, supportedModes, ordered } = this.getProperty({ name: Property.MODE }); + + // Iterate over action mappings + for (const [name, value] of Object.entries(actionMappings)) { + if (/^\(.+\)$/.test(value)) { + // Define ajust mode directive + const directive = { + name: ModeControllerHandler.ADJUST_MODE, + payload: { modeDelta: parseInt(value.slice(1, -1)) } + }; + // Add action mapping object if mode delta numerical and ordered property active + if (!isNaN(directive.payload.modeDelta) && ordered) { + semantics.addActionToDirective(name, directive); + } + } else { + // Define set mode directive + const directive = { + name: ModeControllerHandler.SET_MODE, + payload: { mode: value } + }; + // Add action mapping object if mode value supported + if (supportedModes[value]) { + semantics.addActionToDirective(name, directive); + } + } + } + + // Iterate over state mappings + for (const [name, value] of Object.entries(stateMappings)) { + // Add state mapping object if mode value supported + if (supportedModes[value]) { + semantics.addStateToValue(name, value); + } + } + + return semantics.toJSON(); + } +} + +module.exports = ModeController; diff --git a/lambda/alexa/smarthome/capabilities/motionSensor.js b/lambda/alexa/smarthome/capabilities/motionSensor.js new file mode 100644 index 00000000..ed678e18 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/motionSensor.js @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { DetectionState } = require('../properties'); + +/** + * Defines Alexa.MotionSensor interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-motionsensor.html + * @extends AlexaCapability + */ +class MotionSensor extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_MOTION_SENSOR; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.DETECTION_STATE]: DetectionState + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.MOTION_SENSOR]; + } +} + +module.exports = MotionSensor; diff --git a/lambda/alexa/smarthome/capabilities/networkingAccessController.js b/lambda/alexa/smarthome/capabilities/networkingAccessController.js new file mode 100644 index 00000000..bfb0fbe2 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/networkingAccessController.js @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const { Capability, Interface, Property } = require('../constants'); +const { NetworkAccess } = require('../properties'); + +/** + * Defines Alexa.Networking.AccessController interface capability class + * https://developer.amazon.com/docs/networking/alexa-networking-accesscontroller.html + * @extends AlexaCapability + */ +class NetworkingAccessController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_NETWORKING_ACCESS_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.NETWORK_ACCESS]: NetworkAccess + }; + } + + /** + * Returns required linked capabilities + * @return {Array} + */ + get requiredLinkedCapabilities() { + return [{ name: Capability.NETWORKING_CONNECTED_DEVICE, property: Property.CONNECTED_DEVICE }]; + } + + /** + * Returns capability configuration + * @return {Object} + */ + getCapabilityConfiguration() { + return { supportsScheduling: false }; + } +} + +module.exports = NetworkingAccessController; diff --git a/lambda/alexa/smarthome/capabilities/networkingConnectedDevice.js b/lambda/alexa/smarthome/capabilities/networkingConnectedDevice.js new file mode 100644 index 00000000..78269dc2 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/networkingConnectedDevice.js @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const { Interface, Property } = require('../constants'); +const { ConnectedDevice } = require('../properties'); + +/** + * Defines Alexa.Networking.ConnectedDevice interface capability class + * https://developer.amazon.com/docs/networking/alexa-networking-connecteddevice.html + * @extends AlexaCapability + */ +class NetworkingConnectedDevice extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_NETWORKING_CONNECTED_DEVICE; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.CONNECTED_DEVICE]: ConnectedDevice + }; + } + + /** + * Returns capability configuration + * @return {Object} + */ + getCapabilityConfiguration() { + const configuration = {}; + const { deviceName, hostname, macAddress } = this.getProperty({ name: Property.CONNECTED_DEVICE }); + + configuration.staticDeviceInformation = { deviceName, hostname, macAddress }; + + return configuration; + } + + /** + * Returns relationship + * @return {Object} + */ + getRelationship() { + const relationship = {}; + const { connectedTo: endpointId } = this.getProperty({ name: Property.CONNECTED_DEVICE }); + + relationship.isConnectedBy = { endpointId }; + + return relationship; + } +} + +module.exports = NetworkingConnectedDevice; diff --git a/lambda/alexa/smarthome/capabilities/networkingHomeNetworkController.js b/lambda/alexa/smarthome/capabilities/networkingHomeNetworkController.js new file mode 100644 index 00000000..208281d6 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/networkingHomeNetworkController.js @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const { Interface } = require('../constants'); + +/** + * Defines Alexa.Networking.HomeNetworkController interface capability class + * https://developer.amazon.com/docs/networking/alexa-networking-homenetworkcontroller.html + * @extends AlexaCapability + */ +class NetworkingHomeNetworkController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_NETWORKING_HOME_NETWORK_CONTROLLER; + } +} + +module.exports = NetworkingHomeNetworkController; diff --git a/lambda/alexa/smarthome/capabilities/percentageController.js b/lambda/alexa/smarthome/capabilities/percentageController.js new file mode 100644 index 00000000..e46672b5 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/percentageController.js @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { Percentage } = require('../properties'); + +/** + * Defines Alexa.PercentageController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-percentagecontroller.html + * @extends AlexaCapability + */ +class PercentageController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_PERCENTAGE_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.PERCENTAGE]: Percentage + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.OTHER]; + } +} + +module.exports = PercentageController; diff --git a/lambda/alexa/smarthome/capabilities/playbackController.js b/lambda/alexa/smarthome/capabilities/playbackController.js new file mode 100644 index 00000000..5dbc0f70 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/playbackController.js @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { Playback, PlaybackStop, PlaybackAction } = require('../properties'); + +/** + * Defines Alexa.PlaybackController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-playbackcontroller.html + * @extends AlexaCapability + */ +class PlaybackController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_PLAYBACK_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.PLAYBACK]: Playback, + [Property.PLAYBACK_STOP]: PlaybackStop, + [Property.PLAYBACK_ACTION]: PlaybackAction + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return this.hasProperty({ name: Property.PLAYBACK_ACTION }) + ? [AlexaDisplayCategory.OTHER] + : [AlexaDisplayCategory.STREAMING_DEVICE]; + } + + /** + * Returns alexa interface + * @return {Object} + */ + getAlexaInterface() { + // Get capability interface from parent method + const capability = super.getAlexaInterface(); + + // Initialize capability supported operations array + capability.supportedOperations = []; + + // Iterate over property supported operations + for (const { supportedOperations } of this.properties) { + for (const operation of supportedOperations) { + if (!capability.supportedOperations.includes(operation)) { + capability.supportedOperations.push(operation); + } + } + } + + return capability; + } +} + +module.exports = PlaybackController; diff --git a/lambda/alexa/smarthome/capabilities/powerController.js b/lambda/alexa/smarthome/capabilities/powerController.js new file mode 100644 index 00000000..2279b919 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/powerController.js @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { PowerState } = require('../properties'); + +/** + * Defines Alexa.PowerController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-powercontroller.html + * @extends AlexaCapability + */ +class PowerController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_POWER_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.POWER_STATE]: PowerState + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.SWITCH]; + } +} + +module.exports = PowerController; diff --git a/lambda/alexa/smarthome/capabilities/powerLevelController.js b/lambda/alexa/smarthome/capabilities/powerLevelController.js new file mode 100644 index 00000000..31309600 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/powerLevelController.js @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { PowerLevel } = require('../properties'); + +/** + * Defines Alexa.PowerLevelController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-powerlevelcontroller.html + * @extends AlexaCapability + */ +class PowerLevelController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_POWER_LEVEL_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.POWER_LEVEL]: PowerLevel + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.SWITCH]; + } +} + +module.exports = PowerLevelController; diff --git a/lambda/alexa/smarthome/capabilities/rangeController.js b/lambda/alexa/smarthome/capabilities/rangeController.js new file mode 100644 index 00000000..671fe73c --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/rangeController.js @@ -0,0 +1,140 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const RangeControllerHandler = require('../handlers/rangeController'); +const { RangeValue } = require('../properties'); +const { AlexaPresetResources } = require('../resources'); +const AlexaSemantics = require('../semantics'); + +/** + * Defines Alexa.RangeController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-rangecontroller.html + * @extends AlexaCapability + */ +class RangeController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_RANGE_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.RANGE_VALUE]: RangeValue + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.OTHER]; + } + + /** + * Returns if is multi-instance + * @return {Boolean} + */ + get isMultiInstance() { + return true; + } + + /** + * Returns capability configuration + * @return {Object} + */ + getCapabilityConfiguration() { + const configuration = {}; + const { supportedRange, presets, unitOfMeasure, language } = this.getProperty({ name: Property.RANGE_VALUE }); + + configuration.supportedRange = { + minimumValue: supportedRange[0], + maximumValue: supportedRange[1], + precision: Math.abs(supportedRange[2]) + }; + + if (unitOfMeasure) { + configuration.unitOfMeasure = 'Alexa.Unit.' + unitOfMeasure; + } + + if (presets) { + configuration.presets = Object.entries(presets).map(([preset, labels]) => ({ + rangeValue: parseFloat(preset), + presetResources: AlexaPresetResources.getResources(labels, language) + })); + } + + return configuration; + } + + /** + * Returns capability semantics + * @return {Object} + */ + getCapabilitySemantics() { + const semantics = new AlexaSemantics(); + const { actionMappings, stateMappings, supportedRange } = this.getProperty({ name: Property.RANGE_VALUE }); + + // Iterate over action mappings + for (const [name, value] of Object.entries(actionMappings)) { + if (/^\(.+\)$/.test(value)) { + // Define ajust range directive + const directive = { + name: RangeControllerHandler.ADJUST_RANGE_VALUE, + payload: { rangeValueDelta: parseFloat(value.slice(1, -1)), rangeValueDeltaDefault: false } + }; + // Add action mapping object if absolute range delta < max range + if (Math.abs(directive.payload.rangeValueDelta) < supportedRange[1] - supportedRange[0]) { + semantics.addActionToDirective(name, directive); + } + } else { + // Define set range directive + const directive = { + name: RangeControllerHandler.SET_RANGE_VALUE, + payload: { rangeValue: parseFloat(value) } + }; + // Add action mapping object if range value valid + if (value >= supportedRange[0] && value <= supportedRange[1]) { + semantics.addActionToDirective(name, directive); + } + } + } + + // Iterate over state mappings + for (const [name, value] of Object.entries(stateMappings)) { + const values = value && value.split(':', 2); + // Add state mapping object if value(s) valid + if (values && values.every((value) => value >= supportedRange[0] && value <= supportedRange[1])) { + if (values.length === 2) { + semantics.addStateToRange(name, { minimumValue: parseFloat(values[0]), maximumValue: parseFloat(values[1]) }); + } else { + semantics.addStateToValue(name, parseFloat(values[0])); + } + } + } + + return semantics.toJSON(); + } +} + +module.exports = RangeController; diff --git a/lambda/alexa/smarthome/capabilities/safety.js b/lambda/alexa/smarthome/capabilities/safety.js new file mode 100644 index 00000000..bf23bbc0 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/safety.js @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const { Capability, Interface, Property } = require('../constants'); +const { OpenState } = require('../device/attributes'); +const { AlertState } = require('../properties'); + +/** + * Defines Alexa.Safety interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-safety-errorresponse.html + * @extends AlexaCapability + */ +class Safety extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_SAFETY; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.OBSTACLE_ALERT]: AlertState, + [Property.SAFETY_BEAM_ALERT]: AlertState + }; + } + + /** + * Returns required linked capabilities + * @return {Array} + */ + get requiredLinkedCapabilities() { + // Requires open state attribute mode controller capability to be linked + return [{ name: Capability.MODE_CONTROLLER, instance: OpenState.name }]; + } + + /** + * Returns if is discoverable + * @return {Boolean} + */ + get isDiscoverable() { + return false; + } +} + +module.exports = Safety; diff --git a/lambda/alexa/smarthome/capabilities/sceneController.js b/lambda/alexa/smarthome/capabilities/sceneController.js new file mode 100644 index 00000000..ebf7d540 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/sceneController.js @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { Scene } = require('../properties'); + +/** + * Defines Alexa.SceneController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-scenecontroller.html + * @extends AlexaCapability + */ +class SceneController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_SCENE_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.SCENE]: Scene + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.SCENE_TRIGGER]; + } + + /** + * Returns alexa interface + * @return {Object} + */ + getAlexaInterface() { + // Get capability interface from parent method + const capability = super.getAlexaInterface(); + const { supportsDeactivation } = this.getProperty({ name: Property.SCENE }); + + capability.supportsDeactivation = supportsDeactivation; + + return capability; + } +} + +module.exports = SceneController; diff --git a/lambda/alexa/smarthome/capabilities/securityPanelController.js b/lambda/alexa/smarthome/capabilities/securityPanelController.js new file mode 100644 index 00000000..b6247bfe --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/securityPanelController.js @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { ArmState, AlarmState, SecurityAlert } = require('../properties'); + +/** + * Defines Alexa.SecurityPanelController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-securitypanelcontroller.html + * @extends AlexaCapability + */ +class SecurityPanelController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_SECURITY_PANEL_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.ARM_STATE]: ArmState, + [Property.BURGLARY_ALARM]: AlarmState, + [Property.CARBON_MONOXIDE_ALARM]: AlarmState, + [Property.FIRE_ALARM]: AlarmState, + [Property.WATER_ALARM]: AlarmState, + [Property.ALARM_ALERT]: SecurityAlert, + [Property.READY_ALERT]: SecurityAlert, + [Property.TROUBLE_ALERT]: SecurityAlert, + [Property.ZONES_ALERT]: SecurityAlert + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.SECURITY_PANEL]; + } + + /** + * Returns capability configuration + * @return {Object} + */ + getCapabilityConfiguration() { + const configuration = {}; + const armState = this.getProperty({ name: Property.ARM_STATE }); + + if (armState) { + const { supportedArmStates, pinCodes } = armState; + + configuration.supportedArmStates = supportedArmStates.map((state) => ({ value: state })); + + if (pinCodes.length > 0) { + configuration.supportedAuthorizationTypes = [{ type: ArmState.AuthType.FOUR_DIGIT_PIN }]; + } + } + + return configuration; + } +} + +module.exports = SecurityPanelController; diff --git a/lambda/alexa/smarthome/capabilities/speaker.js b/lambda/alexa/smarthome/capabilities/speaker.js new file mode 100644 index 00000000..51ff7a7e --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/speaker.js @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { MuteState, VolumeLevel } = require('../properties'); + +/** + * Defines Alexa.Speaker interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-speaker.html + * @extends AlexaCapability + */ +class Speaker extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_SPEAKER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.MUTED]: MuteState, + [Property.VOLUME]: VolumeLevel + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.SPEAKER]; + } +} + +module.exports = Speaker; diff --git a/lambda/alexa/smarthome/capabilities/stepSpeaker.js b/lambda/alexa/smarthome/capabilities/stepSpeaker.js new file mode 100644 index 00000000..2b79f58d --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/stepSpeaker.js @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { MuteStep, VolumeSteps } = require('../properties'); + +/** + * Defines Alexa.StepSpeaker interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-stepspeaker.html + * @extends AlexaCapability + */ +class StepSpeaker extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_STEP_SPEAKER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.MUTED]: MuteStep, + [Property.VOLUME]: VolumeSteps + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.SPEAKER]; + } +} + +module.exports = StepSpeaker; diff --git a/lambda/alexa/smarthome/capabilities/temperatureSensor.js b/lambda/alexa/smarthome/capabilities/temperatureSensor.js new file mode 100644 index 00000000..4cccab5a --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/temperatureSensor.js @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { Temperature } = require('../properties'); + +/** + * Defines Alexa.TemperatureSensor interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-temperaturesensor.html + * @extends AlexaCapability + */ +class TemperatureSensor extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_TEMPERATURE_SENSOR; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.TEMPERATURE]: Temperature + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.TEMPERATURE_SENSOR]; + } +} + +module.exports = TemperatureSensor; diff --git a/lambda/alexa/smarthome/capabilities/thermostatController.js b/lambda/alexa/smarthome/capabilities/thermostatController.js new file mode 100644 index 00000000..e3ea3e58 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/thermostatController.js @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const { TargetSetpoint, UpperSetpoint, LowerSetpoint, ThermostatMode, ThermostatHold } = require('../properties'); + +/** + * Defines Alexa.ThermostatController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-thermostatcontroller.html + * @extends AlexaCapability + */ +class ThermostatController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_THERMOSTAT_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.TARGET_SETPOINT]: TargetSetpoint, + [Property.UPPER_SETPOINT]: UpperSetpoint, + [Property.LOWER_SETPOINT]: LowerSetpoint, + [Property.THERMOSTAT_MODE]: ThermostatMode, + [Property.THERMOSTAT_HOLD]: ThermostatHold + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.THERMOSTAT]; + } + + /** + * Returns capability configuration + * @return {Object} + */ + getCapabilityConfiguration() { + const configuration = {}; + const thermostatMode = this.getProperty({ name: Property.THERMOSTAT_MODE }); + + if (thermostatMode) { + configuration.supportedModes = thermostatMode.supportedModes; + configuration.supportsScheduling = this.hasProperty({ name: Property.THERMOSTAT_HOLD }); + } + + return configuration; + } + + /** + * Returns reportable properties + * @param {Array} items + * @param {Object} properties + * @return {Array} + */ + getReportableProperties(items, properties) { + const thermostatMode = properties[Property.THERMOSTAT_MODE]; + + if (thermostatMode) { + const item = items.find((item) => item.name === thermostatMode.item.name) || {}; + const mode = thermostatMode.getState(item.state); + const setpointProperties = this.getSetpointProperties(mode, properties); + // Return thermostat mode and relevant setpoint properties + return [thermostatMode, ...Object.values(setpointProperties)]; + } + + // Return reportable properties from parent method otherwise + return super.getReportableProperties(items, properties); + } + + /** + * Returns setpoint properties for a given thermostat mode + * @param {String} thermostatMode + * @param {Object} properties + * @return {Object} + */ + getSetpointProperties(thermostatMode, properties) { + const targetSetpoint = properties[Property.TARGET_SETPOINT]; + const upperSetpoint = properties[Property.UPPER_SETPOINT]; + const lowerSetpoint = properties[Property.LOWER_SETPOINT]; + + if (thermostatMode === ThermostatMode.AUTO || thermostatMode === ThermostatMode.ECO) { + const taggedProperties = Object.values(properties).filter( + (property) => + (property instanceof UpperSetpoint || property instanceof LowerSetpoint) && + property.tag === thermostatMode.toLowerCase() + ); + // Use tagged properties setpoints if defined, fallback to upper/lower setpoints if defined + if (taggedProperties.length === 2) { + return Object.fromEntries(taggedProperties.map((property) => [property.name, property])); + } else if (upperSetpoint && lowerSetpoint) { + return { upperSetpoint, lowerSetpoint }; + } + } else if (thermostatMode === ThermostatMode.COOL) { + // Use target setpoint if defined, fallback to upper setpoint mapped as target setpoint if defined + if (targetSetpoint) { + return { targetSetpoint }; + } else if (upperSetpoint) { + upperSetpoint.reportName = Property.TARGET_SETPOINT; + return { targetSetpoint: upperSetpoint }; + } + } else if (thermostatMode === ThermostatMode.HEAT) { + // Use target setpoint if defined, fallback to lower setpoint mapped as target setpoint if defined + if (targetSetpoint) { + return { targetSetpoint }; + } else if (lowerSetpoint) { + lowerSetpoint.reportName = Property.TARGET_SETPOINT; + return { targetSetpoint: lowerSetpoint }; + } + } else if (thermostatMode === ThermostatMode.OFF) { + // No setpoint + return {}; + } + + // Return standard defined setpoint properties as fallback + return { + ...(targetSetpoint && { targetSetpoint }), + ...(upperSetpoint && { upperSetpoint }), + ...(lowerSetpoint && { lowerSetpoint }) + }; + } +} + +module.exports = ThermostatController; diff --git a/lambda/alexa/smarthome/capabilities/toggleController.js b/lambda/alexa/smarthome/capabilities/toggleController.js new file mode 100644 index 00000000..b2295527 --- /dev/null +++ b/lambda/alexa/smarthome/capabilities/toggleController.js @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +const { ItemValue } = require('@openhab/constants'); +const AlexaCapability = require('./capability'); +const AlexaDisplayCategory = require('../category'); +const { Interface, Property } = require('../constants'); +const ToggleControllerHandler = require('../handlers/toggleController'); +const { ToggleState } = require('../properties'); +const AlexaSemantics = require('../semantics'); + +/** + * Defines Alexa.ToggleController interface capability class + * https://developer.amazon.com/docs/device-apis/alexa-togglecontroller.html + * @extends AlexaCapability + */ +class ToggleController extends AlexaCapability { + /** + * Returns interface + * @return {String} + */ + get interface() { + return Interface.ALEXA_TOGGLE_CONTROLLER; + } + + /** + * Returns supported properties + * @return {Object} + */ + get supportedProperties() { + return { + [Property.TOGGLE_STATE]: ToggleState + }; + } + + /** + * Returns default display categories + * @return {Array} + */ + get defaultDisplayCategories() { + return [AlexaDisplayCategory.OTHER]; + } + + /** + * Returns if is multi-instance + * @return {Boolean} + */ + get isMultiInstance() { + return true; + } + + /** + * Returns capability semantics + * @return {Object} + */ + getCapabilitySemantics() { + const semantics = new AlexaSemantics(); + const { actionMappings, stateMappings } = this.getProperty({ name: Property.TOGGLE_STATE }); + + // Iterate over action mappings + for (const [name, value] of Object.entries(actionMappings)) { + // Add action mapping object if toggle value valid + if (value === ItemValue.ON || value === ItemValue.OFF) { + semantics.addActionToDirective(name, { + name: value === ItemValue.ON ? ToggleControllerHandler.TURN_ON : ToggleControllerHandler.TURN_OFF, + payload: {} + }); + } + } + + // Iterate over state mappings + for (const [name, value] of Object.entries(stateMappings)) { + // Add state mapping object if toggle value valid + if (value === ItemValue.ON || value === ItemValue.OFF) { + semantics.addStateToValue(name, value); + } + } + + return semantics.toJSON(); + } +} + +module.exports = ToggleController; diff --git a/lambda/alexa/smarthome/catalog.js b/lambda/alexa/smarthome/catalog.js new file mode 100644 index 00000000..223be09f --- /dev/null +++ b/lambda/alexa/smarthome/catalog.js @@ -0,0 +1,466 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +/** + * Defines alexa global catalog class + * https://developer.amazon.com/docs/device-apis/resources-and-assets.html#global-alexa-catalog + */ +class AlexaGlobalCatalog { + /** + * Defines device name air purifier asset + * @type {String} + */ + static DEVICE_NAME_AIR_PURIFIER = '@DeviceName.AirPurifier'; + + /** + * Defines device name camera asset + * @type {String} + */ + static DEVICE_NAME_CAMERA = '@DeviceName.Camera'; + + /** + * Defines device name fan asset + * @type {String} + */ + static DEVICE_NAME_FAN = '@DeviceName.Fan'; + + /** + * Defines device name router asset + * @type {String} + */ + static DEVICE_NAME_ROUTER = '@DeviceName.Router'; + + /** + * Defines device name shade asset + * @type {String} + */ + static DEVICE_NAME_SHADE = '@DeviceName.Shade'; + + /** + * Defines device name shower asset + * @type {String} + */ + static DEVICE_NAME_SHOWER = '@DeviceName.Shower'; + + /** + * Defines device name space heater asset + * @type {String} + */ + static DEVICE_NAME_SPACE_HEATER = '@DeviceName.SpaceHeater'; + + /** + * Defines device name washer asset + * @type {String} + */ + static DEVICE_NAME_WASHER = '@DeviceName.Washer'; + + /** + * Defines setting 2g guest wifi asset + * @type {String} + */ + static SETTING_2G_GUEST_WIFI = '@Setting.2GGuestWiFi'; + + /** + * Defines setting 5g guest wifi asset + * @type {String} + */ + static SETTING_5G_GUEST_WIFI = '@Setting.5GGuestWiFi'; + + /** + * Defines setting auto asset + * @type {String} + */ + static SETTING_AUTO = '@Setting.Auto'; + + /** + * Defines setting direction asset + * @type {String} + */ + static SETTING_DIRECTION = '@Setting.Direction'; + + /** + * Defines setting dry cycle asset + * @type {String} + */ + static SETTING_DRY_CYCLE = '@Setting.DryCycle'; + + /** + * Defines setting fan speed asset + * @type {String} + */ + static SETTING_FAN_SPEED = '@Setting.FanSpeed'; + + /** + * Defines setting guest wifi asset + * @type {String} + */ + static SETTING_GUEST_WIFI = '@Setting.GuestWiFi'; + + /** + * Defines setting heat asset + * @type {String} + */ + static SETTING_HEAT = '@Setting.Heat'; + + /** + * Defines setting mode asset + * @type {String} + */ + static SETTING_MODE = '@Setting.Mode'; + + /** + * Defines setting night asset + * @type {String} + */ + static SETTING_NIGHT = '@Setting.Night'; + + /** + * Defines setting opening asset + * @type {String} + */ + static SETTING_OPENING = '@Setting.Opening'; + + /** + * Defines setting oscillate asset + * @type {String} + */ + static SETTING_OSCILLATE = '@Setting.Oscillate'; + + /** + * Defines setting preset asset + * @type {String} + */ + static SETTING_PRESET = '@Setting.Preset'; + + /** + * Defines setting quiet asset + * @type {String} + */ + static SETTING_QUIET = '@Setting.Quiet'; + + /** + * Defines setting temperature asset + * @type {String} + */ + static SETTING_TEMPERATURE = '@Setting.Temperature'; + + /** + * Defines setting wash cycle asset + * @type {String} + */ + static SETTING_WASH_CYCLE = '@Setting.WashCycle'; + + /** + * Defines setting water temperature asset + * @type {String} + */ + static SETTING_WATER_TEMPERATURE = '@Setting.WaterTemperature'; + + /** + * Defines shower hand held asset + * @type {String} + */ + static SHOWER_HAND_HELD = '@Shower.HandHeld'; + + /** + * Defines shower rain head asset + * @type {String} + */ + static SHOWER_RAIN_HEAD = '@Shower.RainHead'; + + /** + * Defines value close asset + * @type {String} + */ + static VALUE_CLOSE = '@Value.Close'; + + /** + * Defines value delicate asset + * @type {String} + */ + static VALUE_DELICATE = '@Value.Delicate'; + + /** + * Defines value high asset + * @type {String} + */ + static VALUE_HIGH = '@Value.High'; + + /** + * Defines value low asset + * @type {String} + */ + static VALUE_LOW = '@Value.Low'; + + /** + * Defines value maximum asset + * @type {String} + */ + static VALUE_MAXIMUM = '@Value.Maximum'; + + /** + * Defines value medium asset + * @type {String} + */ + static VALUE_MEDIUM = '@Value.Medium'; + + /** + * Defines value minimum asset + * @type {String} + */ + static VALUE_MINIMUM = '@Value.Minimum'; + + /** + * Defines value open asset + * @type {String} + */ + static VALUE_OPEN = '@Value.Open'; + + /** + * Defines value quick wash asset + * @type {String} + */ + static VALUE_QUICK_WASH = '@Value.QuickWash'; + + /** + * Returns if asset id is supported + * @param {String} assetId + * @return {Boolean} + */ + static isSupported(assetId) { + return Object.values(AlexaGlobalCatalog).includes(assetId); + } + + /** + * Returns list of label object values + * @param {String} assetId + * @return {Array} + */ + static getLabels(assetId) { + return [{ assetId: 'Alexa.' + assetId.slice(1) }]; + } +} + +/** + * Defines alexa asset catalog class + * @extends AlexaGlobalCatalog + */ +class AlexaAssetCatalog extends AlexaGlobalCatalog { + /** + * Defines setting angle asset + * @type {String} + */ + static SETTING_ANGLE = '@Setting.Angle'; + + /** + * Defines setting battery level asset + * @type {String} + */ + static SETTING_BATTERY_LEVEL = '@Setting.BatteryLevel'; + + /** + * Defines setting clean asset + * @type {String} + */ + static SETTING_CLEAN = '@Setting.Clean'; + + /** + * Defines setting dock asset + * @type {String} + */ + static SETTING_DOCK = '@Setting.Dock'; + + /** + * Defines setting forward asset + * @type {String} + */ + static SETTING_FORWARD = '@Setting.Forward'; + + /** + * Defines setting humidity asset + * @type {String} + */ + static SETTING_HUMIDITY = '@Setting.Humidity'; + + /** + * Defines setting input asset + * @type {String} + */ + static SETTING_INPUT = '@Setting.Input'; + + /** + * Defines setting position asset + * @type {String} + */ + static SETTING_POSTION = '@Setting.Position'; + + /** + * Defines setting range value asset + * @type {String} + */ + static SETTING_RANGE_VALUE = '@Setting.RangeValue'; + + /** + * Defines setting reverse asset + * @type {String} + */ + static SETTING_REVERSE = '@Setting.Reverse'; + + /** + * Defines setting speed asset + * @type {String} + */ + static SETTING_SPEED = '@Setting.Speed'; + + /** + * Defines setting spot asset + * @type {String} + */ + static SETTING_SPOT = '@Setting.Spot'; + + /** + * Defines setting tilt asset + * @type {String} + */ + static SETTING_TILT = '@Setting.Tilt'; + + /** + * Defines setting toggle state asset + * @type {String} + */ + static SETTING_TOGGLE_STATE = '@Setting.ToggleState'; + + /** + * Defines value decrease asset + * @type {String} + */ + static VALUE_DECREASE = '@Value.Decrease'; + + /** + * Defines value default asset + * @type {String} + */ + static VALUE_DEFAULT = '@Value.Default'; + + /** + * Defines value down asset + * @type {String} + */ + static VALUE_DOWN = '@Value.Down'; + + /** + * Defines value increase asset + * @type {String} + */ + static VALUE_INCREASE = '@Value.Increase'; + + /** + * Defines value left asset + * @type {String} + */ + static VALUE_LEFT = '@Value.Left'; + + /** + * Defines value move asset + * @type {String} + */ + static VALUE_MOVE = '@Value.Move'; + + /** + * Defines value off asset + * @type {String} + */ + static VALUE_OFF = '@Value.Off'; + + /** + * Defines value on asset + * @type {String} + */ + static VALUE_ON = '@Value.On'; + + /** + * Defines value pause asset + * @type {String} + */ + static VALUE_PAUSE = '@Value.Pause'; + + /** + * Defines value resume asset + * @type {String} + */ + static VALUE_RESUME = '@Value.Resume'; + + /** + * Defines value right asset + * @type {String} + */ + static VALUE_RIGHT = '@Value.Right'; + + /** + * Defines value start asset + * @type {String} + */ + static VALUE_START = '@Value.Start'; + + /** + * Defines value stop asset + * @type {String} + */ + static VALUE_STOP = '@Value.Stop'; + + /** + * Defines value up asset + * @type {String} + */ + static VALUE_UP = '@Value.Up'; + + /** + * Returns custom catalog label values + * This is a temporary solution until Amazon provides the ability to upload our own catalog: + * https://developer.amazon.com/docs/device-apis/resources-and-assets.html#upload-your-own-catalog + * + * { + * '': [ + * { + * text: '