From 989aeb9eb42cc13147b7fddaf12cbb2051cd45ae Mon Sep 17 00:00:00 2001 From: Carlos Ravelo Date: Sat, 2 Feb 2019 01:15:39 -0500 Subject: [PATCH 1/4] Added the ability to handle custom commands that match the capability name e.g. device.temperature() to set the temperature Added some helpful debug logs --- package.json | 2 +- smartapps/stj/mqtt-bridge.src/mqtt-bridge.groovy | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 64b080d..c3d0c76 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "smartthings-mqtt-bridge", - "version": "3.0.0", + "version": "3.1.0", "description": "Bridge between SmartThings and an MQTT broker", "main": "server.js", "bin": { diff --git a/smartapps/stj/mqtt-bridge.src/mqtt-bridge.groovy b/smartapps/stj/mqtt-bridge.src/mqtt-bridge.groovy index 5cd877c..c9893f3 100644 --- a/smartapps/stj/mqtt-bridge.src/mqtt-bridge.groovy +++ b/smartapps/stj/mqtt-bridge.src/mqtt-bridge.groovy @@ -560,6 +560,9 @@ def bridgeHandler(evt) { device.setStatus(json.type, json.value) state.ignoreEvent = json; } + else { + log.debug "Device doesn't support setStatus command." + } } else { if (capability.containsKey("action")) { @@ -567,6 +570,13 @@ def bridgeHandler(evt) { // Yes, this is calling the method dynamically "$action"(device, json.type, json.value) } + else if (device.getSupportedCommands().any {it.name == json.type}) { + log.debug "Calling device command ${json.type} with ${json.value}" + device."$json.type"(json.value) + } + else { + log.debug "Device doesn't support ${json.type} command." + } } } } From dd3aa773a45b6d032eb87102610f03eabe2407d0 Mon Sep 17 00:00:00 2001 From: Carlos Ravelo Date: Sat, 2 Feb 2019 01:36:34 -0500 Subject: [PATCH 2/4] Added actions to temperature and humidity sensors to update them with more conventional commands Fixed indents --- .../stj/mqtt-bridge.src/mqtt-bridge.groovy | 66 ++++++++++++------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/smartapps/stj/mqtt-bridge.src/mqtt-bridge.groovy b/smartapps/stj/mqtt-bridge.src/mqtt-bridge.groovy index c9893f3..dee7588 100644 --- a/smartapps/stj/mqtt-bridge.src/mqtt-bridge.groovy +++ b/smartapps/stj/mqtt-bridge.src/mqtt-bridge.groovy @@ -29,13 +29,13 @@ import groovy.transform.Field "acceleration" ] ], - "airQualitySensors": [ - name: "AirQuality Sensor", - capability: "capability.airQualitySensor", - attributes: [ - "airQuality" - ] - ], + "airQualitySensors": [ + name: "AirQuality Sensor", + capability: "capability.airQualitySensor", + attributes: [ + "airQuality" + ] + ], "alarm": [ name: "Alarm", capability: "capability.alarm", @@ -120,14 +120,14 @@ import groovy.transform.Field ], action: "actionOpenClosed" ], - "dustSensors": [ - name: "Dust Sensor", - capability: "capability.dustSensor", - attributes: [ - "fineDustLevel", - "dustLevel" - ] - ], + "dustSensors": [ + name: "Dust Sensor", + capability: "capability.dustSensor", + attributes: [ + "fineDustLevel", + "dustLevel" + ] + ], "energyMeter": [ name: "Energy Meter", capability: "capability.energyMeter", @@ -228,7 +228,8 @@ import groovy.transform.Field capability: "capability.relativeHumidityMeasurement", attributes: [ "humidity" - ] + ], + action: "actionHumiditySensors" ], "relaySwitch": [ name: "Relay Switch", @@ -316,7 +317,8 @@ import groovy.transform.Field capability: "capability.temperatureMeasurement", attributes: [ "temperature" - ] + ], + action: "actionTemperatureSensors" ], "thermostat": [ name: "Thermostat", @@ -561,7 +563,7 @@ def bridgeHandler(evt) { state.ignoreEvent = json; } else { - log.debug "Device doesn't support setStatus command." + log.debug "Device doesn't support setStatus command." } } else { @@ -572,10 +574,10 @@ def bridgeHandler(evt) { } else if (device.getSupportedCommands().any {it.name == json.type}) { log.debug "Calling device command ${json.type} with ${json.value}" - device."$json.type"(json.value) + device."$json.type"(json.value) } else { - log.debug "Device doesn't support ${json.type} command." + log.debug "Device doesn't support ${json.type} command." } } } @@ -715,16 +717,36 @@ def actionColorTemperature(device, attribute, value) { device.setColorTemperature(value as int) } +//Temperature Sensors don't have commands but a simulated sensor might hence the hasCommand() check. +def actionTemperatureSensors(device, attribute, value) { + if (device.hasCommand("temperature")) { + device.temperature(value as int) + } + if (device.hasCommand("setTemperature")) { + device.setTemperature(value as int) + } +} + +//Humidity Sensors don't have commands but a simulated sensor might hence the hasCommand() check. +def actionHumiditySensors(device, attribute, value) { + if (device.hasCommand("humidity")) { + device.humidity(value as int) + } + if (device.hasCommand("setHumidity")) { + device.setHumidity(value as int) + } +} + def actionLevel(device, attribute, value) { device.setLevel(value as int) } def actionPresence(device, attribute, value) { if (value == "present") { - device.arrived(); + device.arrived(); } else if (value == "not present") { - device.departed(); + device.departed(); } } From 450731568b8d16b7ef82b7ca9eb116a6d0b05c12 Mon Sep 17 00:00:00 2001 From: Carlos Ravelo Date: Sat, 2 Feb 2019 01:45:57 -0500 Subject: [PATCH 3/4] Updated README and config samples --- README.md | 24 +++++++++++++++++++++++- _config.yml | 9 +++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 55adf66..3dab6b5 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,27 @@ $ mqtt pub -t 'smartthings/Fireplace Lights/switch' -m 'off' # Light goes off in SmartThings ``` +A special command can also be sent (by using a different suffix e.g. set_state). The Bridge will subscribe to changes +in topics ending in set_state for all devices. Updates to these topics triggers a setStatus command on the device, +the device handler has to support this command: + +``` +command "setStatus" + +... + +def setStatus(type, status) { + log.trace("Setting status ${type}: ${status}") + + sendEvent(name: type, value: status) +} +``` + +``` +$ mqtt pub -t 'smartthings/Living Room Temperature/temperature/set_state' -m '72' +# Virtual temperature sensor is updated to reflect the new temperature +``` + # Configuration The bridge has one yaml file for configuration: @@ -46,7 +67,7 @@ The bridge has one yaml file for configuration: ``` --- mqtt: - # Specify your MQTT Broker URL here + # Specify your MQTT Broker's hostname or IP address here host: mqtt://localhost # Example from CloudMQTT # host: mqtt:///m10.cloudmqtt.com:19427 @@ -65,6 +86,7 @@ mqtt: # state_write_suffix: set_state # Suffix for the command topics $PREFACE/$DEVICE_NAME/$PROPERTY/$COMMAND_SUFFIX + # your physical device or application should write to this topic to execute commands in SmartThings devices that support them # command_suffix: cmd # Other optional settings from https://www.npmjs.com/package/mqtt#mqttclientstreambuilder-options diff --git a/_config.yml b/_config.yml index b673ef1..d05b2ac 100644 --- a/_config.yml +++ b/_config.yml @@ -1,8 +1,9 @@ --- mqtt: # Specify your MQTT Broker's hostname or IP address here - host: mqtt - # Preface for the topics $PREFACE/$DEVICE_NAME/$PROPERTY + host: mqtt://localhost + + # Preface for the topics $PREFACE/$DEVICE_NAME/$PROPERTY preface: smartthings # The write and read suffixes need to be different to be able to differentiate when state comes from SmartThings or when its coming from the physical device/application @@ -16,11 +17,15 @@ mqtt: # state_write_suffix: set_state # Suffix for the command topics $PREFACE/$DEVICE_NAME/$PROPERTY/$COMMAND_SUFFIX + # your physical device or application should write to this topic to execute commands in SmartThings devices that support them # command_suffix: cmd # Other optional settings from https://www.npmjs.com/package/mqtt#mqttclientstreambuilder-options # username: AzureDiamond # password: hunter2 + # MQTT retains state changes be default, retain mode can be disabled: + # retain: false + # Port number to listen on port: 8080 From 40b77dc7fea1b9d685d1958fd38c3b54983d36c6 Mon Sep 17 00:00:00 2001 From: Carlos Ravelo Date: Sat, 2 Feb 2019 01:47:41 -0500 Subject: [PATCH 4/4] indents --- _config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/_config.yml b/_config.yml index d05b2ac..58e3247 100644 --- a/_config.yml +++ b/_config.yml @@ -1,9 +1,9 @@ --- mqtt: # Specify your MQTT Broker's hostname or IP address here - host: mqtt://localhost + host: mqtt://localhost - # Preface for the topics $PREFACE/$DEVICE_NAME/$PROPERTY + # Preface for the topics $PREFACE/$DEVICE_NAME/$PROPERTY preface: smartthings # The write and read suffixes need to be different to be able to differentiate when state comes from SmartThings or when its coming from the physical device/application @@ -17,15 +17,15 @@ mqtt: # state_write_suffix: set_state # Suffix for the command topics $PREFACE/$DEVICE_NAME/$PROPERTY/$COMMAND_SUFFIX - # your physical device or application should write to this topic to execute commands in SmartThings devices that support them + # your physical device or application should write to this topic to execute commands in SmartThings devices that support them # command_suffix: cmd # Other optional settings from https://www.npmjs.com/package/mqtt#mqttclientstreambuilder-options # username: AzureDiamond # password: hunter2 - # MQTT retains state changes be default, retain mode can be disabled: - # retain: false + # MQTT retains state changes be default, retain mode can be disabled: + # retain: false # Port number to listen on port: 8080