diff --git a/devicetypes/axis/axis-gear-st.src/axis-gear-st.groovy b/devicetypes/axis/axis-gear-st.src/axis-gear-st.groovy index 1c4f0b1199a..c32b0a394b2 100644 --- a/devicetypes/axis/axis-gear-st.src/axis-gear-st.groovy +++ b/devicetypes/axis/axis-gear-st.src/axis-gear-st.groovy @@ -84,7 +84,7 @@ metadata { state "default", label: "Preset", action:"presetPosition", icon:"st.Home.home2" } preferences { - input "preset", "number", title: "Preset percentage (1-100) [Default - 50%]", defaultValue: 50, required: false, displayDuringSetup: true, range:"1..100" + input "preset", "number", title: "Preset position", description: "Set the window shade preset position", defaultValue: 50, required: false, displayDuringSetup: true, range:"1..100" } main(["main"]) @@ -416,4 +416,4 @@ private Map parseReportAttributeMessage(String description) { log.debug "parseReportAttributeMessage() --- ignoring attribute" } return resultMap -} \ No newline at end of file +} diff --git a/devicetypes/fibargroup/fibaro-motion-sensor-zw5.src/fibaro-motion-sensor-zw5.groovy b/devicetypes/fibargroup/fibaro-motion-sensor-zw5.src/fibaro-motion-sensor-zw5.groovy index 0d84c708766..30a6ee8946f 100644 --- a/devicetypes/fibargroup/fibaro-motion-sensor-zw5.src/fibaro-motion-sensor-zw5.groovy +++ b/devicetypes/fibargroup/fibaro-motion-sensor-zw5.src/fibaro-motion-sensor-zw5.groovy @@ -272,10 +272,6 @@ def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) { def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) { logging("${device.displayName} woke up", "debug") def cmds = [] - if (state.wakeUpInterval?.state == "notSynced" && state.wakeUpInterval?.value != null) { - cmds << zwave.wakeUpV2.wakeUpIntervalSet(seconds: state.wakeUpInterval.value as Integer, nodeid: zwaveHubNodeId) - state.wakeUpInterval.state = "synced" - } def event = createEvent(descriptionText: "${device.displayName} woke up", displayed: false) cmds << encap(zwave.batteryV1.batteryGet()) cmds << "delay 500" diff --git a/devicetypes/smartthings/ecosmart-4button-remote.src/ecosmart-4button-remote.groovy b/devicetypes/smartthings/ecosmart-4button-remote.src/ecosmart-4button-remote.groovy new file mode 100644 index 00000000000..15f552c1f13 --- /dev/null +++ b/devicetypes/smartthings/ecosmart-4button-remote.src/ecosmart-4button-remote.groovy @@ -0,0 +1,206 @@ +/* + * Copyright 2020 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. + */ + +import groovy.json.JsonOutput +import physicalgraph.zigbee.zcl.DataType + +metadata { + definition (name: "EcoSmart 4-button Remote", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.remotecontroller", mcdSync: true, runLocally: false, executeCommandsLocally: false, mnmn: "SmartThings", vid: "generic-4-button") { + capability "Actuator" + capability "Battery" + capability "Button" + capability "Holdable Button" + capability "Configuration" + capability "Sensor" + capability "Health Check" + + fingerprint inClusters: "0000, 0001, 0003, 1000, FD01", outClusters: "0003, 0004, 0006, 0008, 0019, 0300, 1000", manufacturer: "LDS", model: "ZBT-CCTSwitch-D0001", deviceJoinName: "EcoSmart 4-button remote" + } + + tiles { + standardTile("button", "device.button", width: 2, height: 2) { + state "default", label: "", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffffff" + state "button 1 pushed", label: "pushed #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#00A0DC" + } + + valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) { + state "battery", label:'${currentValue}% battery', unit:"" + } + + main (["button"]) + details(["button", "battery"]) + } +} + +private getCLUSTER_GROUPS() { 0x0004 } + +private channelNumber(String dni) { + dni.split(":")[-1] as Integer +} + +private getButtonName(buttonNum) { + return "${device.displayName} " + "Button ${buttonNum}" +} + +private void createChildButtonDevices(numberOfButtons) { + state.oldLabel = device.label + + log.debug "Creating $numberOfButtons children" + + for (i in 1..numberOfButtons) { + log.debug "Creating child $i" + def child = addChildDevice("Child Button", "${device.deviceNetworkId}:${i}", device.hubId, + [completedSetup: true, label: getButtonName(i), + isComponent: true, componentName: "button$i", componentLabel: "Button ${i}"]) + + child.sendEvent(name: "supportedButtonValues", value: ["pushed"].encodeAsJSON(), displayed: false) + child.sendEvent(name: "numberOfButtons", value: 1, displayed: false) + child.sendEvent(name: "button", value: "pushed", data: [buttonNumber: 1], displayed: false) + } +} + +def installed() { + def numberOfButtons = 4 + state.ignoreNextButton3 = false + + createChildButtonDevices(numberOfButtons) + + sendEvent(name: "supportedButtonValues", value: ["pushed"].encodeAsJSON(), displayed: false) + sendEvent(name: "numberOfButtons", value: numberOfButtons, displayed: false) + numberOfButtons.times { + sendEvent(name: "button", value: "pushed", data: [buttonNumber: it+1], displayed: false) + } + + // These devices don't report regularly so they should only go OFFLINE when Hub is OFFLINE + sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "zigbee", scheme:"untracked"]), displayed: false) +} + +def updated() { + if (childDevices && device.label != state.oldLabel) { + childDevices.each { + def newLabel = getButtonName(channelNumber(it.deviceNetworkId)) + it.setLabel(newLabel) + } + state.oldLabel = device.label + } +} + +def configure() { + log.debug "Configuring device ${device.getDataValue("model")}" + + def cmds = zigbee.configureReporting(zigbee.POWER_CONFIGURATION_CLUSTER, 0x21, DataType.UINT8, 30, 21600, 0x01) + + zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x21) + + zigbee.addBinding(zigbee.ONOFF_CLUSTER) + + // This device doesn't report a binding to this group but will send all messages to this group ID + addHubToGroup(0x4003) + + + cmds +} + +def parse(String description) { + log.debug "Parsing message from device: '$description'" + def event = zigbee.getEvent(description) + if (event) { + log.debug "Creating event: ${event}" + sendEvent(event) + } else { + if ((description?.startsWith("catchall:")) || (description?.startsWith("read attr -"))) { + def descMap = zigbee.parseDescriptionAsMap(description) + if (descMap.clusterInt == zigbee.POWER_CONFIGURATION_CLUSTER && descMap.attrInt == 0x0021) { + event = getBatteryEvent(zigbee.convertHexToInt(descMap.value)) + } else if (descMap.clusterInt == zigbee.ONOFF_CLUSTER || + descMap.clusterInt == zigbee.LEVEL_CONTROL_CLUSTER || + descMap.clusterInt == zigbee.COLOR_CONTROL_CLUSTER) { + event = getButtonEvent(descMap) + } + } + + def result = [] + if (event) { + log.debug "Creating event: ${event}" + result = createEvent(event) + } + + return result + } +} + +private Map getBatteryEvent(value) { + def result = [:] + result.value = value / 2 + result.name = 'battery' + result.descriptionText = "${device.displayName} battery was ${result.value}%" + return result +} + +private sendButtonEvent(buttonNumber, buttonState) { + def child = childDevices?.find { channelNumber(it.deviceNetworkId) == buttonNumber } + + if (child) { + def descriptionText = "$child.displayName was $buttonState" // TODO: Verify if this is needed, and if capability template already has it handled + + child?.sendEvent([name: "button", value: buttonState, data: [buttonNumber: 1], descriptionText: descriptionText, isStateChange: true]) + } else { + log.debug "Child device $buttonNumber not found!" + } +} + +private Map getButtonEvent(Map descMap) { + def buttonState = "" + def buttonNumber = 0 + Map result = [:] + + // Button 1 + if (descMap.clusterInt == zigbee.ONOFF_CLUSTER) { + buttonNumber = 1 + + // Button 2 + } else if (descMap.clusterInt == zigbee.LEVEL_CONTROL_CLUSTER && + (descMap.commandInt == 0x00 || descMap.commandInt == 0x01)) { + buttonNumber = 2 + + // Button 3 + } else if (descMap.clusterInt == zigbee.COLOR_CONTROL_CLUSTER) { + if (descMap.commandInt == 0x0A || (descMap.commandInt == 0x4B && descMap.data[0] != "00")) { + if (state.ignoreNextButton3) { + // button 4 sends 2 cmds; one is a button 3 cmd. We want to ignore these specific cmds + state.ignoreNextButton3 = false + } else { + buttonNumber = 3 + } + } + + // Button 4 + } else if (descMap.clusterInt == zigbee.LEVEL_CONTROL_CLUSTER && + descMap.commandInt == 0x04) { + // remember to ignore the next button 3 message we get + state.ignoreNextButton3 = true + buttonNumber = 4 + } + + + if (buttonNumber != 0) { + // Create and send component event + sendButtonEvent(buttonNumber, "pushed") + } + result +} + +private List addHubToGroup(Integer groupAddr) { + ["st cmd 0x0000 0x01 ${CLUSTER_GROUPS} 0x00 {${zigbee.swapEndianHex(zigbee.convertToHexString(groupAddr,4))} 00}", + "delay 200"] +} \ No newline at end of file diff --git a/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy b/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy index 1d1fb7d814f..cc604687ac5 100644 --- a/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy +++ b/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy @@ -34,6 +34,7 @@ metadata { fingerprint profileId: "0010", inClusters: "0000 0003 0004 0005 0006 0008 0702 0B05", outClusters: "0019", manufacturer: "innr", model: "SP 120", deviceJoinName: "Innr Smart Plug" fingerprint profileId: "0104", inClusters: "0000,0002,0003,0004,0005,0006,0009,0B04,0702", outClusters: "0019,000A,0003,0406", manufacturer: "Aurora", model: "SmartPlug51AU", deviceJoinName: "Aurora SmartPlug" fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0702,0B04,0B05,FC03", outClusters: "0019", manufacturer: "CentraLite", model: "3210-L", deviceJoinName: "Iris Smart Plug" + fingerprint profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0006,0B04,0B05,0702", outClusters: "0003,000A,0B05,0019", manufacturer: " Sercomm Corp.", model: "SZ-ESW01-AU", deviceJoinName: "Sercomm Smart Power Plug" } // simulator metadata diff --git a/devicetypes/smartthings/smartsense-garage-door-multi.src/smartsense-garage-door-multi.groovy b/devicetypes/smartthings/smartsense-garage-door-multi.src/smartsense-garage-door-multi.groovy index cffa8d9d9af..ce68f81bb9d 100644 --- a/devicetypes/smartthings/smartsense-garage-door-multi.src/smartsense-garage-door-multi.groovy +++ b/devicetypes/smartthings/smartsense-garage-door-multi.src/smartsense-garage-door-multi.groovy @@ -25,8 +25,6 @@ metadata { capability "Sensor" capability "Battery" - attribute "status", "string" - attribute "door", "string" } simulator { @@ -48,18 +46,12 @@ metadata { } tiles(scale: 2) { - multiAttributeTile(name:"status", type: "generic", width: 6, height: 4){ - tileAttribute ("device.status", key: "PRIMARY_CONTROL") { - attributeState "closed", label:'${name}', icon:"st.doors.garage.garage-closed", backgroundColor:"#00A0DC", nextState:"opening" - attributeState "open", label:'${name}', icon:"st.doors.garage.garage-open", backgroundColor:"#e86d13", nextState:"closing" - attributeState "opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#e86d13" - attributeState "closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#00A0DC" + multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){ + tileAttribute ("device.contact", key: "PRIMARY_CONTROL") { + attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13" + attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc" } } - standardTile("contact", "device.contact", width: 2, height: 2) { - state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13") - state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00A0DC") - } standardTile("acceleration", "device.acceleration", decoration: "flat", width: 2, height: 2) { state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#00A0DC") state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff") @@ -74,8 +66,8 @@ metadata { state "battery", label:'${currentValue}% battery', unit:"" } - main(["status", "contact", "acceleration"]) - details(["status", "contact", "acceleration", "temperature", "3axis", "battery"]) + main(["contact", "acceleration"]) + details(["contact", "acceleration", "temperature", "3axis", "battery"]) } preferences { @@ -217,14 +209,10 @@ private List parseOrientationMessage(String description) { if (absValueZ > 825) { results << createEvent(name: "contact", value: "open", unit: "") - results << createEvent(name: "status", value: "open", unit: "") - results << createEvent(name: "door", value: "open", unit: "") log.debug "STATUS: open" } else if (absValueZ < 100) { results << createEvent(name: "contact", value: "closed", unit: "") - results << createEvent(name: "status", value: "closed", unit: "") - results << createEvent(name: "door", value: "closed", unit: "") log.debug "STATUS: closed" } diff --git a/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy b/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy index 024400b0097..56b6fee3c09 100755 --- a/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy +++ b/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy @@ -33,6 +33,7 @@ metadata { fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-G", deviceJoinName: "Centralite Water Sensor" fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "moisturev4", deviceJoinName: "Water Leak Sensor" fingerprint inClusters: "0000,0001,0003,0020,0402,0500", outClusters: "0019", manufacturer: "Samjin", model: "water", deviceJoinName: "Water Leak Sensor" + fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "Sercomm Corp.", model: "SZ-WTD03", deviceJoinName: "Sercomm Water Leak Detector" } simulator { diff --git a/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy b/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy index e71d5cf9c2d..f6c9513191a 100755 --- a/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy +++ b/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy @@ -35,7 +35,6 @@ metadata { fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500,FC02", outClusters: "0019", manufacturer: "SmartThings", model: "multiv4", deviceJoinName: "Multipurpose Sensor" fingerprint inClusters: "0000,0001,0003,0020,0402,0500,FC02", outClusters: "0019", manufacturer: "Samjin", model: "multi", deviceJoinName: "Multipurpose Sensor" - attribute "status", "string" } simulator { @@ -73,18 +72,12 @@ metadata { } 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: "#e86d13" - attributeState "closed", label: 'Closed', icon: "st.contact.contact.closed", backgroundColor: "#00a0dc" - attributeState "garage-open", label: 'Open', icon: "st.doors.garage.garage-open", backgroundColor: "#e86d13" - attributeState "garage-closed", label: 'Closed', icon: "st.doors.garage.garage-closed", backgroundColor: "#00a0dc" + multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4) { + tileAttribute("device.contact", key: "PRIMARY_CONTROL") { + state("open", label: 'Open', icon: "st.contact.contact.open", backgroundColor: "#e86d13") + state("closed", label: 'Closed', icon: "st.contact.contact.closed", backgroundColor: "#00a0dc") } } - standardTile("contact", "device.contact", width: 2, height: 2) { - state("open", label: 'Open', icon: "st.contact.contact.open", backgroundColor: "#e86d13") - state("closed", label: 'Closed', icon: "st.contact.contact.closed", backgroundColor: "#00a0dc") - } standardTile("acceleration", "device.acceleration", width: 2, height: 2) { state("active", label: 'Active', icon: "st.motion.acceleration.active", backgroundColor: "#00a0dc") state("inactive", label: 'Inactive', icon: "st.motion.acceleration.inactive", backgroundColor: "#cccccc") @@ -110,8 +103,8 @@ metadata { } - main(["status", "acceleration", "temperature"]) - details(["status", "acceleration", "temperature", "battery", "refresh"]) + main(["contact", "acceleration", "temperature"]) + details(["contact", "acceleration", "temperature", "battery", "refresh"]) } } @@ -270,8 +263,7 @@ private List translateZoneStatus(ZoneStatus zs) { def value = zs.isAlarm1Set() ? 'open' : 'closed' log.debug "Contact: ${device.displayName} value = ${value}" def descriptionText = value == 'open' ? '{{ device.displayName }} was opened' : '{{ device.displayName }} was closed' - results << [name: 'contact', value: value, descriptionText: descriptionText, displayed: false, translatable: true] - results << [name: 'status', value: value, descriptionText: descriptionText, translatable: true] + results << [name: 'contact', value: value, descriptionText: descriptionText, translatable: true] } return results @@ -353,18 +345,14 @@ List garageEvent(zValue) { List results = [] 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' - results << [name: 'contact', value: contactValue, descriptionText: descriptionText, displayed: false, translatable: true] - results << [name: 'status', value: garageValue, descriptionText: descriptionText, translatable: true] + results << [name: 'contact', value: contactValue, descriptionText: descriptionText, translatable: true] } results } @@ -450,26 +438,6 @@ def configure() { return configCmds } -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) - } - } -} - private hexToSignedInt(hexVal) { if (!hexVal) { return null diff --git a/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy b/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy index 673287ef2c9..6a7ffb57250 100644 --- a/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy +++ b/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy @@ -22,8 +22,6 @@ metadata { capability "Battery" fingerprint profileId: "FC01", deviceId: "0139" - - attribute "status", "string" } simulator { @@ -121,17 +119,6 @@ private List parseSingleMessage(description) { displayed: displayed(description, isStateChange) ) - results << createEvent( - name: "status", - value: value, - unit: null, - linkText: linkText, - descriptionText: descriptionText, - handlerName: handlerName, - isStateChange: isStateChange, - displayed: displayed(description, isStateChange) - ) - results } @@ -297,19 +284,7 @@ private List getContactResult(part, description) { linkText: linkText, descriptionText: descriptionText, handlerName: handlerName, - isStateChange: isStateChange, - displayed:false - ) - - results << createEvent( - name: "status", - value: value, - unit: null, - linkText: linkText, - descriptionText: descriptionText, - handlerName: handlerName, - isStateChange: isStateChange, - displayed: displayed(description, isStateChange) + isStateChange: isStateChange ) results diff --git a/devicetypes/smartthings/zigbee-dimmer-with-motion-sensor.src/zigbee-dimmer-with-motion-sensor.groovy b/devicetypes/smartthings/zigbee-dimmer-with-motion-sensor.src/zigbee-dimmer-with-motion-sensor.groovy index 8f9147a89b5..df47180a40d 100644 --- a/devicetypes/smartthings/zigbee-dimmer-with-motion-sensor.src/zigbee-dimmer-with-motion-sensor.groovy +++ b/devicetypes/smartthings/zigbee-dimmer-with-motion-sensor.src/zigbee-dimmer-with-motion-sensor.groovy @@ -25,6 +25,7 @@ metadata { capability "Health Check" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0500, 0702, 0B05, FC01", outClusters: "0019", manufacturer: "sengled", model: "E13-N11", deviceJoinName: "Sengled Smart LED with Motion Sensor PAR38 Bulb" + fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05, FC01", outClusters: "0019", manufacturer: "sengled", model: "E13-A21", deviceJoinName: "Sengled LED Flood Light with Motion Sensor" } tiles(scale: 2) { diff --git a/devicetypes/smartthings/zigbee-dimmer.src/zigbee-dimmer.groovy b/devicetypes/smartthings/zigbee-dimmer.src/zigbee-dimmer.groovy index acd8587ff9b..aa7ced58e71 100644 --- a/devicetypes/smartthings/zigbee-dimmer.src/zigbee-dimmer.groovy +++ b/devicetypes/smartthings/zigbee-dimmer.src/zigbee-dimmer.groovy @@ -100,6 +100,7 @@ metadata { fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E11-N14A", deviceJoinName: "Sengled Extra Bright Daylight" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E21-N13A", deviceJoinName: "Sengled Soft White" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E21-N14A", deviceJoinName: "Sengled Daylight" + fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E11-U21U31", deviceJoinName: "Sengled Element Touch" // SmartThings fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05, 1000, FEDC", outClusters: "000A, 0019", manufacturer: "LDS", model: "ZBT-DIMLight-GLS0006", deviceJoinName: "Smart Bulb" diff --git a/devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy b/devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy index e05626962c3..726ea633eac 100644 --- a/devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy +++ b/devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy @@ -44,6 +44,7 @@ metadata { fingerprint profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0009,0020,0101,0402,0B05,FDBD", outClusters: "000A,0019", manufacturer: "Kwikset", model: "SMARTCODE_DEADBOLT_10T", deviceJoinName: "Kwikset 10-Button Touch Deadbolt" fingerprint profileId: "0104", inClusters: "0000, 0003, 0101", manufacturer:"Kwikset", model:"Smartcode", deviceJoinName: "Kwikset Smartcode Lock" fingerprint profileId: "0104", inClusters: "0000, 0001, 0003, 0009, 0020, 0101, 0B05, FC00", outClusters: "000A, 0019", manufacturer: "Schlage", model: "BE468", deviceJoinName: "Schlage Connect Smart Deadbolt" + fingerprint profileId: "0104", inClusters: "0000,0001,0003,0009,000A,0101,0020,0B05", outClusters: "000A,0019", manufacturer: "Yale", model: "YDD-D4F0 TSDB", deviceJoinName: "Lockwood Smart Lock" } tiles(scale: 2) { diff --git a/devicetypes/smartthings/zigbee-non-holdable-button.src/zigbee-non-holdable-button.groovy b/devicetypes/smartthings/zigbee-non-holdable-button.src/zigbee-non-holdable-button.groovy index 5ccfca0ce9c..bbdd2104342 100755 --- a/devicetypes/smartthings/zigbee-non-holdable-button.src/zigbee-non-holdable-button.groovy +++ b/devicetypes/smartthings/zigbee-non-holdable-button.src/zigbee-non-holdable-button.groovy @@ -17,7 +17,7 @@ import physicalgraph.zigbee.clusters.iaszone.ZoneStatus import physicalgraph.zigbee.zcl.DataType metadata { - definition(name: "Zigbee Non-Holdable Button", namespace: "smartthings", author: "SmartThings", runLocally: false, mnmn: "SmartThings", vid: "generic-button-4", ocfDeviceType: "x.com.st.d.remotecontroller") { + definition(name: "Zigbee Non-Holdable Button", namespace: "smartthings", author: "SmartThings", runLocally: false, mnmn: "SmartThings", vid: "generic-button-2", ocfDeviceType: "x.com.st.d.remotecontroller") { capability "Configuration" capability "Battery" capability "Refresh" @@ -193,4 +193,4 @@ def configure() { return zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) + zigbee.enrollResponse() + zigbee.batteryConfig() -} \ No newline at end of file +} diff --git a/devicetypes/smartthings/zigbee-scene-keypad.src/zigbee-scene-keypad.groovy b/devicetypes/smartthings/zigbee-scene-keypad.src/zigbee-scene-keypad.groovy old mode 100755 new mode 100644 index d4b29993aa2..a13bd588f1d --- a/devicetypes/smartthings/zigbee-scene-keypad.src/zigbee-scene-keypad.groovy +++ b/devicetypes/smartthings/zigbee-scene-keypad.src/zigbee-scene-keypad.groovy @@ -18,7 +18,7 @@ import groovy.json.JsonOutput import physicalgraph.zigbee.zcl.DataType metadata { - definition (name: "Zigbee Scene Keypad", namespace: "smartthings", author: "SmartThings", mcdSync: true) { + definition (name: "Zigbee Scene Keypad", namespace: "smartthings", author: "SmartThings", mcdSync: true, ocfDeviceType: "x.com.st.d.remotecontroller") { capability "Actuator" capability "Button" capability "Configuration" @@ -104,7 +104,16 @@ def installed() { if (!childDevices) { addChildButtons(numberOfButtons) } - sendEvent(name: "supportedButtonValues", value: ["pushed"]) + if (childDevices) { + def event + for (def endpoint : 1..device.currentValue("numberOfButtons")) { + event = createEvent(name: "button", value: "pushed", isStateChange: true, displayed: false) + sendEventToChild(endpoint, event) + } + } + + sendEvent(name: "button", value: "pushed", isStateChange: true, displayed: false) + sendEvent(name: "supportedButtonValues", value: supportedButtonValues.encodeAsJSON(), displayed: false) } def updated() { @@ -116,19 +125,29 @@ def initialize() { } private addChildButtons(numberOfButtons) { - for (def i : 2..numberOfButtons) { + for (def endpoint : 2..numberOfButtons) { try { - String childDni = "${device.deviceNetworkId}:$i" - def componentLabel = (device.displayName.endsWith(' 1') ? device.displayName[0..-2] : device.displayName) + "${i}" - addChildDevice("Child Button", "${device.deviceNetworkId}:${i}", device.hubId, - [completedSetup: true, label: "${device.displayName} button ${i}", - isComponent: true, componentName: "button$i", componentLabel: "Button $i"]) - } catch (Exception e) { + String childDni = "${device.deviceNetworkId}:$endpoint" + def childLabel = (device.displayName.endsWith(' 1') ? device.displayName[0..-2] : device.displayName) + "${endpoint}" + def child = addChildDevice("Child Button", childDni, device.getHub().getId(), [ + completedSetup: true, + label : childLabel, + isComponent : true, + componentName : "button$endpoint", + componentLabel: "Button $endpoint" + ]) + child.sendEvent(name: "supportedButtonValues", value: supportedButtonValues.encodeAsJSON(), displayed: false) + } catch(Exception e) { log.debug "Exception: ${e}" } } } +private getSupportedButtonValues() { + def values = ["pushed"] + return values +} + private getChildCount() { if (device.getDataValue("model") == "0106-G") { return 6 diff --git a/devicetypes/smartthings/zigbee-thermostat.src/zigbee-thermostat.groovy b/devicetypes/smartthings/zigbee-thermostat.src/zigbee-thermostat.groovy index 2c92fa8976a..d7179584c90 100644 --- a/devicetypes/smartthings/zigbee-thermostat.src/zigbee-thermostat.groovy +++ b/devicetypes/smartthings/zigbee-thermostat.src/zigbee-thermostat.groovy @@ -146,7 +146,7 @@ private parseAttrMessage(description) { descMap.additionalAttrs.each { attrData << [cluster: descMap.clusterInt, attribute: it.attrInt, value: it.value] } - attrData.each { + attrData.findAll( {it.value != null} ).each { def map = [:] if (it.cluster == THERMOSTAT_CLUSTER) { if (it.attribute == LOCAL_TEMPERATURE) { diff --git a/devicetypes/smartthings/zigbee-window-shade-battery.src/zigbee-window-shade-battery.groovy b/devicetypes/smartthings/zigbee-window-shade-battery.src/zigbee-window-shade-battery.groovy index eaa82c214ba..fa1bd9f3ab4 100644 --- a/devicetypes/smartthings/zigbee-window-shade-battery.src/zigbee-window-shade-battery.groovy +++ b/devicetypes/smartthings/zigbee-window-shade-battery.src/zigbee-window-shade-battery.groovy @@ -210,7 +210,7 @@ def configure() { def cmds if (supportsLiftPercentage()) { - cmds = zigbee.configureReporting(CLUSTER_WINDOW_COVERING, ATTRIBUTE_POSITION_LIFT, DataType.UINT8, 0, 600, null) + cmds = zigbee.configureReporting(CLUSTER_WINDOW_COVERING, ATTRIBUTE_POSITION_LIFT, DataType.UINT8, 2, 600, null) } else { cmds = zigbee.levelConfig() } diff --git a/devicetypes/smartthings/zll-dimmer-bulb.src/zll-dimmer-bulb.groovy b/devicetypes/smartthings/zll-dimmer-bulb.src/zll-dimmer-bulb.groovy index 1b903686e07..a2aae4a5fe6 100644 --- a/devicetypes/smartthings/zll-dimmer-bulb.src/zll-dimmer-bulb.groovy +++ b/devicetypes/smartthings/zll-dimmer-bulb.src/zll-dimmer-bulb.groovy @@ -34,6 +34,7 @@ metadata { fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05, 1000", outClusters: "0005, 0019, 0020, 1000", manufacturer: "IKEA of Sweden", model: "TRADFRI bulb E17 W op/ch 400lm", deviceJoinName: "IKEA TRÅDFRI LED Bulb" fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05, 1000", outClusters: "0005, 0019, 0020, 1000", manufacturer: "IKEA of Sweden", model: "TRADFRI bulb GU10 W 400lm", deviceJoinName: "IKEA TRÅDFRI LED Bulb" fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05, 1000", outClusters: "0005, 0019, 0020, 1000", manufacturer: "IKEA of Sweden", model: "TRADFRI bulb E27 W opal 1000lm", deviceJoinName: "IKEA TRÅDFRI LED Bulb" + fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05, 1000", outClusters: "0005, 0019, 0020, 1000", manufacturer: "IKEA of Sweden", model: "TRADFRI bulb E26 W opal 1000lm", deviceJoinName: "IKEA TRÅDFRI LED Bulb" fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05, 1000", outClusters: "0005, 0019, 0020, 1000", manufacturer: "IKEA of Sweden", model: "TRADFRI bulb E14 W op/ch 400lm", deviceJoinName: "IKEA TRÅDFRI LED Bulb" fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05, 1000", outClusters: "0005, 0019, 0020, 1000", manufacturer: "IKEA of Sweden", model: "TRADFRI transformer 10W", deviceJoinName: "IKEA TRÅDFRI Driver for wireless control 10W" fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05, 1000", outClusters: "0005, 0019, 0020, 1000", manufacturer: "IKEA of Sweden", model: "TRADFRI Driver 10W", deviceJoinName: "IKEA TRÅDFRI Driver for wireless control 10W" @@ -167,4 +168,4 @@ def configure() { def updated() { log.debug "updated()" configureHealthCheck() -} \ No newline at end of file +} diff --git a/devicetypes/smartthings/zll-rgbw-bulb.src/zll-rgbw-bulb.groovy b/devicetypes/smartthings/zll-rgbw-bulb.src/zll-rgbw-bulb.groovy index 85ff53e22b8..f64533b3622 100644 --- a/devicetypes/smartthings/zll-rgbw-bulb.src/zll-rgbw-bulb.groovy +++ b/devicetypes/smartthings/zll-rgbw-bulb.src/zll-rgbw-bulb.groovy @@ -39,7 +39,7 @@ metadata { fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, FFFF", outClusters: "0019", manufacturer: "Megaman", model: "ZLL-ExtendedColor", deviceJoinName: "INGENIUM ZB RGBW Light" // Innr - fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300", outClusters: "0019", manufacturer: "innr", model: "RB 185 C", deviceJoinName: "Innr Smart Bulb Color" + fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300", outClusters: "0019", manufacturer: "innr", model: "RB 185 C", deviceJoinName: "Innr Smart Bulb Color", mnmn: "SmartThings", vid: "generic-rgbw-color-bulb-1800K-6500K" fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300", outClusters: "0019", manufacturer: "innr", model: "FL 130 C", deviceJoinName: "Innr Flex Light Color" // OSRAM @@ -49,7 +49,7 @@ metadata { fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,0300,1000,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Flex RGBW", deviceJoinName: "OSRAM SMART+ Flex RGBW" fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,0300,1000,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Gardenpole RGBW-Lightify", deviceJoinName: "OSRAM SMART+ Gardenpole RGBW" fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,0300,1000,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY Outdoor Flex RGBW", deviceJoinName: "OSRAM SMART+ Outdoor Flex RGBW" - fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,0300,1000,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY Indoor Flex RGBW", deviceJoinName: "OSRAM SMART+ Indoor Flex RGBW", mnmn:"SmartThings", vid: "generic-rgbw-color-bulb-2000K-6500K" + fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,0300,1000,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY Indoor Flex RGBW", deviceJoinName: "OSRAM SMART+ Indoor Flex RGBW", mnmn: "SmartThings", vid: "generic-rgbw-color-bulb-2000K-6500K" // Philips Hue fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,0300,1000", outClusters: "0019", manufacturer: "Philips", model: "LCT001", deviceJoinName: "Philips Hue A19" diff --git a/devicetypes/smartthings/zwave-lock-without-codes.src/zwave-lock-without-codes.groovy b/devicetypes/smartthings/zwave-lock-without-codes.src/zwave-lock-without-codes.groovy index 8ab6472749e..73958a17af7 100644 --- a/devicetypes/smartthings/zwave-lock-without-codes.src/zwave-lock-without-codes.groovy +++ b/devicetypes/smartthings/zwave-lock-without-codes.src/zwave-lock-without-codes.groovy @@ -419,6 +419,103 @@ private def handleBatteryAlarmReport(cmd) { result } +/** + * Responsible for handling AlarmReport commands which are ignored by Access & Burglar handlers + * + * @param cmd: The AlarmReport command to be parsed + * + * @return The event(s) to be sent out + * + */ +private def handleAlarmReportUsingAlarmType(cmd) { + log.trace "[DTH] Executing 'handleAlarmReportUsingAlarmType' with cmd = $cmd" + def result = [] + def map = null + def deviceName = device.displayName + lockCodes = loadLockCodes() + switch(cmd.alarmType) { + case 9: + case 17: + map = [ name: "lock", value: "unknown", descriptionText: "Unknown state" ] + break + case 16: // Note: for levers this means it's unlocked, for non-motorized deadbolt, it's just unsecured and might not get unlocked + case 19: // Unlocked with keypad + map = [ name: "lock", value: "unlocked" , method: "keypad"] + map.descriptionText = "Unlocked by keypad" + break + case 18: // Locked with keypad + codeID = readCodeSlotId(cmd) + map = [ name: "lock", value: "locked" ] + map.descriptionText = "Locked by keypad" + map.data = [ method: "keypad" ] + break + case 21: // Manually locked + map = [ name: "lock", value: "locked", data: [ method: (cmd.alarmLevel == 2) ? "keypad" : "manual" ] ] + map.descriptionText = "Locked manually" + break + case 22: // Manually unlocked + map = [ name: "lock", value: "unlocked", data: [ method: "manual" ] ] + map.descriptionText = "Unlocked manually" + break + case 23: + map = [ name: "lock", value: "unknown", descriptionText: "Unknown state" ] + map.data = [ method: "command" ] + break + case 24: // Locked by command + map = [ name: "lock", value: "locked", data: [ method: "command" ] ] + map.descriptionText = "Locked" + break + case 25: // Unlocked by command + map = [ name: "lock", value: "unlocked", data: [ method: "command" ] ] + map.descriptionText = "Unlocked" + break + case 26: + map = [ name: "lock", value: "unknown", descriptionText: "Unknown state" ] + map.data = [ method: "auto" ] + break + case 27: // Auto locked + map = [ name: "lock", value: "locked", data: [ method: "auto" ] ] + map.descriptionText = "Auto locked" + break + case 130: // Batteries replaced + map = [ descriptionText: "Batteries replaced", isStateChange: true ] + break + case 161: // Tamper Alarm + if (cmd.alarmLevel == 2) { + map = [ name: "tamper", value: "detected", descriptionText: "Front escutcheon removed", isStateChange: true ] + } + break + case 167: // Low Battery Alarm + if (!state.lastbatt || now() - state.lastbatt > 12*60*60*1000) { + map = [ descriptionText: "Battery low", isStateChange: true ] + result << response(secure(zwave.batteryV1.batteryGet())) + } else { + map = [ name: "battery", value: device.currentValue("battery"), descriptionText: "Battery low", isStateChange: true ] + } + break + case 168: // Critical Battery Alarms + map = [ name: "battery", value: 1, descriptionText: "Battery level critical", displayed: true ] + break + case 169: // Battery too low to operate + map = [ name: "battery", value: 0, descriptionText: "Battery too low to operate lock", isStateChange: true, displayed: true ] + break + default: + map = [ displayed: false, descriptionText: "Alarm event ${cmd.alarmType} level ${cmd.alarmLevel}" ] + break + } + + if (map) { + if (map.data) { + map.data.lockName = deviceName + } else { + map.data = [ lockName: deviceName ] + } + result << createEvent(map) + } + result = result.flatten() + result +} + /** * Responsible for parsing BatteryReport command * diff --git a/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy b/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy index 23e0a3dd6cc..05352e06e52 100644 --- a/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy +++ b/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy @@ -40,7 +40,7 @@ metadata { fingerprint mfr: "0129", prod: "6F01", model: "0001", deviceJoinName: "Yale External Siren" fingerprint mfr: "0060", prod: "000C", model: "0002", deviceJoinName: "Everspring Outdoor Solar Siren", vid: "generic-siren-12" fingerprint mfr: "0154", prod: "0004", model: "0002", deviceJoinName: "POPP Solar Outdoor Siren", vid: "generic-siren-12" - fingerprint mfr: "0109", prod: "2005", model: "0518", deviceJoinName: "Vision Outdoor Siren" + fingerprint mfr: "0109", prod: "2005", model: "0518", deviceJoinName: "Vision Outdoor Siren", vid: "generic-siren-12" fingerprint mfr: "0258", prod: "0003", model: "6088", deviceJoinName: "NEO Coolcam Siren Alarm"//AU } @@ -77,13 +77,13 @@ metadata { // Yale siren only preferences { - input name: "alarmLength", type: "number", title: "Alarm length", range: "1..10" + input name: "alarmLength", type: "number", title: "Alarm length", description: "This setting does not apply to all devices", range: "1..10" // defaultValue: 10 - input name: "alarmLEDflash", type: "bool", title: "Alarm LED flash" + input name: "alarmLEDflash", type: "bool", title: "Alarm LED flash", description: "This setting does not apply to all devices" // defaultValue: false - input name: "comfortLED", type: "number", title: "Comfort LED (x10 sec.)", range: "0..25" + input name: "comfortLED", type: "number", title: "Comfort LED (x10 sec.)", description: "This setting does not apply to all devices", range: "0..25" // defaultValue: 0 - input name: "tamper", type: "bool", title: "Tamper alert" + input name: "tamper", type: "bool", title: "Tamper alert", description: "This setting does not apply to all devices" // defaultValue: false } diff --git a/devicetypes/smartthings/zwave-water-sensor.src/zwave-water-sensor.groovy b/devicetypes/smartthings/zwave-water-sensor.src/zwave-water-sensor.groovy index ebfbe22ee10..5534fd42c28 100644 --- a/devicetypes/smartthings/zwave-water-sensor.src/zwave-water-sensor.groovy +++ b/devicetypes/smartthings/zwave-water-sensor.src/zwave-water-sensor.groovy @@ -29,6 +29,7 @@ metadata { fingerprint mfr: "0258", prod: "0003", model: "1085", deviceJoinName: "NEO Coolcam Water Sensor" //NAS-WS03ZE fingerprint mfr: "0086", prod: "0102", model: "007A", deviceJoinName: "Aeotec Water Sensor 6" //US fingerprint mfr: "0086", prod: "0002", model: "007A", deviceJoinName: "Aeotec Water Sensor 6" //EU + fingerprint mfr: "0086", prod: "0202", model: "007A", deviceJoinName: "Aeotec Water Sensor 6" //AU fingerprint mfr: "000C", prod: "0201", model: "000A", deviceJoinName: "HomeSeer LS100+ Water Sensor" } diff --git a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy index 7015b52076c..319284a9089 100644 --- a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy +++ b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy @@ -80,7 +80,7 @@ metadata { } preferences { - input "preset", "number", title: "Preset position", defaultValue: 50, range: "1..100", required: false, displayDuringSetup: false + input "preset", "number", title: "Preset position", description: "Set the window shade preset position", defaultValue: 50, range: "1..100", required: false, displayDuringSetup: false } main(["windowShade"]) @@ -246,4 +246,4 @@ def refresh() { zwave.switchMultilevelV1.switchMultilevelGet().format(), zwave.batteryV1.batteryGet().format() ], 1500) -} \ No newline at end of file +}