From 2580dd44a11e50c95ae2f6adc0659b7336bfb47b Mon Sep 17 00:00:00 2001 From: zhangjinkang Date: Fri, 6 Jul 2018 05:31:23 -0400 Subject: [PATCH 1/9] add orvibo gas detector DTH --- .../Orvibo-Gas-detect.groovy | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy diff --git a/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy b/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy new file mode 100644 index 00000000000..025a8e0a9aa --- /dev/null +++ b/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy @@ -0,0 +1,142 @@ +/* + * 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. + * Author : jinkang zhang / jk0218.zhang@samsung.com + * Date : 2018-07-04 + */ +import physicalgraph.zigbee.clusters.iaszone.ZoneStatus +import physicalgraph.zigbee.zcl.DataType + +metadata { + definition(name: "Orvibo Gas Detector", namespace: "smartthings", author: "SmartThings", runLocally: false, minHubCoreVersion: '000.017.0012', executeCommandsLocally: false, mnmn: "SmartThings", vid: "generic-smoke") { + capability "Smoke Detector" + capability "Configuration" + capability "Alarm" + capability "Health Check" + capability "Sensor" + + + fingerprint profileId: "0104", deviceId: "0402", inClusters: "0000,0003,0500,0009", outClusters: "0019",manufacturer: "Heiman",model:"d0e857bfd54f4a12816295db3945a421" + } + + tiles { + standardTile("main", "device.smoke", width: 2, height: 2) { + state("clear", label:"Clear", icon:"st.alarm.smoke.clear", backgroundColor:"#ffffff") + state("detected", label:"Smoke!", icon:"st.alarm.smoke.smoke", backgroundColor:"#e86d13") + } + + standardTile("alarm", "device.alarm", width: 2, height: 2) { + state "off", label:'off', action:'alarm.strobe', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" + state "strobe", label:'strobe!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" + state "siren", label:'siren!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" + state "both", label:'alarm!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" + } + + + + main "main" + details(["main","alarm"]) + } +} + +def installed(){ + log.debug "installed" + configure() +} + +def parse(String description) { + log.debug "description(): $description" + def map = zigbee.getEvent(description) + if(!map){ + if (description?.startsWith('zone status')) { + map = parseIasMessage(description) + } + } + + log.debug "Parse returned $map" + def result = map ? createEvent(map) : [:] + + if (description?.startsWith('enroll request')) { + List cmds = zigbee.enrollResponse() + log.debug "enroll response: ${cmds}" + result = cmds?.collect { new physicalgraph.device.HubAction(it) } + } + + return result +} + + +private Map parseIasMessage(String description) { + ZoneStatus zs = zigbee.parseZoneStatus(description) + translateZoneStatus(zs) +} + +private Map translateZoneStatus(ZoneStatus zs) { + // Some sensor models that use this DTH use alarm1 and some use alarm2 to signify motion + return (zs.isAlarm1Set() || zs.isAlarm2Set()) ? getDetectedResult('detected') : getDetectedResult('clear') +} + +private Map getDetectedResult(value) { + String descriptionText = value == 'detected' ? "${device.displayName} detected smoke" : "${device.displayName} smoke clear" + if(value == detected){ + strobe() + }else{ + off() + } + return [ + name : 'smoke', + value : value, + descriptionText: descriptionText, + translatable : true + ] +} + +def strobe() { + sendEvent(name: "alarm", value: "strobe") +} + +def siren() { + sendEvent(name: "alarm", value: "siren") +} + +def both() { + sendEvent(name: "alarm", value: "both") +} + +def off() { + sendEvent(name: "alarm", value: "off") +} + + +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + log.debug "ping " + return zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) +} + +def configure() { + log.debug "configure" + // Device-Watch allows 2 check-in misses from device + ping (plus 1 min lag time) + // enrolls with default periodic reporting until newer 5 min interval is confirmed + sendEvent(name: "checkInterval", value:40 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) + + log.debug "Configuring Reporting" + def configCmds = [] + + // battery minReport 30 seconds, maxReportTime 6 hrs by default + configCmds += zigbee.configureReporting(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS, DataType.UINT8, 30, 21600, 0x10) + return configCmds // send refresh cmds as part of config +} From dd7bd0aa85ca9e4a3b9be2f88a1c04971eaadb6f Mon Sep 17 00:00:00 2001 From: zhangjinkang Date: Mon, 9 Jul 2018 23:27:20 -0400 Subject: [PATCH 2/9] add install initial state poll --- .../Orvibo-Gas-detect.groovy | 85 +++++++------------ 1 file changed, 33 insertions(+), 52 deletions(-) diff --git a/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy b/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy index 025a8e0a9aa..8da868b0ca6 100644 --- a/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy +++ b/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy @@ -25,36 +25,32 @@ metadata { capability "Alarm" capability "Health Check" capability "Sensor" - - + capability "Refresh" fingerprint profileId: "0104", deviceId: "0402", inClusters: "0000,0003,0500,0009", outClusters: "0019",manufacturer: "Heiman",model:"d0e857bfd54f4a12816295db3945a421" } - tiles { standardTile("main", "device.smoke", width: 2, height: 2) { state("clear", label:"Clear", icon:"st.alarm.smoke.clear", backgroundColor:"#ffffff") state("detected", label:"Smoke!", icon:"st.alarm.smoke.smoke", backgroundColor:"#e86d13") } - standardTile("alarm", "device.alarm", width: 2, height: 2) { - state "off", label:'off', action:'alarm.strobe', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" - state "strobe", label:'strobe!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" - state "siren", label:'siren!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" - state "both", label:'alarm!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" - } - - - - main "main" - details(["main","alarm"]) + state "off", label:'off', action:'alarm.strobe', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" + state "strobe", label:'strobe!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" + state "siren", label:'siren!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" + state "both", label:'alarm!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" + } + standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { + state "default", action: "refresh.refresh", icon: "st.secondary.refresh" + } + main "main" + details(["main","alarm","refresh"]) } } - def installed(){ log.debug "installed" - configure() + return zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER,zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + + zigbee.readAttribute(0x0009,0x0000) } - def parse(String description) { log.debug "description(): $description" def map = zigbee.getEvent(description) @@ -63,30 +59,23 @@ def parse(String description) { map = parseIasMessage(description) } } - log.debug "Parse returned $map" def result = map ? createEvent(map) : [:] - if (description?.startsWith('enroll request')) { - List cmds = zigbee.enrollResponse() - log.debug "enroll response: ${cmds}" - result = cmds?.collect { new physicalgraph.device.HubAction(it) } - } - + List cmds = zigbee.enrollResponse() + log.debug "enroll response: ${cmds}" + result = cmds?.collect { new physicalgraph.device.HubAction(it)} + } return result } - - private Map parseIasMessage(String description) { ZoneStatus zs = zigbee.parseZoneStatus(description) translateZoneStatus(zs) } - private Map translateZoneStatus(ZoneStatus zs) { // Some sensor models that use this DTH use alarm1 and some use alarm2 to signify motion return (zs.isAlarm1Set() || zs.isAlarm2Set()) ? getDetectedResult('detected') : getDetectedResult('clear') } - private Map getDetectedResult(value) { String descriptionText = value == 'detected' ? "${device.displayName} detected smoke" : "${device.displayName} smoke clear" if(value == detected){ @@ -95,30 +84,32 @@ private Map getDetectedResult(value) { off() } return [ - name : 'smoke', - value : value, - descriptionText: descriptionText, - translatable : true + name : 'smoke', + value : value, + descriptionText : descriptionText, + translatable : true ] } - def strobe() { - sendEvent(name: "alarm", value: "strobe") + sendEvent(name: "alarm", value: "strobe") } - def siren() { - sendEvent(name: "alarm", value: "siren") + sendEvent(name: "alarm", value: "siren") } - def both() { - sendEvent(name: "alarm", value: "both") + sendEvent(name: "alarm", value: "both") } - def off() { - sendEvent(name: "alarm", value: "off") + sendEvent(name: "alarm", value: "off") +} +def refresh() { + log.debug "Refreshing Values" + def refreshCmds = [] + refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0021) + + zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER,zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + + zigbee.enrollResponse() + return refreshCmds } - - /** * PING is used by Device-Watch in attempt to reach the Device * */ @@ -126,17 +117,7 @@ def ping() { log.debug "ping " return zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) } - def configure() { log.debug "configure" - // Device-Watch allows 2 check-in misses from device + ping (plus 1 min lag time) - // enrolls with default periodic reporting until newer 5 min interval is confirmed sendEvent(name: "checkInterval", value:40 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) - - log.debug "Configuring Reporting" - def configCmds = [] - - // battery minReport 30 seconds, maxReportTime 6 hrs by default - configCmds += zigbee.configureReporting(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS, DataType.UINT8, 30, 21600, 0x10) - return configCmds // send refresh cmds as part of config } From 2b873e6d917c33a791209afe591d93d12bfd1639 Mon Sep 17 00:00:00 2001 From: zhangjinkang Date: Tue, 10 Jul 2018 08:54:45 -0400 Subject: [PATCH 3/9] rename ORVIBO gas directory. Fix refresh from 2x2 to 1 x 1, fix ping time interval to 20 minutes. --- .../Orvibo-Gas-detect.groovy | 4 +- .../Orvibo-Gas-detector.groovy | 123 ++++++++++++++++++ 2 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy diff --git a/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy b/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy index 8da868b0ca6..020aecf56a8 100644 --- a/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy +++ b/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy @@ -39,7 +39,7 @@ metadata { state "siren", label:'siren!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" state "both", label:'alarm!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" } - standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { + standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 1, height: 1) { state "default", action: "refresh.refresh", icon: "st.secondary.refresh" } main "main" @@ -119,5 +119,5 @@ def ping() { } def configure() { log.debug "configure" - sendEvent(name: "checkInterval", value:40 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) + sendEvent(name: "checkInterval", value:20 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) } diff --git a/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy new file mode 100644 index 00000000000..8da868b0ca6 --- /dev/null +++ b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy @@ -0,0 +1,123 @@ +/* + * 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. + * Author : jinkang zhang / jk0218.zhang@samsung.com + * Date : 2018-07-04 + */ +import physicalgraph.zigbee.clusters.iaszone.ZoneStatus +import physicalgraph.zigbee.zcl.DataType + +metadata { + definition(name: "Orvibo Gas Detector", namespace: "smartthings", author: "SmartThings", runLocally: false, minHubCoreVersion: '000.017.0012', executeCommandsLocally: false, mnmn: "SmartThings", vid: "generic-smoke") { + capability "Smoke Detector" + capability "Configuration" + capability "Alarm" + capability "Health Check" + capability "Sensor" + capability "Refresh" + fingerprint profileId: "0104", deviceId: "0402", inClusters: "0000,0003,0500,0009", outClusters: "0019",manufacturer: "Heiman",model:"d0e857bfd54f4a12816295db3945a421" + } + tiles { + standardTile("main", "device.smoke", width: 2, height: 2) { + state("clear", label:"Clear", icon:"st.alarm.smoke.clear", backgroundColor:"#ffffff") + state("detected", label:"Smoke!", icon:"st.alarm.smoke.smoke", backgroundColor:"#e86d13") + } + standardTile("alarm", "device.alarm", width: 2, height: 2) { + state "off", label:'off', action:'alarm.strobe', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" + state "strobe", label:'strobe!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" + state "siren", label:'siren!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" + state "both", label:'alarm!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" + } + standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { + state "default", action: "refresh.refresh", icon: "st.secondary.refresh" + } + main "main" + details(["main","alarm","refresh"]) + } +} +def installed(){ + log.debug "installed" + return zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER,zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + + zigbee.readAttribute(0x0009,0x0000) +} +def parse(String description) { + log.debug "description(): $description" + def map = zigbee.getEvent(description) + if(!map){ + if (description?.startsWith('zone status')) { + map = parseIasMessage(description) + } + } + log.debug "Parse returned $map" + def result = map ? createEvent(map) : [:] + if (description?.startsWith('enroll request')) { + List cmds = zigbee.enrollResponse() + log.debug "enroll response: ${cmds}" + result = cmds?.collect { new physicalgraph.device.HubAction(it)} + } + return result +} +private Map parseIasMessage(String description) { + ZoneStatus zs = zigbee.parseZoneStatus(description) + translateZoneStatus(zs) +} +private Map translateZoneStatus(ZoneStatus zs) { + // Some sensor models that use this DTH use alarm1 and some use alarm2 to signify motion + return (zs.isAlarm1Set() || zs.isAlarm2Set()) ? getDetectedResult('detected') : getDetectedResult('clear') +} +private Map getDetectedResult(value) { + String descriptionText = value == 'detected' ? "${device.displayName} detected smoke" : "${device.displayName} smoke clear" + if(value == detected){ + strobe() + }else{ + off() + } + return [ + name : 'smoke', + value : value, + descriptionText : descriptionText, + translatable : true + ] +} +def strobe() { + sendEvent(name: "alarm", value: "strobe") +} +def siren() { + sendEvent(name: "alarm", value: "siren") +} +def both() { + sendEvent(name: "alarm", value: "both") +} +def off() { + sendEvent(name: "alarm", value: "off") +} +def refresh() { + log.debug "Refreshing Values" + def refreshCmds = [] + refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0021) + + zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER,zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + + zigbee.enrollResponse() + return refreshCmds +} +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + log.debug "ping " + return zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) +} +def configure() { + log.debug "configure" + sendEvent(name: "checkInterval", value:40 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) +} From 1ceb925cc81653f939eddb9c294653a95ca859b5 Mon Sep 17 00:00:00 2001 From: zhangjinkang Date: Tue, 10 Jul 2018 23:29:26 -0400 Subject: [PATCH 4/9] Fixed orvibo gas detector sensor . 1. add alarm event parse. 2. remove unused alarm state. --- .../Orvibo-Gas-detect.groovy | 123 ------------------ .../Orvibo-Gas-detector.groovy | 85 ++++++------ 2 files changed, 46 insertions(+), 162 deletions(-) delete mode 100644 devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy diff --git a/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy b/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy deleted file mode 100644 index 020aecf56a8..00000000000 --- a/devicetypes/smartthings/Orvibo-Gas-detect.src/Orvibo-Gas-detect.groovy +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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. - * Author : jinkang zhang / jk0218.zhang@samsung.com - * Date : 2018-07-04 - */ -import physicalgraph.zigbee.clusters.iaszone.ZoneStatus -import physicalgraph.zigbee.zcl.DataType - -metadata { - definition(name: "Orvibo Gas Detector", namespace: "smartthings", author: "SmartThings", runLocally: false, minHubCoreVersion: '000.017.0012', executeCommandsLocally: false, mnmn: "SmartThings", vid: "generic-smoke") { - capability "Smoke Detector" - capability "Configuration" - capability "Alarm" - capability "Health Check" - capability "Sensor" - capability "Refresh" - fingerprint profileId: "0104", deviceId: "0402", inClusters: "0000,0003,0500,0009", outClusters: "0019",manufacturer: "Heiman",model:"d0e857bfd54f4a12816295db3945a421" - } - tiles { - standardTile("main", "device.smoke", width: 2, height: 2) { - state("clear", label:"Clear", icon:"st.alarm.smoke.clear", backgroundColor:"#ffffff") - state("detected", label:"Smoke!", icon:"st.alarm.smoke.smoke", backgroundColor:"#e86d13") - } - standardTile("alarm", "device.alarm", width: 2, height: 2) { - state "off", label:'off', action:'alarm.strobe', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" - state "strobe", label:'strobe!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" - state "siren", label:'siren!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" - state "both", label:'alarm!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" - } - standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 1, height: 1) { - state "default", action: "refresh.refresh", icon: "st.secondary.refresh" - } - main "main" - details(["main","alarm","refresh"]) - } -} -def installed(){ - log.debug "installed" - return zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER,zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + - zigbee.readAttribute(0x0009,0x0000) -} -def parse(String description) { - log.debug "description(): $description" - def map = zigbee.getEvent(description) - if(!map){ - if (description?.startsWith('zone status')) { - map = parseIasMessage(description) - } - } - log.debug "Parse returned $map" - def result = map ? createEvent(map) : [:] - if (description?.startsWith('enroll request')) { - List cmds = zigbee.enrollResponse() - log.debug "enroll response: ${cmds}" - result = cmds?.collect { new physicalgraph.device.HubAction(it)} - } - return result -} -private Map parseIasMessage(String description) { - ZoneStatus zs = zigbee.parseZoneStatus(description) - translateZoneStatus(zs) -} -private Map translateZoneStatus(ZoneStatus zs) { - // Some sensor models that use this DTH use alarm1 and some use alarm2 to signify motion - return (zs.isAlarm1Set() || zs.isAlarm2Set()) ? getDetectedResult('detected') : getDetectedResult('clear') -} -private Map getDetectedResult(value) { - String descriptionText = value == 'detected' ? "${device.displayName} detected smoke" : "${device.displayName} smoke clear" - if(value == detected){ - strobe() - }else{ - off() - } - return [ - name : 'smoke', - value : value, - descriptionText : descriptionText, - translatable : true - ] -} -def strobe() { - sendEvent(name: "alarm", value: "strobe") -} -def siren() { - sendEvent(name: "alarm", value: "siren") -} -def both() { - sendEvent(name: "alarm", value: "both") -} -def off() { - sendEvent(name: "alarm", value: "off") -} -def refresh() { - log.debug "Refreshing Values" - def refreshCmds = [] - refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0021) + - zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER,zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + - zigbee.enrollResponse() - return refreshCmds -} -/** - * PING is used by Device-Watch in attempt to reach the Device - * */ -def ping() { - log.debug "ping " - return zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) -} -def configure() { - log.debug "configure" - sendEvent(name: "checkInterval", value:20 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) -} diff --git a/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy index 8da868b0ca6..81773cb0972 100644 --- a/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy +++ b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy @@ -28,28 +28,32 @@ metadata { capability "Refresh" fingerprint profileId: "0104", deviceId: "0402", inClusters: "0000,0003,0500,0009", outClusters: "0019",manufacturer: "Heiman",model:"d0e857bfd54f4a12816295db3945a421" } + + simulator { + status "active": "zone status 0x0001 -- extended status 0x00" + status "alarm" : "read attr - raw: E91D0100090C000000210000, dni: E91D, endpoint: 01, cluster: 0009, size: 0C, attrId: 0000, result: success, encoding: 21, value: 0001" + status "off" : "read attr - raw: E91D0100090C000000210000, dni: E91D, endpoint: 01, cluster: 0009, size: 0C, attrId: 0000, result: success, encoding: 21, value: 0000" + } + tiles { - standardTile("main", "device.smoke", width: 2, height: 2) { + standardTile("smoke", "device.smoke", width: 2, height: 2) { state("clear", label:"Clear", icon:"st.alarm.smoke.clear", backgroundColor:"#ffffff") state("detected", label:"Smoke!", icon:"st.alarm.smoke.smoke", backgroundColor:"#e86d13") } standardTile("alarm", "device.alarm", width: 2, height: 2) { - state "off", label:'off', action:'alarm.strobe', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" - state "strobe", label:'strobe!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" - state "siren", label:'siren!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" - state "both", label:'alarm!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" + state "off", label:'off', action:'alarm.siren', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" + state "siren", label:'siren!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" } - standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { + standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 1, height: 1) { state "default", action: "refresh.refresh", icon: "st.secondary.refresh" } - main "main" - details(["main","alarm","refresh"]) + main "smoke" + details(["smoke","alarm","refresh"]) } } def installed(){ log.debug "installed" - return zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER,zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + - zigbee.readAttribute(0x0009,0x0000) + refresh() } def parse(String description) { log.debug "description(): $description" @@ -57,6 +61,10 @@ def parse(String description) { if(!map){ if (description?.startsWith('zone status')) { map = parseIasMessage(description) + }else if(description?.startsWith('read attr')){ + map = parseAlarmMessage(description) + }else{ + map = [:] } } log.debug "Parse returned $map" @@ -68,46 +76,45 @@ def parse(String description) { } return result } -private Map parseIasMessage(String description) { - ZoneStatus zs = zigbee.parseZoneStatus(description) - translateZoneStatus(zs) +def parseAlarmMessage(String description){ + def descMap = zigbee.parseDescriptionAsMap(description) + def map = [:] + if (descMap?.clusterInt == 0x0009 && descMap.value) { + map = getAlarmResult(descMap.value == "0000" ? false :true) + } + return map; } -private Map translateZoneStatus(ZoneStatus zs) { - // Some sensor models that use this DTH use alarm1 and some use alarm2 to signify motion - return (zs.isAlarm1Set() || zs.isAlarm2Set()) ? getDetectedResult('detected') : getDetectedResult('clear') +def parseIasMessage(String description) { + ZoneStatus zs = zigbee.parseZoneStatus(description) + return getDetectedResult(zs.isAlarm1Set() || zs.isAlarm2Set()) } -private Map getDetectedResult(value) { - String descriptionText = value == 'detected' ? "${device.displayName} detected smoke" : "${device.displayName} smoke clear" - if(value == detected){ - strobe() - }else{ - off() - } - return [ - name : 'smoke', - value : value, - descriptionText : descriptionText, - translatable : true - ] +def getDetectedResult(value) { + def detected = value ? 'detected': 'clear' + String descriptionText = "${device.displayName} smoke ${detected}" + return [name:'smoke', + value: detected, + descriptionText:descriptionText, + translatable:true] } -def strobe() { - sendEvent(name: "alarm", value: "strobe") +def getAlarmResult(value) { + def alarm = value ? 'siren': 'off' + String descriptionText = "${device.displayName} alarm ${alarm}" + return [name:'alarm', + value: alarm, + descriptionText:descriptionText, + translatable:true] } def siren() { sendEvent(name: "alarm", value: "siren") } -def both() { - sendEvent(name: "alarm", value: "both") -} def off() { sendEvent(name: "alarm", value: "off") } def refresh() { log.debug "Refreshing Values" def refreshCmds = [] - refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0021) + - zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER,zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + - zigbee.enrollResponse() + refreshCmds += zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER,zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + + zigbee.readAttribute(0x0009,0x0000) return refreshCmds } /** @@ -115,9 +122,9 @@ def refresh() { * */ def ping() { log.debug "ping " - return zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + refresh() } def configure() { log.debug "configure" - sendEvent(name: "checkInterval", value:40 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) + sendEvent(name: "checkInterval", value:20 * 60 + 2*60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) } From 22b48c5f16389497c5b4eef2dde5050f3591fe64 Mon Sep 17 00:00:00 2001 From: zhangjinkang Date: Wed, 11 Jul 2018 04:15:12 -0400 Subject: [PATCH 5/9] parse IAS zone status as heart beat event . --- .../orvibo-gas-detector.src/Orvibo-Gas-detector.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy index 81773cb0972..edcb219a225 100644 --- a/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy +++ b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy @@ -64,7 +64,7 @@ def parse(String description) { }else if(description?.startsWith('read attr')){ map = parseAlarmMessage(description) }else{ - map = [:] + map = zigbee.parseDescriptionAsMap(description) } } log.debug "Parse returned $map" From c2c0535892f3630e4114e15762b9ca59110ba53d Mon Sep 17 00:00:00 2001 From: zhangjinkang Date: Tue, 17 Jul 2018 22:09:26 -0400 Subject: [PATCH 6/9] remove alarm capabality . Orvibo did not support alarm capability . --- .../Orvibo-Gas-detector.groovy | 43 +++---------------- 1 file changed, 6 insertions(+), 37 deletions(-) diff --git a/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy index edcb219a225..7dfabfbe68e 100644 --- a/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy +++ b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy @@ -22,7 +22,6 @@ metadata { definition(name: "Orvibo Gas Detector", namespace: "smartthings", author: "SmartThings", runLocally: false, minHubCoreVersion: '000.017.0012', executeCommandsLocally: false, mnmn: "SmartThings", vid: "generic-smoke") { capability "Smoke Detector" capability "Configuration" - capability "Alarm" capability "Health Check" capability "Sensor" capability "Refresh" @@ -31,8 +30,6 @@ metadata { simulator { status "active": "zone status 0x0001 -- extended status 0x00" - status "alarm" : "read attr - raw: E91D0100090C000000210000, dni: E91D, endpoint: 01, cluster: 0009, size: 0C, attrId: 0000, result: success, encoding: 21, value: 0001" - status "off" : "read attr - raw: E91D0100090C000000210000, dni: E91D, endpoint: 01, cluster: 0009, size: 0C, attrId: 0000, result: success, encoding: 21, value: 0000" } tiles { @@ -40,15 +37,11 @@ metadata { state("clear", label:"Clear", icon:"st.alarm.smoke.clear", backgroundColor:"#ffffff") state("detected", label:"Smoke!", icon:"st.alarm.smoke.smoke", backgroundColor:"#e86d13") } - standardTile("alarm", "device.alarm", width: 2, height: 2) { - state "off", label:'off', action:'alarm.siren', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" - state "siren", label:'siren!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" - } standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 1, height: 1) { state "default", action: "refresh.refresh", icon: "st.secondary.refresh" } main "smoke" - details(["smoke","alarm","refresh"]) + details(["smoke","refresh"]) } } def installed(){ @@ -61,8 +54,6 @@ def parse(String description) { if(!map){ if (description?.startsWith('zone status')) { map = parseIasMessage(description) - }else if(description?.startsWith('read attr')){ - map = parseAlarmMessage(description) }else{ map = zigbee.parseDescriptionAsMap(description) } @@ -76,55 +67,33 @@ def parse(String description) { } return result } -def parseAlarmMessage(String description){ - def descMap = zigbee.parseDescriptionAsMap(description) - def map = [:] - if (descMap?.clusterInt == 0x0009 && descMap.value) { - map = getAlarmResult(descMap.value == "0000" ? false :true) - } - return map; -} def parseIasMessage(String description) { ZoneStatus zs = zigbee.parseZoneStatus(description) return getDetectedResult(zs.isAlarm1Set() || zs.isAlarm2Set()) } def getDetectedResult(value) { def detected = value ? 'detected': 'clear' - String descriptionText = "${device.displayName} smoke ${detected}" + String descriptionText = "${device.displayName} smoke ${detected}" return [name:'smoke', value: detected, descriptionText:descriptionText, translatable:true] } -def getAlarmResult(value) { - def alarm = value ? 'siren': 'off' - String descriptionText = "${device.displayName} alarm ${alarm}" - return [name:'alarm', - value: alarm, - descriptionText:descriptionText, - translatable:true] -} -def siren() { - sendEvent(name: "alarm", value: "siren") -} -def off() { - sendEvent(name: "alarm", value: "off") -} def refresh() { log.debug "Refreshing Values" def refreshCmds = [] - refreshCmds += zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER,zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + - zigbee.readAttribute(0x0009,0x0000) + refreshCmds += zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER,zigbee.ATTRIBUTE_IAS_ZONE_STATUS) return refreshCmds } /** * PING is used by Device-Watch in attempt to reach the Device * */ def ping() { - log.debug "ping " + log.debug "ping" refresh() } def configure() { log.debug "configure" - sendEvent(name: "checkInterval", value:20 * 60 + 2*60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) + //The gas heart beat is 30 mintues, so we set double time for one package loss. + sendEvent(name: "checkInterval", value:30 * 2 * 60 + 2*60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) } From c4caa02a0f6bc7d2ebece9e7aefa18c4f2e6fd90 Mon Sep 17 00:00:00 2001 From: zhangjinkang Date: Wed, 18 Jul 2018 06:18:49 -0400 Subject: [PATCH 7/9] format --- .../Orvibo-Gas-detector.groovy | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy index 7dfabfbe68e..29c3d5a5c08 100644 --- a/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy +++ b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy @@ -25,7 +25,7 @@ metadata { capability "Health Check" capability "Sensor" capability "Refresh" - fingerprint profileId: "0104", deviceId: "0402", inClusters: "0000,0003,0500,0009", outClusters: "0019",manufacturer: "Heiman",model:"d0e857bfd54f4a12816295db3945a421" + fingerprint profileId: "0104", deviceId: "0402", inClusters: "0000, 0003, 0500, 0009", outClusters: "0019", manufacturer: "Heiman", model:"d0e857bfd54f4a12816295db3945a421" } simulator { @@ -34,8 +34,8 @@ metadata { tiles { standardTile("smoke", "device.smoke", width: 2, height: 2) { - state("clear", label:"Clear", icon:"st.alarm.smoke.clear", backgroundColor:"#ffffff") - state("detected", label:"Smoke!", icon:"st.alarm.smoke.smoke", backgroundColor:"#e86d13") + state("clear", label: "Clear", icon:"st.alarm.smoke.clear", backgroundColor:"#ffffff") + state("detected", label: "Smoke!", icon:"st.alarm.smoke.smoke", backgroundColor:"#e86d13") } standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 1, height: 1) { state "default", action: "refresh.refresh", icon: "st.secondary.refresh" @@ -44,17 +44,17 @@ metadata { details(["smoke","refresh"]) } } -def installed(){ +def installed() { log.debug "installed" refresh() } def parse(String description) { log.debug "description(): $description" def map = zigbee.getEvent(description) - if(!map){ + if (!map) { if (description?.startsWith('zone status')) { map = parseIasMessage(description) - }else{ + } else { map = zigbee.parseDescriptionAsMap(description) } } @@ -82,7 +82,7 @@ def getDetectedResult(value) { def refresh() { log.debug "Refreshing Values" def refreshCmds = [] - refreshCmds += zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER,zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + refreshCmds += zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) return refreshCmds } /** @@ -95,5 +95,5 @@ def ping() { def configure() { log.debug "configure" //The gas heart beat is 30 mintues, so we set double time for one package loss. - sendEvent(name: "checkInterval", value:30 * 2 * 60 + 2*60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) + sendEvent(name: "checkInterval", value: 30 * 2 * 60 + 2*60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) } From 9e312349de1d8b41ae8b609d47a48e96312dfab5 Mon Sep 17 00:00:00 2001 From: zhangjinkang Date: Tue, 24 Jul 2018 04:07:01 -0400 Subject: [PATCH 8/9] Change gas sensor check interval to 5 mintues for better user experience. Gas has no battey , it can response health check service ping immediately. --- .../orvibo-gas-detector.src/Orvibo-Gas-detector.groovy | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy index 29c3d5a5c08..888db8f3259 100644 --- a/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy +++ b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy @@ -94,6 +94,7 @@ def ping() { } def configure() { log.debug "configure" - //The gas heart beat is 30 mintues, so we set double time for one package loss. - sendEvent(name: "checkInterval", value: 30 * 2 * 60 + 2*60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) + //The gas sensor has no battery , it can response the ping immediately + //so i set the checkTinterval to 5 minutes . + sendEvent(name: "checkInterval", value: 5*60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) } From 34a60cb447c5b7ef0e93961d5848d97a497314f3 Mon Sep 17 00:00:00 2001 From: zhangjinkang Date: Tue, 24 Jul 2018 23:43:59 -0400 Subject: [PATCH 9/9] change the health check interval to the sensor heart beat time 30 mintues. --- .../orvibo-gas-detector.src/Orvibo-Gas-detector.groovy | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy index 888db8f3259..c7f6a00e5e9 100644 --- a/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy +++ b/devicetypes/smartthings/orvibo-gas-detector.src/Orvibo-Gas-detector.groovy @@ -94,7 +94,5 @@ def ping() { } def configure() { log.debug "configure" - //The gas sensor has no battery , it can response the ping immediately - //so i set the checkTinterval to 5 minutes . - sendEvent(name: "checkInterval", value: 5*60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) + sendEvent(name: "checkInterval", value: 30 * 60 + 2 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) }