diff --git a/devicetypes/smartthings/centralite-dimmer.src/centralite-dimmer.groovy b/devicetypes/smartthings/centralite-dimmer.src/centralite-dimmer.groovy deleted file mode 100644 index cf41886..0000000 --- a/devicetypes/smartthings/centralite-dimmer.src/centralite-dimmer.groovy +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright 2015 SmartThings - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License - * for the specific language governing permissions and limitations under the License. - * - * CentraLite Dimmer - * - * Author: SmartThings - * Date: 2013-12-04 - */ -//DEPRECATED - Using the generic DTH for this device. Users need to be moved before deleting this DTH -metadata { - definition (name: "CentraLite Dimmer", namespace: "smartthings", author: "SmartThings") { - capability "Switch Level" - capability "Actuator" - capability "Switch" - capability "Power Meter" - capability "Configuration" - capability "Refresh" - capability "Sensor" - - } - - tiles(scale: 2) { - multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ - tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - } - tileAttribute ("device.level", key: "SLIDER_CONTROL") { - attributeState "level", action:"switch level.setLevel" - } - tileAttribute ("power", key: "SECONDARY_CONTROL") { - attributeState "power", label:'${currentValue} W' - } - } - standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" - } - main "switch" - details(["switch", "refresh"]) - } -} - -// Parse incoming device messages to generate events -def parse(String description) { - log.debug "description is $description" - - def event = zigbee.getEvent(description) - if (event) { - log.info event - if (event.name == "power") { - if (device.getDataValue("manufacturer") != "OSRAM") { //OSRAM devices do not reliably update power - event.value = (event.value as Integer) / 10 //TODO: The divisor value needs to be set as part of configuration - sendEvent(event) - } - } - else { - sendEvent(event) - } - } - else { - log.warn "DID NOT PARSE MESSAGE for description : $description" - log.debug zigbee.parseDescriptionAsMap(description) - } -} - -def off() { - zigbee.off() -} - -def on() { - zigbee.on() -} - -def setLevel(value) { - zigbee.setLevel(value) -} - -def refresh() { - zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.simpleMeteringPowerRefresh() + zigbee.electricMeasurementPowerRefresh() + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.simpleMeteringPowerConfig() + zigbee.electricMeasurementPowerConfig() -} - -def configure() { - log.debug "Configuring Reporting and Bindings." - refresh() -} diff --git a/devicetypes/smartthings/ge-zigbee-dimmer.src/ge-zigbee-dimmer.groovy b/devicetypes/smartthings/ge-zigbee-dimmer.src/ge-zigbee-dimmer.groovy deleted file mode 100644 index 85dd41d..0000000 --- a/devicetypes/smartthings/ge-zigbee-dimmer.src/ge-zigbee-dimmer.groovy +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright 2015 SmartThings - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License - * for the specific language governing permissions and limitations under the License. - * - * GE/Jasco ZigBee Dimmer - * - * Author: SmartThings - * Date: 2015-07-01 - */ - -metadata { - definition (name: "GE ZigBee Dimmer", namespace: "smartthings", author: "SmartThings") { - capability "Switch" - capability "Switch Level" - capability "Power Meter" - capability "Configuration" - capability "Refresh" - capability "Actuator" - capability "Sensor" - - } - - tiles(scale: 2) { - multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ - tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - } - tileAttribute ("device.level", key: "SLIDER_CONTROL") { - attributeState "level", action:"switch level.setLevel" - } - tileAttribute ("power", key: "SECONDARY_CONTROL") { - attributeState "power", label:'${currentValue} W' - } - } - standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" - } - main "switch" - details(["switch", "refresh"]) - } -} - -// Parse incoming device messages to generate events -def parse(String description) { - log.debug "description is $description" - - def event = zigbee.getEvent(description) - if (event) { - log.info event - if (event.name == "power") { - if (device.getDataValue("manufacturer") != "OSRAM") { //OSRAM devices do not reliably update power - event.value = (event.value as Integer) / 10 //TODO: The divisor value needs to be set as part of configuration - sendEvent(event) - } - } - else { - sendEvent(event) - } - } - else { - log.warn "DID NOT PARSE MESSAGE for description : $description" - log.debug zigbee.parseDescriptionAsMap(description) - } -} - -def off() { - zigbee.off() -} - -def on() { - zigbee.on() -} - -def setLevel(value) { - zigbee.setLevel(value) -} - -def refresh() { - zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.simpleMeteringPowerRefresh() + zigbee.electricMeasurementPowerRefresh() + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.simpleMeteringPowerConfig() + zigbee.electricMeasurementPowerConfig() -} - -def configure() { - log.debug "Configuring Reporting and Bindings." - refresh() -} diff --git a/devicetypes/smartthings/ge-zigbee-switch.src/ge-zigbee-switch.groovy b/devicetypes/smartthings/ge-zigbee-switch.src/ge-zigbee-switch.groovy deleted file mode 100644 index 082021f..0000000 --- a/devicetypes/smartthings/ge-zigbee-switch.src/ge-zigbee-switch.groovy +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright 2015 SmartThings - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License - * for the specific language governing permissions and limitations under the License. - * - * GE/Jasco ZigBee Switch - * - * Author: SmartThings - * Date: 2015-07-01 - */ - -metadata { - // Automatically generated. Make future change here. - definition (name: "GE ZigBee Switch", namespace: "smartthings", author: "SmartThings") { - capability "Switch" - capability "Power Meter" - capability "Configuration" - capability "Refresh" - capability "Actuator" - capability "Sensor" - - } - - tiles(scale: 2) { - multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ - tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn" - } - tileAttribute ("power", key: "SECONDARY_CONTROL") { - attributeState "power", label:'${currentValue} W' - } - } - standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" - } - main "switch" - details(["switch", "refresh"]) - } -} - -// Parse incoming device messages to generate events -def parse(String description) { - log.debug "description is $description" - def event = zigbee.getEvent(description) - if (event) { - if (event.name == "power") { - def powerValue - powerValue = (event.value as Integer)/10 //TODO: The divisor value needs to be set as part of configuration - sendEvent(name: "power", value: powerValue) - } - else { - sendEvent(event) - } - } - else { - log.warn "DID NOT PARSE MESSAGE for description : $description" - log.debug zigbee.parseDescriptionAsMap(description) - } -} - -def off() { - zigbee.off() -} - -def on() { - zigbee.on() -} - -def refresh() { - zigbee.onOffRefresh() + zigbee.simpleMeteringPowerRefresh() + zigbee.electricMeasurementPowerRefresh() + zigbee.onOffConfig() + zigbee.simpleMeteringPowerConfig() + zigbee.electricMeasurementPowerConfig() -} - -def configure() { - log.debug "Configuring Reporting and Bindings." - refresh() -} diff --git a/devicetypes/smartthings/osram-lightify-gardenspot-mini-rgb.src/osram-lightify-gardenspot-mini-rgb.groovy b/devicetypes/smartthings/osram-lightify-gardenspot-mini-rgb.src/osram-lightify-gardenspot-mini-rgb.groovy deleted file mode 100644 index 618587a..0000000 --- a/devicetypes/smartthings/osram-lightify-gardenspot-mini-rgb.src/osram-lightify-gardenspot-mini-rgb.groovy +++ /dev/null @@ -1,145 +0,0 @@ -/* - Osram Lightify Gardenspot Mini RGB - - Osram bulbs have a firmware issue causing it to forget its dimming level when turned off (via commands). Handling - that issue by using state variables -*/ - -metadata { - definition (name: "OSRAM LIGHTIFY Gardenspot mini RGB", namespace: "smartthings", author: "SmartThings") { - - capability "Color Temperature" - capability "Actuator" - capability "Switch" - capability "Switch Level" - capability "Configuration" - capability "Polling" - capability "Refresh" - capability "Sensor" - capability "Color Control" - - attribute "colorName", "string" - - command "setAdjustedColor" - } - - // UI tile definitions - tiles(scale: 2) { - multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ - tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - } - tileAttribute ("device.level", key: "SLIDER_CONTROL") { - attributeState "level", action:"switch level.setLevel" - } - tileAttribute ("device.color", key: "COLOR_CONTROL") { - attributeState "color", action:"color control.setColor" - } - } - standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" - } - - main(["switch"]) - details(["switch", "refresh"]) - } -} - -//Globals -private getATTRIBUTE_HUE() { 0x0000 } -private getATTRIBUTE_SATURATION() { 0x0001 } -private getHUE_COMMAND() { 0x00 } -private getSATURATION_COMMAND() { 0x03 } -private getCOLOR_CONTROL_CLUSTER() { 0x0300 } - -// Parse incoming device messages to generate events -def parse(String description) { - log.debug "description is $description" - - def event = zigbee.getEvent(description) - if (event) { - log.debug event - if (event.name=="level" && event.value==0) {} - else { - sendEvent(event) - } - } - else { - def zigbeeMap = zigbee.parseDescriptionAsMap(description) - def cluster = zigbee.parse(description) - - if (zigbeeMap?.clusterInt == COLOR_CONTROL_CLUSTER) { - if(zigbeeMap.attrInt == ATTRIBUTE_HUE){ //Hue Attribute - def hueValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 100) - sendEvent(name: "hue", value: hueValue, descriptionText: "Color has changed") - } - else if(zigbeeMap.attrInt == ATTRIBUTE_SATURATION){ //Saturation Attribute - def saturationValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 100) - sendEvent(name: "saturation", value: saturationValue, descriptionText: "Color has changed", displayed: false) - } - } - else if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) { - if (cluster.data[0] == 0x00){ - log.debug "ON/OFF REPORTING CONFIG RESPONSE: $cluster" - sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) - } - else { - log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}" - } - } - else { - log.info "DID NOT PARSE MESSAGE for description : $description" - log.debug zigbeeMap - } - } -} - -def on() { - zigbee.on() -} - -def off() { - zigbee.off() -} -/** - * PING is used by Device-Watch in attempt to reach the Device - * */ -def ping() { - return zigbee.onOffRefresh() -} - -def refresh() { - zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) -} - -def configure() { - log.debug "Configuring Reporting and Bindings." - // Device-Watch allows 3 check-in misses from device (plus 1 min lag time) - // enrolls with default periodic reporting until newer 5 min interval is confirmed - sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) - - // OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity - zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) -} - -def setLevel(value) { - zigbee.setLevel(value) -} - -def setColor(value){ - log.trace "setColor($value)" - zigbee.on() + setHue(value.hue) + "delay 500" + setSaturation(value.saturation) -} - -def setHue(value) { - def scaledHueValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2) - zigbee.command(COLOR_CONTROL_CLUSTER, HUE_COMMAND, scaledHueValue, "00", "0500") //payload-> hue value, direction (00-> shortest distance), transition time (1/10th second) (0500 in U16 reads 5) -} - -def setSaturation(value) { - def scaledSatValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2) - zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") + "delay 1000" + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) -} diff --git a/devicetypes/smartthings/osram-lightify-led-flexible-strip-rgbw.src/osram-lightify-led-flexible-strip-rgbw.groovy b/devicetypes/smartthings/osram-lightify-led-flexible-strip-rgbw.src/osram-lightify-led-flexible-strip-rgbw.groovy deleted file mode 100644 index d12a968..0000000 --- a/devicetypes/smartthings/osram-lightify-led-flexible-strip-rgbw.src/osram-lightify-led-flexible-strip-rgbw.groovy +++ /dev/null @@ -1,183 +0,0 @@ -/* - Osram Flex RGBW Light Strip - - Osram bulbs have a firmware issue causing it to forget its dimming level when turned off (via commands). Handling - that issue by using state variables -*/ -//DEPRECATED - Using the generic DTH for this device. Users need to be moved before deleting this DTH - -metadata { - definition (name: "OSRAM LIGHTIFY LED Flexible Strip RGBW", namespace: "smartthings", author: "SmartThings") { - - capability "Color Temperature" - capability "Actuator" - capability "Switch" - capability "Switch Level" - capability "Configuration" - capability "Polling" - capability "Refresh" - capability "Sensor" - capability "Color Control" - - attribute "colorName", "string" - - command "setAdjustedColor" - - - //fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY Flex RGBW" - //fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Flex RGBW" - - } - - // UI tile definitions - tiles(scale: 2) { - multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ - tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - } - tileAttribute ("device.level", key: "SLIDER_CONTROL") { - attributeState "level", action:"switch level.setLevel" - } - tileAttribute ("device.color", key: "COLOR_CONTROL") { - attributeState "color", action:"color control.setColor" - } - } - controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..6500)") { - state "colorTemperature", action:"color temperature.setColorTemperature" - } - valueTile("colorName", "device.colorName", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "colorName", label: '${currentValue}' - } - standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" - } - - main(["switch"]) - details(["switch", "colorTempSliderControl", "colorName", "refresh"]) - } -} - -//Globals -private getATTRIBUTE_HUE() { 0x0000 } -private getATTRIBUTE_SATURATION() { 0x0001 } -private getHUE_COMMAND() { 0x00 } -private getSATURATION_COMMAND() { 0x03 } -private getCOLOR_CONTROL_CLUSTER() { 0x0300 } -private getATTRIBUTE_COLOR_TEMPERATURE() { 0x0007 } - -// Parse incoming device messages to generate events -def parse(String description) { - log.debug "description is $description" - - def event = zigbee.getEvent(description) - if (event) { - log.debug event - if (event.name=="level" && event.value==0) {} - else { - if (event.name=="colorTemperature") { - setGenericName(event.value) - } - sendEvent(event) - } - } - else { - def zigbeeMap = zigbee.parseDescriptionAsMap(description) - def cluster = zigbee.parse(description) - - if (zigbeeMap?.clusterInt == COLOR_CONTROL_CLUSTER) { - if(zigbeeMap.attrInt == ATTRIBUTE_HUE){ //Hue Attribute - def hueValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 100) - sendEvent(name: "hue", value: hueValue, descriptionText: "Color has changed") - } - else if(zigbeeMap.attrInt == ATTRIBUTE_SATURATION){ //Saturation Attribute - def saturationValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 100) - sendEvent(name: "saturation", value: saturationValue, descriptionText: "Color has changed", displayed: false) - } - } - else if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) { - if (cluster.data[0] == 0x00){ - log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster - sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) - } - else { - log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}" - } - } - else { - log.info "DID NOT PARSE MESSAGE for description : $description" - log.debug zigbeeMap - } - } -} - -def on() { - zigbee.on() -} - -def off() { - zigbee.off() -} -/** - * PING is used by Device-Watch in attempt to reach the Device - * */ -def ping() { - return zigbee.onOffRefresh() -} - -def refresh() { - zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) -} - -def configure() { - log.debug "Configuring Reporting and Bindings." - // Device-Watch allows 3 check-in misses from device (plus 1 min lag time) - // enrolls with default periodic reporting until newer 5 min interval is confirmed - sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) - - // OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity - refresh() -} - -def setColorTemperature(value) { - setGenericName(value) - zigbee.setColorTemperature(value) -} - -//Naming based on the wiki article here: http://en.wikipedia.org/wiki/Color_temperature -def setGenericName(value){ - if (value != null) { - def genericName = "White" - if (value < 3300) { - genericName = "Soft White" - } else if (value < 4150) { - genericName = "Moonlight" - } else if (value <= 5000) { - genericName = "Cool White" - } else if (value >= 5000) { - genericName = "Daylight" - } - sendEvent(name: "colorName", value: genericName) - } -} - -def setLevel(value) { - zigbee.setLevel(value) -} - -def setColor(value){ - log.trace "setColor($value)" - zigbee.on() + setHue(value.hue) + "delay 300" + setSaturation(value.saturation) -} - -def setHue(value) { - def scaledHueValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2) - zigbee.command(COLOR_CONTROL_CLUSTER, HUE_COMMAND, scaledHueValue, "00", "0500") //payload-> hue value, direction (00-> shortest distance), transition time (1/10th second) (0500 in U16 reads 5) -} - -def setSaturation(value) { - def scaledSatValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2) - zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") + "delay 1000" + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) -} \ No newline at end of file diff --git a/devicetypes/smartthings/osram-lightify-led-tunable-white-60w.src/osram-lightify-led-tunable-white-60w.groovy b/devicetypes/smartthings/osram-lightify-led-tunable-white-60w.src/osram-lightify-led-tunable-white-60w.groovy deleted file mode 100644 index 7c18d15..0000000 --- a/devicetypes/smartthings/osram-lightify-led-tunable-white-60w.src/osram-lightify-led-tunable-white-60w.groovy +++ /dev/null @@ -1,139 +0,0 @@ -/* - Osram Tunable White 60 A19 bulb - - Osram bulbs have a firmware issue causing it to forget its dimming level when turned off (via commands). Handling - that issue by using state variables -*/ - -//DEPRECATED - Using the generic DTH for this device. Users need to be moved before deleting this DTH - -metadata { - definition (name: "OSRAM LIGHTIFY LED Tunable White 60W", namespace: "smartthings", author: "SmartThings") { - - capability "Color Temperature" - capability "Actuator" - capability "Switch" - capability "Switch Level" - capability "Configuration" - capability "Refresh" - capability "Sensor" - - attribute "colorName", "string" - } - - // UI tile definitions - tiles(scale: 2) { - multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ - tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn" - } - tileAttribute ("device.level", key: "SLIDER_CONTROL") { - attributeState "level", action:"switch level.setLevel" - } - } - - standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" - } - - controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..6500)") { - state "colorTemperature", action:"color temperature.setColorTemperature" - } - valueTile("colorName", "device.colorName", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "colorName", label: '${currentValue}' - } - - main(["switch"]) - details(["switch", "colorTempSliderControl", "colorName", "refresh"]) - } -} - -// Parse incoming device messages to generate events -def parse(String description) { - log.debug "description is $description" - def event = zigbee.getEvent(description) - if (event) { - if (event.name=="level" && event.value==0) {} - else { - if (event.name=="colorTemperature") { - setGenericName(event.value) - } - sendEvent(event) - } - } - else { - def cluster = zigbee.parse(description) - - if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) { - if (cluster.data[0] == 0x00) { - log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster - sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) - } - else { - log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}" - } - } - else { - log.warn "DID NOT PARSE MESSAGE for description : $description" - log.debug "${cluster}" - } - } -} - -def off() { - zigbee.off() -} - -def on() { - zigbee.on() -} - -def setLevel(value) { - zigbee.setLevel(value) -} - -/** - * PING is used by Device-Watch in attempt to reach the Device - * */ -def ping() { - return zigbee.onOffRefresh() -} - -def refresh() { - zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig() -} - -def configure() { - log.debug "Configuring Reporting and Bindings." - // Device-Watch allows 3 check-in misses from device (plus 1 min lag time) - // enrolls with default periodic reporting until newer 5 min interval is confirmed - sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) - - // OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity - refresh() -} - -def setColorTemperature(value) { - setGenericName(value) - zigbee.setColorTemperature(value) -} - -//Naming based on the wiki article here: http://en.wikipedia.org/wiki/Color_temperature -def setGenericName(value){ - if (value != null) { - def genericName = "White" - if (value < 3300) { - genericName = "Soft White" - } else if (value < 4150) { - genericName = "Moonlight" - } else if (value <= 5000) { - genericName = "Cool White" - } else if (value >= 5000) { - genericName = "Daylight" - } - sendEvent(name: "colorName", value: genericName) - } -} diff --git a/devicetypes/smartthings/smartsense-motion-temp-sensor.src/smartsense-motion-temp-sensor.groovy b/devicetypes/smartthings/smartsense-motion-temp-sensor.src/smartsense-motion-temp-sensor.groovy deleted file mode 100644 index 3b3da9a..0000000 --- a/devicetypes/smartthings/smartsense-motion-temp-sensor.src/smartsense-motion-temp-sensor.groovy +++ /dev/null @@ -1,328 +0,0 @@ -/** - * SmartSense Motion/Temp Sensor - * - * Copyright 2014 SmartThings - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License - * for the specific language governing permissions and limitations under the License. - * - */ - -//DEPRECATED - Using the smartsense-motion-sensor.groovy DTH for this device. Users need to be moved before deleting this DTH -import physicalgraph.zigbee.clusters.iaszone.ZoneStatus - -metadata { - definition (name: "SmartSense Motion/Temp Sensor", namespace: "smartthings", author: "SmartThings") { - capability "Motion Sensor" - capability "Configuration" - capability "Battery" - capability "Temperature Measurement" - capability "Refresh" - capability "Sensor" - - command "enrollResponse" - - } - - preferences { - section { - image(name: 'educationalcontent', multiple: true, images: [ - "http://cdn.device-gse.smartthings.com/Motion/Motion1.jpg", - "http://cdn.device-gse.smartthings.com/Motion/Motion2.jpg", - "http://cdn.device-gse.smartthings.com/Motion/Motion3.jpg" - ]) - } - section { - input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.", displayDuringSetup: false, type: "paragraph", element: "paragraph" - input "tempOffset", "number", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false - } - } - - tiles(scale: 2) { - multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){ - tileAttribute ("device.motion", key: "PRIMARY_CONTROL") { - attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0" - attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff" - } - } - valueTile("temperature", "device.temperature", width: 2, height: 2) { - state("temperature", label:'${currentValue}°', unit:"F", - backgroundColors:[ - [value: 31, color: "#153591"], - [value: 44, color: "#1e9cbb"], - [value: 59, color: "#90d2a7"], - [value: 74, color: "#44b621"], - [value: 84, color: "#f1d801"], - [value: 95, color: "#d04e00"], - [value: 96, color: "#bc2323"] - ] - ) - } - valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) { - state "battery", label:'${currentValue}% battery', unit:"" - } - standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", action:"refresh.refresh", icon:"st.secondary.refresh" - } - - main(["motion", "temperature"]) - details(["motion", "temperature", "battery", "refresh"]) - } -} - -def parse(String description) { - log.debug "description: $description" - - Map map = [:] - if (description?.startsWith('catchall:')) { - map = parseCatchAllMessage(description) - } - else if (description?.startsWith('read attr -')) { - map = parseReportAttributeMessage(description) - } - else if (description?.startsWith('temperature: ')) { - map = parseCustomMessage(description) - } - else if (description?.startsWith('zone status')) { - map = parseIasMessage(description) - } - - log.debug "Parse returned $map" - def result = map ? createEvent(map) : null - - if (description?.startsWith('enroll request')) { - List cmds = enrollResponse() - log.debug "enroll response: ${cmds}" - result = cmds?.collect { new physicalgraph.device.HubAction(it) } - } - return result -} - -private Map parseCatchAllMessage(String description) { - Map resultMap = [:] - def cluster = zigbee.parse(description) - if (shouldProcessMessage(cluster)) { - switch(cluster.clusterId) { - case 0x0001: - // 0x07 - configure reporting - if (cluster.command != 0x07) { - resultMap = getBatteryResult(cluster.data.last()) - } - break - - case 0x0402: - if (cluster.command == 0x07) { - if (cluster.data[0] == 0x00) { - log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster - sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) - } - else { - log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}" - } - - } - else { - // temp is last 2 data values. reverse to swap endian - String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join() - def value = getTemperature(temp) - resultMap = getTemperatureResult(value) - } - break - - case 0x0406: - // 0x07 - configure reporting - if (cluster.command != 0x07) { - log.debug 'motion' - resultMap.name = 'motion' - } - break - } - } - - return resultMap -} - -private boolean shouldProcessMessage(cluster) { - // 0x0B is default response indicating message got through - boolean ignoredMessage = cluster.profileId != 0x0104 || - cluster.command == 0x0B || - (cluster.data.size() > 0 && cluster.data.first() == 0x3e) - return !ignoredMessage -} - -private Map parseReportAttributeMessage(String description) { - Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param -> - def nameAndValue = param.split(":") - map += [(nameAndValue[0].trim()):nameAndValue[1].trim()] - } - log.debug "Desc Map: $descMap" - - Map resultMap = [:] - if (descMap.cluster == "0402" && descMap.attrId == "0000") { - def value = getTemperature(descMap.value) - resultMap = getTemperatureResult(value) - } - else if (descMap.cluster == "0001" && descMap.attrId == "0020") { - resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16)) - } - else if (descMap.cluster == "0406" && descMap.attrId == "0000") { - def value = descMap.value.endsWith("01") ? "active" : "inactive" - resultMap = getMotionResult(value) - } - - return resultMap -} - -private Map parseCustomMessage(String description) { - Map resultMap = [:] - if (description?.startsWith('temperature: ')) { - def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale()) - resultMap = getTemperatureResult(value) - } - return resultMap -} - -private Map parseIasMessage(String description) { - ZoneStatus zs = zigbee.parseZoneStatus(description) - - // Some sensor models that use this DTH use alarm1 and some use alarm2 to signify motion - return (zs.isAlarm1Set() || zs.isAlarm2Set()) ? getMotionResult('active') : getMotionResult('inactive') -} - -def getTemperature(value) { - def celsius = Integer.parseInt(value, 16).shortValue() / 100 - if(getTemperatureScale() == "C"){ - return Math.round(celsius) - } else { - return Math.round(celsiusToFahrenheit(celsius)) - } -} - -private Map getBatteryResult(rawValue) { - log.debug 'Battery' - def linkText = getLinkText(device) - - def result = [:] - - def volts = rawValue / 10 - - if (!(rawValue == 0 || rawValue == 255)) { - def minVolts = 2.1 - def maxVolts = 3.0 - def pct = (volts - minVolts) / (maxVolts - minVolts) - def roundedPct = Math.round(pct * 100) - if (roundedPct <= 0) - roundedPct = 1 - result.name = 'battery' - result.value = Math.min(100, roundedPct) - result.descriptionText = "${linkText} battery was ${result.value}%" - - } - - return result -} - -private Map getTemperatureResult(value) { - log.debug 'TEMP' - if (tempOffset) { - def offset = tempOffset as int - def v = value as int - value = v + offset - } - def descriptionText - if ( temperatureScale == 'C' ) - descriptionText = '{{ device.displayName }} was {{ value }}°C' - else - descriptionText = '{{ device.displayName }} was {{ value }}°F' - - return [ - name: 'temperature', - value: value, - descriptionText: descriptionText, - translatable: true, - unit: temperatureScale - ] -} - -private Map getMotionResult(value) { - log.debug 'motion' - String descriptionText = value == 'active' ? "{{ device.displayName }} detected motion" : "{{ device.displayName }} motion has stopped" - return [ - name: 'motion', - value: value, - descriptionText: descriptionText, - translatable: true - ] -} - -/** - * PING is used by Device-Watch in attempt to reach the Device - * */ -def ping() { - return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level -} - -def refresh() { - log.debug "refresh called" - def refreshCmds = [ - "st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200", - "st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200" - ] - - return refreshCmds + enrollResponse() -} - -def configure() { - // Device-Watch allows 3 check-in misses from device (plus 1 min lag time) - // enrolls with default periodic reporting until newer 5 min interval is confirmed - sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) - - // temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity - // battery minReport 30 seconds, maxReportTime 6 hrs by default - return refresh() + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config -} - -def enrollResponse() { - log.debug "Sending enroll response" - String zigbeeEui = swapEndianHex(device.hub.zigbeeEui) - [ - //Resending the CIE in case the enroll request is sent before CIE is written - "zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200", - "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500", - //Enroll Response - "raw 0x500 {01 23 00 00 00}", - "send 0x${device.deviceNetworkId} 1 1", "delay 200" - ] -} - -private getEndpointId() { - new BigInteger(device.endpointId, 16).toString() -} - -private hex(value) { - new BigInteger(Math.round(value).toString()).toString(16) -} - -private String swapEndianHex(String hex) { - reverseArray(hex.decodeHex()).encodeHex() -} - -private byte[] reverseArray(byte[] array) { - int i = 0; - int j = array.length - 1; - byte tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } - return array -} diff --git a/devicetypes/smartthings/smartsense-open-closed-accelerometer-sensor.src/smartsense-open-closed-accelerometer-sensor.groovy b/devicetypes/smartthings/smartsense-open-closed-accelerometer-sensor.src/smartsense-open-closed-accelerometer-sensor.groovy deleted file mode 100644 index 4e9d14c..0000000 --- a/devicetypes/smartthings/smartsense-open-closed-accelerometer-sensor.src/smartsense-open-closed-accelerometer-sensor.groovy +++ /dev/null @@ -1,503 +0,0 @@ -/** - * SmartSense Open/Closed Accelerometer Sensor - * - * Copyright 2014 SmartThings - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License - * for the specific language governing permissions and limitations under the License. - * - */ -//DEPRECATED - Using the smartsense-multi-sensor.groovy DTH for this device. Users need to be moved before deleting this DTH -import physicalgraph.zigbee.clusters.iaszone.ZoneStatus - -metadata { - definition (name: "SmartSense Open/Closed Accelerometer Sensor", namespace: "smartthings", author: "SmartThings", category: "C2") { - capability "Battery" - capability "Configuration" - capability "Contact Sensor" - capability "Acceleration Sensor" - capability "Refresh" - capability "Temperature Measurement" - capability "Health Check" - capability "Sensor" - - command "enrollResponse" - attribute "status", "string" - } - - preferences { - section { - image(name: 'educationalcontent', multiple: true, images: [ - "http://cdn.device-gse.smartthings.com/Multi/Multi1.jpg", - "http://cdn.device-gse.smartthings.com/Multi/Multi2.jpg", - "http://cdn.device-gse.smartthings.com/Multi/Multi3.jpg", - "http://cdn.device-gse.smartthings.com/Multi/Multi4.jpg" - ]) - } - section { - input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.", displayDuringSetup: false, type: "paragraph", element: "paragraph" - input "tempOffset", "number", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false - } - section { - input("garageSensor", "enum", title: "Do you want to use this sensor on a garage door?", description: "Tap to set", options: ["Yes", "No"], defaultValue: "No", required: false, displayDuringSetup: false) - } - } - - tiles(scale: 2) { - multiAttributeTile(name:"status", type: "generic", width: 6, height: 4){ - tileAttribute ("device.status", key: "PRIMARY_CONTROL") { - attributeState "open", label:'Open', icon:"st.contact.contact.open", backgroundColor:"#ffa81e" - attributeState "closed", label:'Closed', icon:"st.contact.contact.closed", backgroundColor:"#79b821" - attributeState "garage-open", label:'Open', icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e" - attributeState "garage-closed", label:'Closed', icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821" - } - } - standardTile("contact", "device.contact", width: 2, height: 2) { - state("open", label:'Open', icon:"st.contact.contact.open", backgroundColor:"#ffa81e") - state("closed", label:'Closed', icon:"st.contact.contact.closed", backgroundColor:"#79b821") - } - standardTile("acceleration", "device.acceleration", width: 2, height: 2) { - state("active", label:'Active', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0") - state("inactive", label:'Inactive', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff") - } - valueTile("temperature", "device.temperature", width: 2, height: 2) { - state("temperature", label:'${currentValue}°', - backgroundColors:[ - [value: 31, color: "#153591"], - [value: 44, color: "#1e9cbb"], - [value: 59, color: "#90d2a7"], - [value: 74, color: "#44b621"], - [value: 84, color: "#f1d801"], - [value: 95, color: "#d04e00"], - [value: 96, color: "#bc2323"] - ] - ) - } - valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) { - state "battery", label:'${currentValue}% battery', unit:"" - } - standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", action:"refresh.refresh", icon:"st.secondary.refresh" - } - - - main(["status", "acceleration", "temperature"]) - details(["status", "acceleration", "temperature", "battery", "refresh"]) - } -} - -def parse(String description) { - Map map = [:] - if (description?.startsWith('catchall:')) { - map = parseCatchAllMessage(description) - } - else if (description?.startsWith('temperature: ')) { - map = parseCustomMessage(description) - } - else if (description?.startsWith('zone status')) { - map = parseIasMessage(description) - } - - def result = map ? createEvent(map) : null - - if (description?.startsWith('enroll request')) { - List cmds = enrollResponse() - log.debug "enroll response: ${cmds}" - result = cmds?.collect { new physicalgraph.device.HubAction(it) } - } - else if (description?.startsWith('read attr -')) { - result = parseReportAttributeMessage(description).each { createEvent(it) } - } - return result -} - -private Map parseCatchAllMessage(String description) { - Map resultMap = [:] - def cluster = zigbee.parse(description) - log.debug cluster - if (shouldProcessMessage(cluster)) { - switch(cluster.clusterId) { - case 0x0001: - // 0x07 - configure reporting - if (cluster.command != 0x07) { - resultMap = getBatteryResult(cluster.data.last()) - } - break - - case 0xFC02: - log.debug 'ACCELERATION' - break - - case 0x0402: - if (cluster.command == 0x07) { - if(cluster.data[0] == 0x00) { - log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster - sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) - } - else { - log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}" - } - } - else { - // temp is last 2 data values. reverse to swap endian - String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join() - def value = getTemperature(temp) - resultMap = getTemperatureResult(value) - } - break - } - } - - return resultMap -} - -private boolean shouldProcessMessage(cluster) { - // 0x0B is default response indicating message got through - boolean ignoredMessage = cluster.profileId != 0x0104 || - cluster.command == 0x0B || - (cluster.data.size() > 0 && cluster.data.first() == 0x3e) - return !ignoredMessage -} - -private List parseReportAttributeMessage(String description) { - Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param -> - def nameAndValue = param.split(":") - map += [(nameAndValue[0].trim()):nameAndValue[1].trim()] - } - - List result = [] - if (descMap.cluster == "0402" && descMap.attrId == "0000") { - def value = getTemperature(descMap.value) - result << getTemperatureResult(value) - } - else if (descMap.cluster == "FC02" && descMap.attrId == "0010") { - if (descMap.value.size() == 32) { - // value will look like 00ae29001403e2290013001629001201 - // breaking this apart and swapping byte order where appropriate, this breaks down to: - // X (0x0012) = 0x0016 - // Y (0x0013) = 0x03E2 - // Z (0x0014) = 0x00AE - // note that there is a known bug in that the x,y,z attributes are interpreted in the wrong order - // this will be fixed in a future update - def threeAxisAttributes = descMap.value[0..-9] - result << parseAxis(threeAxisAttributes) - descMap.value = descMap.value[-2..-1] - } - result << getAccelerationResult(descMap.value) - } - else if (descMap.cluster == "FC02" && descMap.attrId == "0012" && descMap.value.size() == 24) { - // The size is checked to ensure the attribute report contains X, Y and Z values - // If all three axis are not included then the attribute report is ignored - result << parseAxis(descMap.value) - } - else if (descMap.cluster == "0001" && descMap.attrId == "0020") { - result << getBatteryResult(Integer.parseInt(descMap.value, 16)) - } - - return result -} - -private Map parseCustomMessage(String description) { - Map resultMap = [:] - if (description?.startsWith('temperature: ')) { - def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale()) - resultMap = getTemperatureResult(value) - } - return resultMap -} - -private Map parseIasMessage(String description) { - ZoneStatus zs = zigbee.parseZoneStatus(description) - Map resultMap = [:] - - if (garageSensor != "Yes"){ - resultMap = zs.isAlarm1Set() ? getContactResult('open') : getContactResult('closed') - } - - return resultMap -} - -def updated() { - log.debug "updated called" - log.info "garage value : $garageSensor" - if (garageSensor == "Yes") { - def descriptionText = "Updating device to garage sensor" - if (device.latestValue("status") == "open") { - sendEvent(name: 'status', value: 'garage-open', descriptionText: descriptionText, translatable: true) - } - else if (device.latestValue("status") == "closed") { - sendEvent(name: 'status', value: 'garage-closed', descriptionText: descriptionText, translatable: true) - } - } - else { - def descriptionText = "Updating device to open/close sensor" - if (device.latestValue("status") == "garage-open") { - sendEvent(name: 'status', value: 'open', descriptionText: descriptionText, translatable: true) - } - else if (device.latestValue("status") == "garage-closed") { - sendEvent(name: 'status', value: 'closed', descriptionText: descriptionText, translatable: true) - } - } -} - -def getTemperature(value) { - def celsius = Integer.parseInt(value, 16).shortValue() / 100 - if(getTemperatureScale() == "C"){ - return Math.round(celsius) - } else { - return Math.round(celsiusToFahrenheit(celsius)) - } -} - -private Map getBatteryResult(rawValue) { - log.debug 'Battery' - def linkText = getLinkText(device) - - def result = [:] - - def volts = rawValue / 10 - - if (!(rawValue == 0 || rawValue == 255)) { - def minVolts = 2.1 - def maxVolts = 3.0 - def pct = (volts - minVolts) / (maxVolts - minVolts) - def roundedPct = Math.round(pct * 100) - if (roundedPct <= 0) - roundedPct = 1 - result.name = 'battery' - result.value = Math.min(100, roundedPct) - result.descriptionText = "${linkText} battery was ${result.value}%" - - } - - return result -} - -private Map getTemperatureResult(value) { - log.debug "Temperature" - if (tempOffset) { - def offset = tempOffset as int - def v = value as int - value = v + offset - } - def descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C': - '{{ device.displayName }} was {{ value }}°F' - - return [ - name: 'temperature', - value: value, - descriptionText: descriptionText, - translatable: true, - unit: temperatureScale - ] -} - -private Map getContactResult(value) { - log.debug "Contact: ${device.displayName} value = ${value}" - def descriptionText = value == 'open' ? '{{ device.displayName }} was opened' : '{{ device.displayName }} was closed' - sendEvent(name: 'contact', value: value, descriptionText: descriptionText, displayed: false, translatable: true) - sendEvent(name: 'status', value: value, descriptionText: descriptionText, translatable: true) -} - -private getAccelerationResult(numValue) { - log.debug "Acceleration" - def name = "acceleration" - def value - def descriptionText - - if ( numValue.endsWith("1") ) { - value = "active" - descriptionText = '{{ device.displayName }} was active' - } else { - value = "inactive" - descriptionText = '{{ device.displayName }} was inactive' - } - - def isStateChange = isStateChange(device, name, value) - return [ - name: name, - value: value, - descriptionText: descriptionText, - isStateChange: isStateChange, - translatable: true - ] -} - -/** - * PING is used by Device-Watch in attempt to reach the Device - * */ -def ping() { - return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level -} - -def refresh() { - log.debug "Refreshing Values " - - def refreshCmds = [] - - if (device.getDataValue("manufacturer") == "SmartThings") { - log.debug "Refreshing Values for manufacturer: SmartThings " - /* These values of Motion Threshold Multiplier(0x01) and Motion Threshold (0x0276) - seem to be giving pretty accurate results for the XYZ co-ordinates for this manufacturer. - Separating these out in a separate if-else because I do not want to touch Centralite part - as of now. - */ - refreshCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x01, [mfgCode: manufacturerCode]) - refreshCmds += zigbee.writeAttribute(0xFC02, 0x0002, 0x21, 0x0276, [mfgCode: manufacturerCode]) - } else { - refreshCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x02, [mfgCode: manufacturerCode]) - } - - //Common refresh commands - refreshCmds += zigbee.readAttribute(0x0402, 0x0000) + - zigbee.readAttribute(0x0001, 0x0020) + - zigbee.readAttribute(0xFC02, 0x0010, [mfgCode: manufacturerCode]) - - return refreshCmds + enrollResponse() -} - -def configure() { - // Device-Watch allows 3 check-in misses from device (plus 1 min lag time) - // enrolls with default periodic reporting until newer 5 min interval is confirmed - sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) - - log.debug "Configuring Reporting" - - // temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity - // battery minReport 30 seconds, maxReportTime 6 hrs by default - def configCmds = zigbee.batteryConfig() + - zigbee.temperatureConfig(30, 300) + - zigbee.configureReporting(0xFC02, 0x0010, 0x18, 10, 3600, 0x01, [mfgCode: manufacturerCode]) + - zigbee.configureReporting(0xFC02, 0x0012, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) + - zigbee.configureReporting(0xFC02, 0x0013, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) + - zigbee.configureReporting(0xFC02, 0x0014, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) - - return refresh() + configCmds -} - -private getEndpointId() { - new BigInteger(device.endpointId, 16).toString() -} - -def enrollResponse() { - log.debug "Sending enroll response" - String zigbeeEui = swapEndianHex(device.hub.zigbeeEui) - [ - //Resending the CIE in case the enroll request is sent before CIE is written - "zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200", - "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500", - //Enroll Response - "raw 0x500 {01 23 00 00 00}", "delay 200", - "send 0x${device.deviceNetworkId} 1 1", "delay 200" - ] -} - -private Map parseAxis(String description) { - def z = hexToSignedInt(description[0..3]) - def y = hexToSignedInt(description[10..13]) - def x = hexToSignedInt(description[20..23]) - def xyzResults = [x: x, y: y, z: z] - - if (device.getDataValue("manufacturer") == "SmartThings") { - // This mapping matches the current behavior of the Device Handler for the Centralite sensors - xyzResults.x = z - xyzResults.y = y - xyzResults.z = -x - } else { - // The axises reported by the Device Handler differ from the axises reported by the sensor - // This may change in the future - xyzResults.x = z - xyzResults.y = x - xyzResults.z = y - } - - log.debug "parseAxis -- ${xyzResults}" - - if (garageSensor == "Yes") - garageEvent(xyzResults.z) - - getXyzResult(xyzResults, description) -} - -private hexToSignedInt(hexVal) { - def unsignedVal = hexToInt(hexVal) - unsignedVal > 32767 ? unsignedVal - 65536 : unsignedVal -} - -def garageEvent(zValue) { - def absValue = zValue.abs() - def contactValue = null - def garageValue = null - if (absValue>900) { - contactValue = 'closed' - garageValue = 'garage-closed' - } - else if (absValue < 100) { - contactValue = 'open' - garageValue = 'garage-open' - } - if (contactValue != null){ - def descriptionText = contactValue == 'open' ? '{{ device.displayName }} was opened' :'{{ device.displayName }} was closed' - sendEvent(name: 'contact', value: contactValue, descriptionText: descriptionText, displayed:false, translatable: true) - sendEvent(name: 'status', value: garageValue, descriptionText: descriptionText, translatable: true) - } -} - -private Map getXyzResult(results, description) { - def name = "threeAxis" - def value = "${results.x},${results.y},${results.z}" - def linkText = getLinkText(device) - def descriptionText = "$linkText was $value" - def isStateChange = isStateChange(device, name, value) - - [ - name: name, - value: value, - unit: null, - linkText: linkText, - descriptionText: descriptionText, - handlerName: name, - isStateChange: isStateChange, - displayed: false - ] -} - -private getManufacturerCode() { - if (device.getDataValue("manufacturer") == "SmartThings") { - return "0x110A" - } else { - return "0x104E" - } -} - -private hexToInt(value) { - new BigInteger(value, 16) -} - -private hex(value) { - new BigInteger(Math.round(value).toString()).toString(16) -} - -private String swapEndianHex(String hex) { - reverseArray(hex.decodeHex()).encodeHex() -} - -private byte[] reverseArray(byte[] array) { - int i = 0; - int j = array.length - 1; - byte tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } - return array -} diff --git a/devicetypes/smartthings/zigbee-hue-bulb.src/zigbee-hue-bulb.groovy b/devicetypes/smartthings/zigbee-hue-bulb.src/zigbee-hue-bulb.groovy deleted file mode 100644 index 5d13492..0000000 --- a/devicetypes/smartthings/zigbee-hue-bulb.src/zigbee-hue-bulb.groovy +++ /dev/null @@ -1,168 +0,0 @@ -/** - * Copyright 2015 SmartThings - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License - * for the specific language governing permissions and limitations under the License. - * - */ - -//@Deprecated - Moved to zll-rgbw-bulb - -/* Philips Hue (via Zigbee) - -Capabilities: - Actuator - Color Control - Configuration - Polling - Refresh - Sensor - Switch - Switch Level - -Custom Commands: - setAdjustedColor - -*/ - -metadata { - definition (name: "Zigbee Hue Bulb", namespace: "smartthings", author: "SmartThings") { - capability "Switch Level" - capability "Actuator" - capability "Color Control" - capability "Switch" - capability "Configuration" - capability "Polling" - capability "Refresh" - capability "Sensor" - - command "setAdjustedColor" - - //fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,0300,1000", outClusters: "0019" - } - - // UI tile definitions - tiles(scale: 2) { - multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ - tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - } - tileAttribute ("device.level", key: "SLIDER_CONTROL") { - attributeState "level", action:"switch level.setLevel" - } - tileAttribute ("device.color", key: "COLOR_CONTROL") { - attributeState "color", action:"color control.setColor" - } - } - controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..6500)") { - state "colorTemperature", action:"color temperature.setColorTemperature" - } - valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "colorTemperature", label: '${currentValue} K' - } - standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { - state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" - } - - main(["switch"]) - details(["switch", "colorTempSliderControl", "colorTemp", "refresh"]) - } -} - -//Globals -private getATTRIBUTE_HUE() { 0x0000 } -private getATTRIBUTE_SATURATION() { 0x0001 } -private getHUE_COMMAND() { 0x00 } -private getSATURATION_COMMAND() { 0x03 } -private getCOLOR_CONTROL_CLUSTER() { 0x0300 } -private getATTRIBUTE_COLOR_TEMPERATURE() { 0x0007 } - -// Parse incoming device messages to generate events -def parse(String description) { - log.debug "description is $description" - - def finalResult = zigbee.getEvent(description) - if (finalResult) { - log.debug finalResult - sendEvent(finalResult) - } - else { - def zigbeeMap = zigbee.parseDescriptionAsMap(description) - log.trace "zigbeeMap : $zigbeeMap" - - if (zigbeeMap?.clusterInt == COLOR_CONTROL_CLUSTER) { - if(zigbeeMap.attrInt == ATTRIBUTE_HUE){ //Hue Attribute - def hueValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 360) - sendEvent(name: "hue", value: hueValue, displayed:false) - } - else if(zigbeeMap.attrInt == ATTRIBUTE_SATURATION){ //Saturation Attribute - def saturationValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 100) - sendEvent(name: "saturation", value: saturationValue, displayed:false) - } - } - else { - log.info "DID NOT PARSE MESSAGE for description : $description" - } - } -} - -def on() { - zigbee.on() + ["delay 1500"] + zigbee.onOffRefresh() -} - -def off() { - zigbee.off() + ["delay 1500"] + zigbee.onOffRefresh() -} - -def refresh() { - refreshAttributes() + configureAttributes() -} - -def poll() { - refreshAttributes() -} - -def configure() { - log.debug "Configuring Reporting and Bindings." - configureAttributes() + refreshAttributes() -} - -def configureAttributes() { - zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) -} - -def refreshAttributes() { - zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) -} - -def setColorTemperature(value) { - zigbee.setColorTemperature(value) + ["delay 1500"] + zigbee.colorTemperatureRefresh() -} - -def setLevel(value) { - zigbee.setLevel(value) + ["delay 1500"] + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report -} - -def setColor(value){ - log.trace "setColor($value)" - zigbee.on() + setHue(value.hue) + ["delay 300"] + setSaturation(value.saturation) + ["delay 2000"] + refreshAttributes() -} - -def setHue(value) { - def scaledHueValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2) - zigbee.command(COLOR_CONTROL_CLUSTER, HUE_COMMAND, scaledHueValue, "00", "0500") + ["delay 1500"] + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) //payload-> hue value, direction (00-> shortest distance), transition time (1/10th second) (0500 in U16 reads 5) -} - -def setSaturation(value) { - def scaledSatValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2) - zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") + ["delay 1500"] + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) //payload-> sat value, transition time -}