diff --git a/devicetypes/fibargroup/fibaro-wall-plug-eu-zw5.src/fibaro-wall-plug-eu-zw5.groovy b/devicetypes/fibargroup/fibaro-wall-plug-eu-zw5.src/fibaro-wall-plug-eu-zw5.groovy index 3b977448e5c..76d6edc2f46 100644 --- a/devicetypes/fibargroup/fibaro-wall-plug-eu-zw5.src/fibaro-wall-plug-eu-zw5.groovy +++ b/devicetypes/fibargroup/fibaro-wall-plug-eu-zw5.src/fibaro-wall-plug-eu-zw5.groovy @@ -12,8 +12,7 @@ metadata { command "reset" - fingerprint mfr: "010F", prod: "0602", model: "1001", deviceJoinName: "Fibaro Wall Plug EU ZW5" // EU - fingerprint mfr: "010F", prod: "1801", model: "1000", deviceJoinName: "Fibaro Wall Plug ZW5" // UK + fingerprint mfr: "010F", prod: "0602", model: "1001", deviceJoinName: "Fibaro Wall Plug EU ZW5" fingerprint deviceId: "0x1001", inClusters:"0x5E,0x22,0x59,0x56,0x7A,0x32,0x71,0x73,0x31,0x85,0x70,0x72,0x5A,0x8E,0x25,0x86" } diff --git a/devicetypes/fibargroup/fibaro-wall-plug-us-zw5.src/fibaro-wall-plug-us-zw5.groovy b/devicetypes/fibargroup/fibaro-wall-plug-us-zw5.src/fibaro-wall-plug-us-zw5.groovy index dfbddfbed9e..80b541b1e37 100644 --- a/devicetypes/fibargroup/fibaro-wall-plug-us-zw5.src/fibaro-wall-plug-us-zw5.groovy +++ b/devicetypes/fibargroup/fibaro-wall-plug-us-zw5.src/fibaro-wall-plug-us-zw5.groovy @@ -164,6 +164,7 @@ def configure() { def ping() { log.debug "ping..()" + childRefresh() refresh() //response(refresh()) } @@ -510,4 +511,4 @@ private parameterMap() {[ 8: "Cyan", 9: "Magenta" ], def: "0", title: "Ring LED color when off", descr: "Ring LED colour when the device is OFF.", defValDescr: "Off (Default)"] -]} \ No newline at end of file +]} diff --git a/devicetypes/smartthings/nyce-motion-sensor.src/nyce-motion-sensor.groovy b/devicetypes/smartthings/nyce-motion-sensor.src/nyce-motion-sensor.groovy index 2e99485aefa..f0d56ab66d8 100644 --- a/devicetypes/smartthings/nyce-motion-sensor.src/nyce-motion-sensor.groovy +++ b/devicetypes/smartthings/nyce-motion-sensor.src/nyce-motion-sensor.groovy @@ -16,7 +16,7 @@ import physicalgraph.zigbee.clusters.iaszone.ZoneStatus metadata { - definition (name: "NYCE Motion Sensor", namespace: "smartthings", author: "SmartThings") { + definition (name: "NYCE Motion Sensor", namespace: "smartthings", author: "SmartThings", mnmn: "SmartThings", vid: "generic-motion-2") { capability "Motion Sensor" capability "Configuration" capability "Battery" diff --git a/devicetypes/smartthings/nyce-open-closed-sensor.src/nyce-open-closed-sensor.groovy b/devicetypes/smartthings/nyce-open-closed-sensor.src/nyce-open-closed-sensor.groovy index 9b39146e092..aa5de1ebebd 100644 --- a/devicetypes/smartthings/nyce-open-closed-sensor.src/nyce-open-closed-sensor.groovy +++ b/devicetypes/smartthings/nyce-open-closed-sensor.src/nyce-open-closed-sensor.groovy @@ -18,7 +18,7 @@ import physicalgraph.zigbee.clusters.iaszone.ZoneStatus metadata { - definition (name: "NYCE Open/Closed Sensor", namespace: "smartthings", author: "NYCE") { + definition (name: "NYCE Open/Closed Sensor", namespace: "smartthings", author: "NYCE", mnmn: "SmartThings", vid: "generic-contact-3") { capability "Battery" capability "Configuration" capability "Contact Sensor" diff --git a/devicetypes/smartthings/zigbee-lock-without-codes.src/README.md b/devicetypes/smartthings/zigbee-lock-without-codes.src/README.md new file mode 100644 index 00000000000..b932fa44510 --- /dev/null +++ b/devicetypes/smartthings/zigbee-lock-without-codes.src/README.md @@ -0,0 +1,26 @@ +# Danalock ZigBee + +Local Execution + +Works with: + +* [Danalock V3 858125000074](https://danalock.com/products/danalock-v3-smart-lock/) + +## Table of contents + +* [Capabilities](#capabilities) +* [Device Health](#device-health) + +## Capabilities + +* **Configuration** +* **Health Check** +* **Sensor** +* **Battery** +* **Actuator** +* **Lock** +* **Refresh** + +## Device Health +* __122 min__ checkInterval + diff --git a/devicetypes/smartthings/zigbee-lock-without-codes.src/zigbee-lock-without-codes.groovy b/devicetypes/smartthings/zigbee-lock-without-codes.src/zigbee-lock-without-codes.groovy new file mode 100644 index 00000000000..7452d8999ae --- /dev/null +++ b/devicetypes/smartthings/zigbee-lock-without-codes.src/zigbee-lock-without-codes.groovy @@ -0,0 +1,256 @@ +/** + * + * Copyright 2018 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 physicalgraph.zigbee.zcl.DataType + +metadata { + definition (name:"ZigBee Lock Without Codes", namespace:"smartthings", author:"SmartThings", vid:"generic-lock-2", mnmn:"SmartThings", runLocally:true, minHubCoreVersion:'000.022.00013', executeCommandsLocally:true) { + capability "Actuator" + capability "Lock" + capability "Refresh" + capability "Sensor" + capability "Battery" + capability "Configuration" + capability "Health Check" + + fingerprint profileId:"0104, 000A", inClusters:"0000, 0001, 0003, 0009, 0020,0101, 0B05", outclusters:"000A, 0019, 0B05", manufacturer:"Danalock", model:"V3-BTZB", deviceJoinName:"Danalock V3 Smart Lock" + + } + + tiles(scale:2) { + multiAttributeTile(name:"toggle", type:"generic", width:6, height:4) { + tileAttribute("device.lock", key:"PRIMARY_CONTROL"){ + attributeState "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#00A0DC", nextState:"unlocking" + attributeState "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff", nextState:"locking" + attributeState "unknown", label:"unknown", action:"lock.lock", icon:"st.locks.lock.unknown", backgroundColor:"#ffffff", nextState:"locking" + attributeState "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#00A0DC" + attributeState "unlocking", label:'unlocking', icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff" + } + } + standardTile("lock", "device.lock", inactiveLabel:false, decoration:"flat", width:2, height:2) { + state "default", label:'lock', action:"lock.lock", icon:"st.locks.lock.locked", nextState:"locking" + } + standardTile("unlock", "device.lock", inactiveLabel:false, decoration:"flat", width:2, height:2) { + state "default", label:'unlock', action:"lock.unlock", icon:"st.locks.lock.unlocked", nextState:"unlocking" + + } + valueTile("battery", "device.battery", inactiveLabel:false, decoration:"flat", width:2, height:2) { + state "battery", label:'${currentValue}% battery', unit:"" + } + standardTile("refresh", "device.refresh", inactiveLabel:false, decoration:"flat", width:2, height:2) { + state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" + } + + main "toggle" + details(["toggle", "lock", "unlock", "battery", "refresh"]) + } +} + +private getCLUSTER_POWER() { 0x0001 } +private getCLUSTER_DOORLOCK() { 0x0101 } +private getDOORLOCK_CMD_LOCK_DOOR() { 0x00 } +private getDOORLOCK_CMD_UNLOCK_DOOR() { 0x01 } +private getDOORLOCK_RESPONSE_OPERATION_EVENT() { 0x20 } +private getDOORLOCK_RESPONSE_PROGRAMMING_EVENT() { 0x21 } +private getPOWER_ATTR_BATTERY_PERCENTAGE_REMAINING() { 0x0021 } +private getDOORLOCK_ATTR_LOCKSTATE() { 0x0000 } + +def installed() { + log.debug "Executing installed()" + initialize() +} + +def uninstalled() { + log.debug "Executing uninstalled()" + sendEvent(name:"lockRemoved", value:device.id, isStateChange:true, displayed:false) +} + +def updated() { + try { + if (!state.init || !state.configured) { + state.init = true + def cmds = [] + if (!state.configured) { + cmds << initialize() + } else { + cmds << refresh() + } + + return response(cmds.flatten()) + } + } catch (e) { + log.warn "ZigBee DTH - updated() threw exception:- $e" + } + return null +} + +def ping() { + refresh() +} + +def refresh() { + def cmds = zigbee.readAttribute(CLUSTER_DOORLOCK, DOORLOCK_ATTR_LOCKSTATE) + return cmds +} + +def configure() { + def cmds = initialize() + return cmds +} + +def initialize() { + log.debug "Executing initialize()" + state.configured = true + sendEvent(name:"checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed:false, data: [protocol:"zigbee", hubHardwareId:device.hub.hardwareID, offlinePingable:"1"]) + + def cmds = zigbee.configureReporting(CLUSTER_DOORLOCK, DOORLOCK_ATTR_LOCKSTATE, + DataType.ENUM8, 0, 3600, null) + + zigbee.configureReporting(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING,DataType.UINT8, 600, 21600, 0x01) + + zigbee.readAttribute(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING) + + def allCmds = cmds + refresh() + return allCmds +} + +def lock() { + def cmds = zigbee.command(CLUSTER_DOORLOCK, DOORLOCK_CMD_LOCK_DOOR) + + zigbee.readAttribute(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING) + + return cmds +} + +def unlock() { + def cmds = zigbee.command(CLUSTER_DOORLOCK, DOORLOCK_CMD_UNLOCK_DOOR) + + zigbee.readAttribute(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING) + return cmds +} + +def parse(String description) { + def result = null + if (description) { + if (description.startsWith('read attr -')) { + result = parseAttributeResponse(description) + } else { + result = parseCommandResponse(description) + } + } + return result +} + +private def parseAttributeResponse(String description) { + Map descMap = zigbee.parseDescriptionAsMap(description) + log.debug "Executing parseAttributeResponse() with description map:- $descMap" + def result = [] + Map responseMap = [:] + def clusterInt = descMap.clusterInt + def attrInt = descMap.attrInt + def deviceName = device.displayName + responseMap.data = deviceName + + if (clusterInt == CLUSTER_POWER && attrInt == POWER_ATTR_BATTERY_PERCENTAGE_REMAINING) { + responseMap.name = "battery" + + if (Integer.parseInt(descMap.value, 16) != 255) { + responseMap.value = Math.round(Integer.parseInt(descMap.value, 16) / 2) + responseMap.descriptionText = "Battery is at ${responseMap.value}%" + } + + } else if (clusterInt == CLUSTER_DOORLOCK && attrInt == DOORLOCK_ATTR_LOCKSTATE) { + def value = Integer.parseInt(descMap.value, 16) + responseMap.name = "lock" + if (value == 0) { + responseMap.value = "unknown" + responseMap.descriptionText = "Unknown state" + } else if (value == 1) { + log.debug "locked" + responseMap.value = "locked" + responseMap.descriptionText = "Locked" + } else if (value == 2) { + log.debug "unlocked" + responseMap.value = "unlocked" + responseMap.descriptionText = "Unlocked" + } else { + responseMap.value = "unknown" + responseMap.descriptionText = "Unknown state" + } + } else { + return null + } + result << createEvent(responseMap) + return result +} + +private def parseCommandResponse(String description) { + Map descMap = zigbee.parseDescriptionAsMap(description) + log.debug "Executing parseCommandResponse() with description map:- $descMap" + + def deviceName = device.displayName + def result = [] + Map responseMap = [:] + def data = descMap.data + def cmd = descMap.commandInt + def clusterInt = descMap.clusterInt + responseMap.data = deviceName + + if (clusterInt == CLUSTER_DOORLOCK && (cmd == DOORLOCK_CMD_LOCK_DOOR || cmd == DOORLOCK_CMD_UNLOCK_DOOR)) { + def cmdList = [] + cmdList << "delay 4200" + cmdList << zigbee.readAttribute(CLUSTER_DOORLOCK, DOORLOCK_ATTR_LOCKSTATE).first() + result << response(cmdList) + } else if (clusterInt == CLUSTER_DOORLOCK && cmd == DOORLOCK_RESPONSE_OPERATION_EVENT) { + def eventSource = Integer.parseInt(data[0], 16) + def eventCode = Integer.parseInt(data[1], 16) + + responseMap.name = "lock" + responseMap.displayed = true + responseMap.isStateChange = true + + if (eventSource == 1) { + responseMap.data = [method: "command"] + } else if (eventSource == 2) { + def desc = "manually" + responseMap.data = [method: "manual"] + } + + switch (eventCode) { + case 1: + responseMap.value = "locked" + responseMap.descriptionText = "Locked ${desc}" + break + case 2: + responseMap.value = "unlocked" + responseMap.descriptionText = "Unlocked ${desc}" + break + default: + break + } + } + + result << createEvent(responseMap) + return result +} + +private Boolean secondsPast(timestamp, seconds) { + if (!(timestamp instanceof Number)) { + if (timestamp instanceof Date) { + timestamp = timestamp.time + } else if ((timestamp instanceof String) && timestamp.isNumber()) { + timestamp = timestamp.toLong() + } else { + return true + } + } + return (now() - timestamp) > (seconds * 1000) +} diff --git a/devicetypes/smartthings/zll-white-color-temperature-bulb-5000k.src/zll-white-color-temperature-bulb-5000k.groovy b/devicetypes/smartthings/zll-white-color-temperature-bulb-5000k.src/zll-white-color-temperature-bulb-5000k.groovy index 7e144d6d139..16974898659 100644 --- a/devicetypes/smartthings/zll-white-color-temperature-bulb-5000k.src/zll-white-color-temperature-bulb-5000k.groovy +++ b/devicetypes/smartthings/zll-white-color-temperature-bulb-5000k.src/zll-white-color-temperature-bulb-5000k.groovy @@ -13,7 +13,7 @@ */ metadata { - definition (name: "ZLL White Color Temperature Bulb 5000K", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light", runLocally: true, minHubCoreVersion: '000.021.00001', executeCommandsLocally: true) { + definition (name: "ZLL White Color Temperature Bulb 5000K", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light", runLocally: true, minHubCoreVersion: '000.023.00001', executeCommandsLocally: true) { capability "Actuator" capability "Color Temperature" diff --git a/devicetypes/smartthings/zwave-basic-heat-alarm.src/zwave-basic-heat-alarm.groovy b/devicetypes/smartthings/zwave-basic-heat-alarm.src/zwave-basic-heat-alarm.groovy index 610859095c5..83727dc49bc 100644 --- a/devicetypes/smartthings/zwave-basic-heat-alarm.src/zwave-basic-heat-alarm.groovy +++ b/devicetypes/smartthings/zwave-basic-heat-alarm.src/zwave-basic-heat-alarm.groovy @@ -32,10 +32,9 @@ metadata { tiles(scale: 2) { multiAttributeTile(name: "heat", type: "lighting", width: 6, height: 4) { - tileAttribute("device.heat", key: "PRIMARY_CONTROL") { + tileAttribute("device.temperatureAlarm", key: "PRIMARY_CONTROL") { attributeState("cleared", label: "cleared", icon: "st.alarm.smoke.clear", backgroundColor: "#ffffff") - attributeState("detected", label: "HEAT", icon: "st.alarm.smoke.smoke", backgroundColor: "#e86d13") - attributeState("tested", label: "TEST", icon: "st.alarm.smoke.test", backgroundColor: "#e86d13") + attributeState("heat", label: "HEAT", icon: "st.alarm.smoke.smoke", backgroundColor: "#e86d13") } } valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { @@ -49,15 +48,19 @@ metadata { def installed() { def cmds = [] - // Device checks in every 4 hours, this interval allows us to miss one check-in notification before marking offline - cmds << createEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) - cmds << createHeatEvents("heatClear") + cmds << checkIntervalEvent + cmds << createHeatEvents("clear") cmds.each { cmd -> sendEvent(cmd) } + response(initialPoll()) } def updated() { + //sendEvent(checkIntervalEvent) +} + +def getCheckIntervalEvent() { // Device checks in every 4 hours, this interval allows us to miss one check-in notification before marking offline - sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) + createEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) } def getCommandClassVersions() { @@ -123,17 +126,15 @@ def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cm switch (cmd.event) { case 0x00: case 0xFE: - result = createHeatEvents("heatClear") + result = createHeatEvents("clear") break case 0x01: //Overheat detected case 0x02: //Overheat detected Unknown Location case 0x03: //Rapid Temperature Rise case 0x03: //Rapid Temperature Rise Unknown Location + case 0x07: //Tested result = createHeatEvents("heat") break - case 0x07: - result = createHeatEvents("tested") - break } } return result @@ -145,20 +146,32 @@ def createHeatEvents(name) { switch (name) { case "heat": text = "$device.displayName heat was detected!" - result = createEvent(name: "heat", value: "detected", descriptionText: text) + result = createEvent(name: "temperatureAlarm", value: "heat", descriptionText: text) break - case "tested": - text = "$device.displayName heat tested" - result = createEvent(name: "heat", value: "tested", descriptionText: text) - break - case "heatClear": + case "clear": text = "$device.displayName heat is clear" - result = createEvent(name: "heat", value: "cleared", descriptionText: text) - break - case "testClear": - text = "$device.displayName heat cleared" - result = createEvent(name: "heat", value: "cleared", descriptionText: text) + result = createEvent(name: "temperatureAlarm", value: "cleared", descriptionText: text, isStateChange: true) + log.debug "Clear event created" break } return result +} + +private command(physicalgraph.zwave.Command cmd) { + if (zwaveInfo?.zw?.endsWith("s")) { + zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() + } else { + cmd.format() + } +} + +private commands(commands, delay = 200) { + delayBetween(commands.collect { command(it) }, delay) +} + +def initialPoll() { + def request = [] + // check initial battery + request << zwave.batteryV1.batteryGet() + commands(request, 500) + ["delay 6000", command(zwave.wakeUpV1.wakeUpNoMoreInformation())] } \ No newline at end of file diff --git a/devicetypes/smartthings/zwave-dimmer-switch-generic.src/zwave-dimmer-switch-generic.groovy b/devicetypes/smartthings/zwave-dimmer-switch-generic.src/zwave-dimmer-switch-generic.groovy index 4e3553571be..49cf4c94215 100644 --- a/devicetypes/smartthings/zwave-dimmer-switch-generic.src/zwave-dimmer-switch-generic.groovy +++ b/devicetypes/smartthings/zwave-dimmer-switch-generic.src/zwave-dimmer-switch-generic.groovy @@ -28,7 +28,6 @@ metadata { fingerprint mfr: "001D", prod: "3201", model: "0001", deviceJoinName: "Leviton Dimmer Switch" fingerprint mfr: "001D", prod: "1B03", model: "0334", deviceJoinName: "Leviton Universal Dimmer" fingerprint mfr: "011A", prod: "0102", model: "0201", deviceJoinName: "Enerwave In-Wall Dimmer" - fingerprint mfr: "001D", prod: "1001", model: "0334", deviceJoinName: "Leviton 3-Speed Fan Controller" fingerprint mfr: "001D", prod: "0602", model: "0334", deviceJoinName: "Leviton Magnetic Low Voltage Dimmer" fingerprint mfr: "001D", prod: "0401", model: "0334", deviceJoinName: "Leviton 600W Incandescent Dimmer" fingerprint mfr: "0111", prod: "8200", model: "0200", deviceJoinName: "Remotec Technology Plug-In Dimmer" @@ -37,9 +36,6 @@ metadata { fingerprint mfr: "0039", prod: "5044", model: "3038", deviceJoinName: "Honeywell Z-Wave Plug-in Dimmer" fingerprint mfr: "0039", prod: "4944", model: "3038", deviceJoinName: "Honeywell Z-Wave In-Wall Smart Dimmer" fingerprint mfr: "0039", prod: "4944", model: "3130", deviceJoinName: "Honeywell Z-Wave In-Wall Smart Toggle Dimmer" - fingerprint mfr: "0063", prod: "4944", model: "3034", deviceJoinName: "GE In-Wall Smart Fan Control" - fingerprint mfr: "0063", prod: "4944", model: "3131", deviceJoinName: "GE In-Wall Smart Fan Control" - fingerprint mfr: "0039", prod: "4944", model: "3131", deviceJoinName: "Honeywell Z-Wave Plus In-Wall Fan Speed Control" fingerprint mfr: "001A", prod: "4449", model: "0101", deviceJoinName: "Eaton RF Master Dimmer" fingerprint mfr: "001A", prod: "4449", model: "0003", deviceJoinName: "Eaton RF Dimming Plug-In Module" fingerprint mfr: "0086", prod: "0103", model: "0063", deviceJoinName: "Aeotec Smart Dimmer 6" diff --git a/devicetypes/smartthings/zwave-fan-controller.src/zwave-fan-controller.groovy b/devicetypes/smartthings/zwave-fan-controller.src/zwave-fan-controller.groovy new file mode 100644 index 00000000000..c4308be48c0 --- /dev/null +++ b/devicetypes/smartthings/zwave-fan-controller.src/zwave-fan-controller.groovy @@ -0,0 +1,160 @@ +/** + * Copyright 2018 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. + * + */ +metadata { + definition(name: "Z-Wave Fan Controller", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.fan") { + capability "Switch Level" + capability "Switch" + capability "Fan Speed" + capability "Health Check" + capability "Actuator" + capability "Refresh" + capability "Sensor" + + command "low" + command "medium" + command "high" + command "raiseFanSpeed" + command "lowerFanSpeed" + + fingerprint mfr: "001D", prod: "1001", model: "0334", deviceJoinName: "Leviton 3-Speed Fan Controller" + fingerprint mfr: "0063", prod: "4944", model: "3034", deviceJoinName: "GE In-Wall Smart Fan Control" + fingerprint mfr: "0063", prod: "4944", model: "3131", deviceJoinName: "GE In-Wall Smart Fan Control" + fingerprint mfr: "0039", prod: "4944", model: "3131", deviceJoinName: "Honeywell Z-Wave Plus In-Wall Fan Speed Control" + } + + simulator { + status "00%": "command: 2003, payload: 00" + status "33%": "command: 2003, payload: 21" + status "66%": "command: 2003, payload: 42" + status "99%": "command: 2003, payload: 63" + } + + tiles(scale: 2) { + multiAttributeTile(name: "fanSpeed", type: "generic", width: 6, height: 4, canChangeIcon: true) { + tileAttribute("device.fanSpeed", key: "PRIMARY_CONTROL") { + attributeState "0", label: "off", action: "switch.on", icon: "st.thermostat.fan-off", backgroundColor: "#ffffff" + attributeState "1", label: "low", action: "switch.off", icon: "st.thermostat.fan-on", backgroundColor: "#00a0dc" + attributeState "2", label: "medium", action: "switch.off", icon: "st.thermostat.fan-on", backgroundColor: "#00a0dc" + attributeState "3", label: "high", action: "switch.off", icon: "st.thermostat.fan-on", backgroundColor: "#00a0dc" + } + tileAttribute("device.fanSpeed", key: "VALUE_CONTROL") { + attributeState "VALUE_UP", action: "raiseFanSpeed" + attributeState "VALUE_DOWN", action: "lowerFanSpeed" + } + } + + standardTile("refresh", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") { + state "default", label: '', action: "refresh.refresh", icon: "st.secondary.refresh" + } + main "fanSpeed" + details(["fanSpeed", "refresh"]) + } + +} + +def installed() { + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) + response(refresh()) +} + +def parse(String description) { + def result = null + if (description != "updated") { + log.debug "parse() >> zwave.parse($description)" + def cmd = zwave.parse(description, [0x20: 1, 0x26: 1]) + if (cmd) { + result = zwaveEvent(cmd) + } + } + if (result?.name == 'hail' && hubFirmwareLessThan("000.011.00602")) { + result = [result, response(zwave.basicV1.basicGet())] + log.debug "Was hailed: requesting state update" + } else { + log.debug "Parse returned ${result?.descriptionText}" + } + return result +} + +def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) { + fanEvents(cmd) +} + +def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) { + fanEvents(cmd) +} + +def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd) { + fanEvents(cmd) +} + +def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelSet cmd) { + fanEvents(cmd) +} + +def fanEvents(physicalgraph.zwave.Command cmd) { + def value = (cmd.value ? "on" : "off") + def result = [createEvent(name: "switch", value: value)] + result << createEvent(name: "level", value: cmd.value == 99 ? 100 : cmd.value) + result << createEvent(name: "fanSpeed", value: cmd.value/33) + return result +} + +def on() { + setLevel(0xFF) +} + +def off() { + setLevel(0x00) +} + +def setLevel(value) { + log.debug "setLevel >> value: $value" + def level = value as Integer + level = level == 255 ? level : Math.max(Math.min(level, 99), 0) + sendEvent(name: "switch", value: level > 0 ? "on" : "off") + delayBetween([zwave.basicV1.basicSet(value: level).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000) +} + +def setFanSpeed(speed) { + setLevel(speed * 33) +} + +def raiseFanSpeed() { + setFanSpeed(Math.min((device.currentValue("fanSpeed") as Integer) + 1, 3)) +} + +def lowerFanSpeed() { + setFanSpeed(Math.max((device.currentValue("fanSpeed") as Integer) - 1, 0)) +} + +def low() { + setFanSpeed(1) +} + +def medium() { + setFanSpeed(2) +} + +def high() { + setFanSpeed(3) +} + +def refresh() { + zwave.switchMultilevelV1.switchMultilevelGet().format() +} + +def ping() { + refresh() +} + diff --git a/devicetypes/smartthings/zwave-metering-switch-secure.src/zwave-metering-switch-secure.groovy b/devicetypes/smartthings/zwave-metering-switch-secure.src/zwave-metering-switch-secure.groovy index a362f7a3235..f750dbb9c81 100644 --- a/devicetypes/smartthings/zwave-metering-switch-secure.src/zwave-metering-switch-secure.groovy +++ b/devicetypes/smartthings/zwave-metering-switch-secure.src/zwave-metering-switch-secure.groovy @@ -26,7 +26,7 @@ metadata { command "reset" fingerprint deviceId: "0x1001", inClusters: "0x5E, 0x22, 0x85, 0x59, 0x70, 0x56, 0x5A, 0x7A, 0x72, 0x32, 0x8E, 0x71, 0x73, 0x98, 0x31, 0x25, 0x86", outClusters: "" - fingerprint mfr: "0072", prod: "0501", model: "0F06", deviceJoinName: "Fibaro Wall Plug ZW5" // US + fingerprint mfr: "0072", prod: "0501", model: "0F06", deviceJoinName: "Fibaro Wall Plug ZW5" // US } // simulator metadata diff --git a/devicetypes/smartthings/zwave-metering-switch.src/zwave-metering-switch.groovy b/devicetypes/smartthings/zwave-metering-switch.src/zwave-metering-switch.groovy index ca5260d6998..b23ed3aa3c9 100644 --- a/devicetypes/smartthings/zwave-metering-switch.src/zwave-metering-switch.groovy +++ b/devicetypes/smartthings/zwave-metering-switch.src/zwave-metering-switch.groovy @@ -35,6 +35,8 @@ metadata { fingerprint mfr: "014F", prod: "5053", model: "3531", deviceJoinName: "GoControl Plug-in Switch" fingerprint mfr: "0063", prod: "4F44", model: "3031", deviceJoinName: "GE Direct-Wire Outdoor Switch" fingerprint mfr: "0258", prod: "0003", model: "0087", deviceJoinName: "NEO Coolcam Power plug" + fingerprint mfr: "010F", prod: "0602", model: "1001", deviceJoinName: "Fibaro Wall Plug ZW5" // EU + fingerprint mfr: "010F", prod: "1801", model: "1000", deviceJoinName: "Fibaro Wall Plug ZW5" // UK } // simulator metadata diff --git a/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy b/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy index f9ed139e9c8..215d40cacfe 100644 --- a/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy +++ b/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy @@ -115,7 +115,7 @@ def initialize() { def configure() { log.debug "config" def cmds = [] - if (zwaveInfo.mfr == "0258" && zwaveInfo.model == "1088") { + if (zwaveInfo.mfr == "0131" && zwaveInfo.model == "1083") { // Set alarm volume to 2 (medium) cmds << zwave.configurationV1.configurationSet(parameterNumber: 1, size: 1, configurationValue: [2]).format() cmds << "delay 500" @@ -142,7 +142,7 @@ def on() { // Those alarms do not end with Siren Notification Report. // For those cases we add additional state check after alarm duration to // synchronize cloud state with actual device state. - if (zwaveInfo.mfr == "0258" && zwaveInfo.model == "1088") { + if (zwaveInfo.mfr == "0131" && zwaveInfo.model == "1083") { [ zwave.basicV1.basicSet(value: 0xFF).format(), zwave.basicV1.basicGet().format(),