From 34882b90f3b6d78822164b8663706b5662534275 Mon Sep 17 00:00:00 2001 From: dcmeglio Date: Thu, 28 Nov 2019 08:54:22 -0500 Subject: [PATCH 1/5] initial support for rfx events --- ...er-virtual-carbon-monoxide-detector.groovy | 9 ++++ ...alarmdecoder-virtual-contact-sensor.groovy | 9 ++++ ...larmdecoder-virtual-motion-detector.groovy | 9 ++++ .../alarmdecoder-virtual-shock-sensor.groovy | 9 ++++ .../alarmdecoder-virtual-smoke-alarm.groovy | 9 ++++ .../alarmdecoder-service.groovy | 53 +++++++++++++++---- 6 files changed, 89 insertions(+), 9 deletions(-) diff --git a/devicetypes/alarmdecoder/alarmdecoder-virtual-carbon-monoxide-detector.src/alarmdecoder-virtual-carbon-monoxide-detector.groovy b/devicetypes/alarmdecoder/alarmdecoder-virtual-carbon-monoxide-detector.src/alarmdecoder-virtual-carbon-monoxide-detector.groovy index d7104d8..deaa670 100644 --- a/devicetypes/alarmdecoder/alarmdecoder-virtual-carbon-monoxide-detector.src/alarmdecoder-virtual-carbon-monoxide-detector.groovy +++ b/devicetypes/alarmdecoder/alarmdecoder-virtual-carbon-monoxide-detector.src/alarmdecoder-virtual-carbon-monoxide-detector.groovy @@ -28,6 +28,8 @@ metadata { namespace: APPNAMESPACE, author: "Nu Tech Software Solutions, Inc.") { capability "CarbonMonoxideDetector" + attribute "low_battery", "bool" + attribute "last_checkin", "number" } // tile definitions @@ -67,6 +69,11 @@ metadata { title: "Zone Number", description: "Zone # required for zone events.", required: false) + input( + name: "serial", type: + "string", title: "Serial Number", + description: "The serial number of an RF device.", + required: false) } } @@ -82,9 +89,11 @@ metadata { def installed() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) + updateDataValue("serial", serial) } def updated() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) + updateDataValue("serial", serial) } diff --git a/devicetypes/alarmdecoder/alarmdecoder-virtual-contact-sensor.src/alarmdecoder-virtual-contact-sensor.groovy b/devicetypes/alarmdecoder/alarmdecoder-virtual-contact-sensor.src/alarmdecoder-virtual-contact-sensor.groovy index 0167270..aff27d2 100644 --- a/devicetypes/alarmdecoder/alarmdecoder-virtual-contact-sensor.src/alarmdecoder-virtual-contact-sensor.groovy +++ b/devicetypes/alarmdecoder/alarmdecoder-virtual-contact-sensor.src/alarmdecoder-virtual-contact-sensor.groovy @@ -28,6 +28,8 @@ metadata { namespace: APPNAMESPACE, author: "Nu Tech Software Solutions, Inc.") { capability "Contact Sensor" + attribute "low_battery", "bool" + attribute "last_checkin", "number" } // tile definitions @@ -66,6 +68,11 @@ metadata { "number", title: "Zone Number", description: "Zone # required for zone events.", required: false) + input( + name: "serial", type: + "string", title: "Serial Number", + description: "The serial number of an RF device.", + required: false) } } @@ -81,9 +88,11 @@ metadata { def installed() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) + updateDataValue("serial", serial) } def updated() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) + updateDataValue("serial", serial) } diff --git a/devicetypes/alarmdecoder/alarmdecoder-virtual-motion-detector.src/alarmdecoder-virtual-motion-detector.groovy b/devicetypes/alarmdecoder/alarmdecoder-virtual-motion-detector.src/alarmdecoder-virtual-motion-detector.groovy index c7e948d..b011ca5 100644 --- a/devicetypes/alarmdecoder/alarmdecoder-virtual-motion-detector.src/alarmdecoder-virtual-motion-detector.groovy +++ b/devicetypes/alarmdecoder/alarmdecoder-virtual-motion-detector.src/alarmdecoder-virtual-motion-detector.groovy @@ -28,6 +28,8 @@ metadata { namespace: APPNAMESPACE, author: "Nu Tech Software Solutions, Inc.") { capability "Motion Sensor" + attribute "low_battery", "bool" + attribute "last_checkin", "number" } // tile definitions @@ -69,6 +71,11 @@ metadata { title: "Zone Number", description: "Zone # required for zone events.", required: false) + input( + name: "serial", type: + "string", title: "Serial Number", + description: "The serial number of an RF device.", + required: false) } } @@ -84,11 +91,13 @@ metadata { def installed() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) + updateDataValue("serial", serial) } def updated() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) + updateDataValue("serial", serial) } // FIXME: what? diff --git a/devicetypes/alarmdecoder/alarmdecoder-virtual-shock-sensor.src/alarmdecoder-virtual-shock-sensor.groovy b/devicetypes/alarmdecoder/alarmdecoder-virtual-shock-sensor.src/alarmdecoder-virtual-shock-sensor.groovy index f8c838e..99cb1c0 100644 --- a/devicetypes/alarmdecoder/alarmdecoder-virtual-shock-sensor.src/alarmdecoder-virtual-shock-sensor.groovy +++ b/devicetypes/alarmdecoder/alarmdecoder-virtual-shock-sensor.src/alarmdecoder-virtual-shock-sensor.groovy @@ -28,6 +28,8 @@ metadata { namespace: APPNAMESPACE, author: "Nu Tech Software Solutions, Inc.") { capability "ShockSensor" + attribute "low_battery", "bool" + attribute "last_checkin", "number" } // tile definitions @@ -68,6 +70,11 @@ metadata { title: "Zone Number", description: "Zone # required for zone events.", required: false) + input( + name: "serial", type: + "string", title: "Serial Number", + description: "The serial number of an RF device.", + required: false) } } @@ -83,9 +90,11 @@ metadata { def installed() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) + updateDataValue("serial", serial) } def updated() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) + updateDataValue("serial", serial) } diff --git a/devicetypes/alarmdecoder/alarmdecoder-virtual-smoke-alarm.src/alarmdecoder-virtual-smoke-alarm.groovy b/devicetypes/alarmdecoder/alarmdecoder-virtual-smoke-alarm.src/alarmdecoder-virtual-smoke-alarm.groovy index a0a6ffe..8d76f49 100644 --- a/devicetypes/alarmdecoder/alarmdecoder-virtual-smoke-alarm.src/alarmdecoder-virtual-smoke-alarm.groovy +++ b/devicetypes/alarmdecoder/alarmdecoder-virtual-smoke-alarm.src/alarmdecoder-virtual-smoke-alarm.groovy @@ -28,6 +28,8 @@ metadata { namespace: APPNAMESPACE, author: "Nu Tech Software Solutions, Inc.") { capability "Smoke Detector" + attribute "low_battery", "bool" + attribute "last_checkin", "number" } // tile definitions @@ -67,6 +69,11 @@ metadata { title: "Zone Number", description: "Zone # required for zone events.", required: false) + input( + name: "serial", type: + "string", title: "Serial Number", + description: "The serial number of an RF device.", + required: false) } } @@ -82,9 +89,11 @@ metadata { def installed() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) + updateDataValue("serial", serial) } def updated() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) + updateDataValue("serial", serial) } diff --git a/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy b/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy index 1e4a9cd..4bb1181 100644 --- a/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy +++ b/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy @@ -2023,6 +2023,41 @@ def rfxSet(evt) { sent = true } else { + def d = getChildDevices().findAll { + it.deviceNetworkId.contains(":switch") && + it.getDataValue("serial") == sn + } + + if (d) { + if (loop1 == "1" || loop2 == "1" || loop3 == "1" || loop4 == "1") { + d.each { + _sendEventTranslate(it, ("on"), false) + } + } + else { + d.each { + _sendEventTranslate(it, ("off"), false) + } + + d.each { + it.sendEvent( + name: "low_battery", + value: bat == "1" + ) + } + + if (supv == "1") { + def last_checkin = now() + d.each { + it.sendEvent( + name: "last_checkin", + value: last_checkin + ) + } + } + } + + } if (debug) log.info("rfxSet device: ${device_name} no match ${match}") } } @@ -2092,7 +2127,7 @@ def zoneOn(evt) { // Find all :switch devices with a matching zone the event. def d = getChildDevices().findAll { it.deviceNetworkId.contains(":switch") && - it.getDataValue("zone") == evt.value + it.getDataValue("zone") == evt.value && it.getDataValue("serial") == null } if (d) { @@ -2114,7 +2149,7 @@ def zoneOff(evt) { def d = getChildDevices().findAll { it.deviceNetworkId.contains(":switch") && - it.getDataValue("zone") == evt.value + it.getDataValue("zone") == evt.value && it.getDataValue("serial") == null } if (d) { @@ -3039,7 +3074,7 @@ private getDeviceNamePart(d) { * Default clear = off, detected(Alerting) = on * */ -def _sendEventTranslate(ad2d, state) { +def _sendEventTranslate(ad2d, state, stateChange = true) { // Grab the devices preferences for inverting def invert = (ad2d.device.getDataValue("invert") == "true" ? true : false) @@ -3057,7 +3092,7 @@ def _sendEventTranslate(ad2d, state) { ad2d.sendEvent( name: "switch", value: (sval ? "on" : "off"), - isStateChange: true, + isStateChange: stateChange, filtered: true ) } @@ -3075,7 +3110,7 @@ def _sendEventTranslate(ad2d, state) { ad2d.sendEvent( name: "contact", value: (sval ? "open" : "closed"), - isStateChange: true, + isStateChange: stateChange, filtered: true ) } @@ -3093,7 +3128,7 @@ def _sendEventTranslate(ad2d, state) { ad2d.sendEvent( name: "motion", value: (sval ? "active" : "inactive"), - isStateChange: true, + isStateChange: stateChange, filtered: true ) } @@ -3111,7 +3146,7 @@ def _sendEventTranslate(ad2d, state) { ad2d.sendEvent( name: "shock", value: (sval ? "detected" : "clear"), - isStateChange: true, + isStateChange: stateChange, filtered: true ) } @@ -3129,7 +3164,7 @@ def _sendEventTranslate(ad2d, state) { ad2d.sendEvent( name: "carbonMonoxide", value: (sval ? "detected" : "clear"), - isStateChange: true, + isStateChange: stateChange, filtered: true ) } @@ -3147,7 +3182,7 @@ def _sendEventTranslate(ad2d, state) { ad2d.sendEvent( name: "smoke", value: (sval ? "detected" : "clear"), - isStateChange: true, + isStateChange: stateChange, filtered: true ) } From 83a81f90b69a805492a446dd0c954b062136eec5 Mon Sep 17 00:00:00 2001 From: dcmeglio Date: Thu, 28 Nov 2019 14:25:35 -0500 Subject: [PATCH 2/5] fixed a few careless bugs from copy/pasting --- .../alarmdecoder-service.groovy | 79 ++++++++++--------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy b/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy index 4bb1181..8dd6073 100644 --- a/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy +++ b/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy @@ -1986,6 +1986,43 @@ def rfxSet(evt) { def device_name = "RFX-${sn}-${bat}-${supv}-" + "${loop0}-${loop1}-${loop2}-${loop3}" + def d = getChildDevices().findAll { + it.deviceNetworkId.contains(":switch") && + it.getDataValue("serial") == sn + } + + if (d) { + if (loop1 == "1" || loop2 == "1" || loop3 == "1" || loop4 == "1") { + d.each { + _sendEventTranslate(it, ("on"), false) + } + } + else { + d.each { + _sendEventTranslate(it, ("off"), false) + } + + d.each { + it.sendEvent( + name: "low_battery", + value: bat == "1" + ) + } + + if (supv == "1") { + def last_checkin = now() + d.each { + it.sendEvent( + name: "last_checkin", + value: last_checkin + ) + } + } + } + + } + + def children = getChildDevices() children.each { if (it.deviceNetworkId.contains(":RFX-")) { @@ -2022,46 +2059,10 @@ def rfxSet(evt) { sent = true - } else { - def d = getChildDevices().findAll { - it.deviceNetworkId.contains(":switch") && - it.getDataValue("serial") == sn - } - - if (d) { - if (loop1 == "1" || loop2 == "1" || loop3 == "1" || loop4 == "1") { - d.each { - _sendEventTranslate(it, ("on"), false) - } - } - else { - d.each { - _sendEventTranslate(it, ("off"), false) - } - - d.each { - it.sendEvent( - name: "low_battery", - value: bat == "1" - ) - } - - if (supv == "1") { - def last_checkin = now() - d.each { - it.sendEvent( - name: "last_checkin", - value: last_checkin - ) - } - } - } - - } - if (debug) log.info("rfxSet device: ${device_name} no match ${match}") - } + } } - } + + } if (!sent) { log.warn("rfxSet: Could not find '${device_name}|XXX' device.") From ca3592aa4eaad2e32f62293513458a17cade1f59 Mon Sep 17 00:00:00 2001 From: dcmeglio Date: Fri, 29 Nov 2019 10:34:56 -0500 Subject: [PATCH 3/5] fixed spacing --- .../alarmdecoder-service.groovy | 71 +++++++++---------- 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy b/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy index 8dd6073..e0df4cd 100644 --- a/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy +++ b/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy @@ -1986,42 +1986,40 @@ def rfxSet(evt) { def device_name = "RFX-${sn}-${bat}-${supv}-" + "${loop0}-${loop1}-${loop2}-${loop3}" - def d = getChildDevices().findAll { - it.deviceNetworkId.contains(":switch") && - it.getDataValue("serial") == sn - } - - if (d) { - if (loop1 == "1" || loop2 == "1" || loop3 == "1" || loop4 == "1") { - d.each { - _sendEventTranslate(it, ("on"), false) - } - } - else { - d.each { - _sendEventTranslate(it, ("off"), false) - } - - d.each { - it.sendEvent( - name: "low_battery", - value: bat == "1" - ) - } - - if (supv == "1") { - def last_checkin = now() - d.each { - it.sendEvent( - name: "last_checkin", - value: last_checkin - ) - } - } - } - - } - + def d = getChildDevices().findAll { + it.deviceNetworkId.contains(":switch") && + it.getDataValue("serial") == sn + } + + if (d) { + if (loop1 == "1" || loop2 == "1" || loop3 == "1" || loop4 == "1") { + d.each { + _sendEventTranslate(it, ("on"), false) + } + } + else { + d.each { + _sendEventTranslate(it, ("off"), false) + } + } + + d.each { + it.sendEvent( + name: "low_battery", + value: bat == "1" + ) + } + + if (supv == "1") { + def last_checkin = now() + d.each { + it.sendEvent( + name: "last_checkin", + value: last_checkin + ) + } + } + } def children = getChildDevices() children.each { @@ -2061,7 +2059,6 @@ def rfxSet(evt) { } } - } if (!sent) { From b5c548eef659b6d1f995480df5e0d6f73d8d3049 Mon Sep 17 00:00:00 2001 From: dcmeglio Date: Sun, 1 Dec 2019 17:26:53 -0500 Subject: [PATCH 4/5] fixed a mistake with the loop numbers being off by 1 --- .../alarmdecoder-service.src/alarmdecoder-service.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy b/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy index e0df4cd..4f8b68f 100644 --- a/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy +++ b/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy @@ -1992,7 +1992,7 @@ def rfxSet(evt) { } if (d) { - if (loop1 == "1" || loop2 == "1" || loop3 == "1" || loop4 == "1") { + if (loop0 == "1" || loop1 == "1" || loop2 == "1" || loop3 == "1") { d.each { _sendEventTranslate(it, ("on"), false) } From 3cfe680d374fc255386bb45b34fa5e570b5f5384 Mon Sep 17 00:00:00 2001 From: dcmeglio Date: Sun, 8 Dec 2019 17:05:59 -0500 Subject: [PATCH 5/5] added the ability to distinguish tamper from zone trip faults --- ...er-virtual-carbon-monoxide-detector.groovy | 20 +++++++++++ ...alarmdecoder-virtual-contact-sensor.groovy | 21 ++++++++++++ ...larmdecoder-virtual-motion-detector.groovy | 20 +++++++++++ .../alarmdecoder-virtual-shock-sensor.groovy | 20 +++++++++++ .../alarmdecoder-virtual-smoke-alarm.groovy | 20 +++++++++++ .../alarmdecoder-service.groovy | 34 ++++++++++++++----- 6 files changed, 126 insertions(+), 9 deletions(-) diff --git a/devicetypes/alarmdecoder/alarmdecoder-virtual-carbon-monoxide-detector.src/alarmdecoder-virtual-carbon-monoxide-detector.groovy b/devicetypes/alarmdecoder/alarmdecoder-virtual-carbon-monoxide-detector.src/alarmdecoder-virtual-carbon-monoxide-detector.groovy index deaa670..d68a447 100644 --- a/devicetypes/alarmdecoder/alarmdecoder-virtual-carbon-monoxide-detector.src/alarmdecoder-virtual-carbon-monoxide-detector.groovy +++ b/devicetypes/alarmdecoder/alarmdecoder-virtual-carbon-monoxide-detector.src/alarmdecoder-virtual-carbon-monoxide-detector.groovy @@ -28,6 +28,7 @@ metadata { namespace: APPNAMESPACE, author: "Nu Tech Software Solutions, Inc.") { capability "CarbonMonoxideDetector" + capability "Tamper Alert" attribute "low_battery", "bool" attribute "last_checkin", "number" } @@ -74,6 +75,21 @@ metadata { "string", title: "Serial Number", description: "The serial number of an RF device.", required: false) + if (serial != null) { + input( + name: "zoneLoop", type: + "number", title: "Zone Loop", + range: "1..4", + description: "The loop to use for zone open/close.", + required: true) + input( + name: "tamperLoop", type: + "number", title: "Tamper Loop", + range: "1..4", + description: "The loop to use to detect tamper.", + defaultValue: 4, + required: false) + } } } @@ -90,10 +106,14 @@ def installed() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) updateDataValue("serial", serial) + updateDataValue("zoneLoop", zoneLoop.toString()) + updateDataValue("tamperLoop", tamperLoop.toString()) } def updated() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) updateDataValue("serial", serial) + updateDataValue("zoneLoop", zoneLoop.toString()) + updateDataValue("tamperLoop", tamperLoop.toString()) } diff --git a/devicetypes/alarmdecoder/alarmdecoder-virtual-contact-sensor.src/alarmdecoder-virtual-contact-sensor.groovy b/devicetypes/alarmdecoder/alarmdecoder-virtual-contact-sensor.src/alarmdecoder-virtual-contact-sensor.groovy index aff27d2..6fd0172 100644 --- a/devicetypes/alarmdecoder/alarmdecoder-virtual-contact-sensor.src/alarmdecoder-virtual-contact-sensor.groovy +++ b/devicetypes/alarmdecoder/alarmdecoder-virtual-contact-sensor.src/alarmdecoder-virtual-contact-sensor.groovy @@ -28,6 +28,7 @@ metadata { namespace: APPNAMESPACE, author: "Nu Tech Software Solutions, Inc.") { capability "Contact Sensor" + capability "Tamper Alert" attribute "low_battery", "bool" attribute "last_checkin", "number" } @@ -71,8 +72,24 @@ metadata { input( name: "serial", type: "string", title: "Serial Number", + submitOnChange: true, description: "The serial number of an RF device.", required: false) + if (serial != null) { + input( + name: "zoneLoop", type: + "number", title: "Zone Loop", + range: "1..4", + description: "The loop to use for zone open/close.", + required: true) + input( + name: "tamperLoop", type: + "number", title: "Tamper Loop", + range: "1..4", + description: "The loop to use to detect tamper.", + defaultValue: 4, + required: false) + } } } @@ -89,10 +106,14 @@ def installed() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) updateDataValue("serial", serial) + updateDataValue("zoneLoop", zoneLoop.toString()) + updateDataValue("tamperLoop", tamperLoop.toString()) } def updated() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) updateDataValue("serial", serial) + updateDataValue("zoneLoop", zoneLoop.toString()) + updateDataValue("tamperLoop", tamperLoop.toString()) } diff --git a/devicetypes/alarmdecoder/alarmdecoder-virtual-motion-detector.src/alarmdecoder-virtual-motion-detector.groovy b/devicetypes/alarmdecoder/alarmdecoder-virtual-motion-detector.src/alarmdecoder-virtual-motion-detector.groovy index b011ca5..5fa1e01 100644 --- a/devicetypes/alarmdecoder/alarmdecoder-virtual-motion-detector.src/alarmdecoder-virtual-motion-detector.groovy +++ b/devicetypes/alarmdecoder/alarmdecoder-virtual-motion-detector.src/alarmdecoder-virtual-motion-detector.groovy @@ -28,6 +28,7 @@ metadata { namespace: APPNAMESPACE, author: "Nu Tech Software Solutions, Inc.") { capability "Motion Sensor" + capability "Tamper Alert" attribute "low_battery", "bool" attribute "last_checkin", "number" } @@ -76,6 +77,21 @@ metadata { "string", title: "Serial Number", description: "The serial number of an RF device.", required: false) + if (serial != null) { + input( + name: "zoneLoop", type: + "number", title: "Zone Loop", + range: "1..4", + description: "The loop to use for zone open/close.", + required: true) + input( + name: "tamperLoop", type: + "number", title: "Tamper Loop", + range: "1..4", + description: "The loop to use to detect tamper.", + defaultValue: 4, + required: false) + } } } @@ -92,12 +108,16 @@ def installed() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) updateDataValue("serial", serial) + updateDataValue("zoneLoop", zoneLoop.toString()) + updateDataValue("tamperLoop", tamperLoop.toString()) } def updated() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) updateDataValue("serial", serial) + updateDataValue("zoneLoop", zoneLoop.toString()) + updateDataValue("tamperLoop", tamperLoop.toString()) } // FIXME: what? diff --git a/devicetypes/alarmdecoder/alarmdecoder-virtual-shock-sensor.src/alarmdecoder-virtual-shock-sensor.groovy b/devicetypes/alarmdecoder/alarmdecoder-virtual-shock-sensor.src/alarmdecoder-virtual-shock-sensor.groovy index 99cb1c0..97e0527 100644 --- a/devicetypes/alarmdecoder/alarmdecoder-virtual-shock-sensor.src/alarmdecoder-virtual-shock-sensor.groovy +++ b/devicetypes/alarmdecoder/alarmdecoder-virtual-shock-sensor.src/alarmdecoder-virtual-shock-sensor.groovy @@ -28,6 +28,7 @@ metadata { namespace: APPNAMESPACE, author: "Nu Tech Software Solutions, Inc.") { capability "ShockSensor" + capability "Tamper Alert" attribute "low_battery", "bool" attribute "last_checkin", "number" } @@ -75,6 +76,21 @@ metadata { "string", title: "Serial Number", description: "The serial number of an RF device.", required: false) + if (serial != null) { + input( + name: "zoneLoop", type: + "number", title: "Zone Loop", + range: "1..4", + description: "The loop to use for zone open/close.", + required: true) + input( + name: "tamperLoop", type: + "number", title: "Tamper Loop", + range: "1..4", + description: "The loop to use to detect tamper.", + defaultValue: 4, + required: false) + } } } @@ -91,10 +107,14 @@ def installed() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) updateDataValue("serial", serial) + updateDataValue("zoneLoop", zoneLoop.toString()) + updateDataValue("tamperLoop", tamperLoop.toString()) } def updated() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) updateDataValue("serial", serial) + updateDataValue("zoneLoop", zoneLoop.toString()) + updateDataValue("tamperLoop", tamperLoop.toString()) } diff --git a/devicetypes/alarmdecoder/alarmdecoder-virtual-smoke-alarm.src/alarmdecoder-virtual-smoke-alarm.groovy b/devicetypes/alarmdecoder/alarmdecoder-virtual-smoke-alarm.src/alarmdecoder-virtual-smoke-alarm.groovy index 8d76f49..a05c60c 100644 --- a/devicetypes/alarmdecoder/alarmdecoder-virtual-smoke-alarm.src/alarmdecoder-virtual-smoke-alarm.groovy +++ b/devicetypes/alarmdecoder/alarmdecoder-virtual-smoke-alarm.src/alarmdecoder-virtual-smoke-alarm.groovy @@ -28,6 +28,7 @@ metadata { namespace: APPNAMESPACE, author: "Nu Tech Software Solutions, Inc.") { capability "Smoke Detector" + capability "Tamper Alert" attribute "low_battery", "bool" attribute "last_checkin", "number" } @@ -74,6 +75,21 @@ metadata { "string", title: "Serial Number", description: "The serial number of an RF device.", required: false) + if (serial != null) { + input( + name: "zoneLoop", type: + "number", title: "Zone Loop", + range: "1..4", + description: "The loop to use for zone open/close.", + required: true) + input( + name: "tamperLoop", type: + "number", title: "Tamper Loop", + range: "1..4", + description: "The loop to use to detect tamper.", + defaultValue: 4, + required: false) + } } } @@ -90,10 +106,14 @@ def installed() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) updateDataValue("serial", serial) + updateDataValue("zoneLoop", zoneLoop.toString()) + updateDataValue("tamperLoop", tamperLoop.toString()) } def updated() { updateDataValue("invert", invert.toString()) updateDataValue("zone", zone.toString()) updateDataValue("serial", serial) + updateDataValue("zoneLoop", zoneLoop.toString()) + updateDataValue("tamperLoop", tamperLoop.toString()) } diff --git a/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy b/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy index 4f8b68f..6e0c1fc 100644 --- a/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy +++ b/smartapps/alarmdecoder/alarmdecoder-service.src/alarmdecoder-service.groovy @@ -1992,15 +1992,31 @@ def rfxSet(evt) { } if (d) { - if (loop0 == "1" || loop1 == "1" || loop2 == "1" || loop3 == "1") { - d.each { - _sendEventTranslate(it, ("on"), false) - } - } - else { - d.each { - _sendEventTranslate(it, ("off"), false) - } + d.each { + def zoneLoop = it.getDataValue("zoneLoop") + def tamperLoop = it.getDataValue("tamperLoop") + + if (zoneLoop != null && zoneLoop != "null") { + if ((zoneLoop == "1" && loop0 == "1") || (zoneLoop == "2" && loop1 == "1") || (zoneLoop == "3" && loop2 == "1") || (zoneLoop == "4" && loop3 == "1")) { + _sendEventTranslate(it, ("on"), false) + } else { + _sendEventTranslate(it, ("off"), false) + } + } + + if (tamperLoop != null && tamperLoop != "null") { + if ((tamperLoop == "1" && loop0 == "1") || (tamperLoop == "2" && loop1 == "1") || (tamperLoop == "3" && loop2 == "1") || (tamperLoop == "4" && loop3 == "1")) { + it.sendEvent( + name: "tamper", + value: "detected" + ) + } else { + it.sendEvent( + name: "tamper", + value: "clear" + ) + } + } } d.each {