From 25ef9e1c1878fe8eabad18229072b32dd7646cc9 Mon Sep 17 00:00:00 2001 From: "Bartlomiej Janusz/Home IoT Development (IoT) /SRPOL/Associate/Samsung Electronics" Date: Wed, 29 Jul 2020 13:50:30 +0200 Subject: [PATCH 1/4] Handled values for energy and power events --- .../zigbee-metering-plug.groovy | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/devicetypes/smartthings/zigbee-metering-plug.src/zigbee-metering-plug.groovy b/devicetypes/smartthings/zigbee-metering-plug.src/zigbee-metering-plug.groovy index 49c2eeb99cd..a680e7c4900 100755 --- a/devicetypes/smartthings/zigbee-metering-plug.src/zigbee-metering-plug.groovy +++ b/devicetypes/smartthings/zigbee-metering-plug.src/zigbee-metering-plug.groovy @@ -67,8 +67,6 @@ def parse(String description) { log.debug "description is $description" def event = zigbee.getEvent(description) def descMap = zigbee.parseDescriptionAsMap(description) - def powerDiv = 1 - def energyDiv = 100 if (event) { log.info "event enter:$event" @@ -76,10 +74,10 @@ def parse(String description) { log.info "Ignoring default response with desc map: $descMap" return [:] } else if (event.name== "power") { - event.value = event.value/powerDiv + event.value = event.value/getPowerDiv() event.unit = "W" } else if (event.name== "energy") { - event.value = event.value/energyDiv + event.value = event.value/getEnergyDiv() event.unit = "kWh" } log.info "event outer:$event" @@ -98,13 +96,13 @@ def parse(String description) { if (it.value && it.clusterInt == zigbee.SIMPLE_METERING_CLUSTER && it.attrInt == ATTRIBUTE_HISTORICAL_CONSUMPTION) { log.debug "power" map.name = "power" - map.value = zigbee.convertHexToInt(it.value)/powerDiv + map.value = zigbee.convertHexToInt(it.value)/getPowerDiv() map.unit = "W" } else if (it.value && it.clusterInt == zigbee.SIMPLE_METERING_CLUSTER && it.attrInt == ATTRIBUTE_READING_INFO_SET) { log.debug "energy" map.name = "energy" - map.value = zigbee.convertHexToInt(it.value)/energyDiv + map.value = zigbee.convertHexToInt(it.value)/getEnergyDiv() map.unit = "kWh" } @@ -155,5 +153,18 @@ def configure() { return refresh() + zigbee.onOffConfig() + zigbee.configureReporting(zigbee.SIMPLE_METERING_CLUSTER, ATTRIBUTE_READING_INFO_SET, DataType.UINT48, 1, 600, 1) + - zigbee.electricMeasurementPowerConfig(1, 600, 1) + zigbee.electricMeasurementPowerConfig(1, 600, 1) + + zigbee.simpleMeteringPowerConfig() +} + +private int getPowerDiv() { + isSengledOutlet() ? 10 : 1 +} + +private int getEnergyDiv() { + isSengledOutlet() ? 10000 : 100 +} + +private boolean isSengledOutlet() { + device.getDataValue("model") == "E1C-NB7" } \ No newline at end of file From 054e5e12852274dc8d2fcf6f5d4c7bd5c09e7813 Mon Sep 17 00:00:00 2001 From: PKacprowiczS <41617389+PKacprowiczS@users.noreply.github.com> Date: Thu, 30 Jul 2020 20:12:22 +0200 Subject: [PATCH 2/4] WWST-6286 Added fingerprint and some tweaks for Aeotec Radiator Thermostat (#38798) --- .../zwave-radiator-thermostat.groovy | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/devicetypes/smartthings/zwave-radiator-thermostat.src/zwave-radiator-thermostat.groovy b/devicetypes/smartthings/zwave-radiator-thermostat.src/zwave-radiator-thermostat.groovy index a4c79ca74ab..7e4ee20830b 100644 --- a/devicetypes/smartthings/zwave-radiator-thermostat.src/zwave-radiator-thermostat.groovy +++ b/devicetypes/smartthings/zwave-radiator-thermostat.src/zwave-radiator-thermostat.groovy @@ -27,6 +27,7 @@ metadata { //this DTH is sending temperature setpoint commands using Celsius scale and assumes that they'll be handled correctly by device //if new device added to this DTH won't be able to do that, make sure to you'll handle conversion in a right way fingerprint mfr: "0002", prod: "0115", model: "A010", deviceJoinName: "POPP Thermostat", mnmn: "SmartThings", vid: "generic-radiator-thermostat-2" //POPP Radiator Thermostat Valve + fingerprint mfr: "0371", prod: "0002", model: "0015", deviceJoinName: "Aeotec Thermostat", mnmn: "SmartThings", vid: "aeotec-radiator-thermostat" //Aeotec Radiator Thermostat ZWA021 } tiles(scale: 2) { @@ -168,6 +169,7 @@ def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeRepor map.value = "heat" break case 11: + case 15: map.value = "emergency heat" break case 0: @@ -213,7 +215,11 @@ def setThermostatMode(String mode) { modeValue = 1 break case "emergency heat": - modeValue = 11 + if (isAeotecRadiatorThermostat()) { + modeValue = 15 + } else { + modeValue = 11 + } break case "off": modeValue = 0 @@ -295,7 +301,7 @@ def multiEncap(cmds) { private getMaxHeatingSetpointTemperature() { if (isEverspringRadiatorThermostat()) { temperatureScale == 'C' ? 35 : 95 - } else if (isPoppRadiatorThermostat()) { + } else if (isPoppRadiatorThermostat() || isAeotecRadiatorThermostat()) { temperatureScale == 'C' ? 28 : 82 } else { temperatureScale == 'C' ? 30 : 86 @@ -307,13 +313,15 @@ private getMinHeatingSetpointTemperature() { temperatureScale == 'C' ? 15 : 59 } else if (isPoppRadiatorThermostat()) { temperatureScale == 'C' ? 4 : 39 + } else if (isAeotecRadiatorThermostat()) { + temperatureScale == 'C' ? 8 : 47 } else { temperatureScale == 'C' ? 10 : 50 } } private getThermostatSupportedModes() { - if (isEverspringRadiatorThermostat()) { + if (isEverspringRadiatorThermostat() || isAeotecRadiatorThermostat()) { ["off", "heat", "emergency heat"] } else if (isPoppRadiatorThermostat()) { //that's just for looking fine in Classic ["heat"] @@ -336,4 +344,8 @@ private isEverspringRadiatorThermostat() { private isPoppRadiatorThermostat() { zwaveInfo.mfr == "0002" && zwaveInfo.prod == "0115" +} + +private isAeotecRadiatorThermostat() { + zwaveInfo.mfr == "0371" && zwaveInfo.prod == "0002" } \ No newline at end of file From 94885a1a066a19debe9117d21f386f20f1080c9c Mon Sep 17 00:00:00 2001 From: Konrad K <33450498+KKlimczukS@users.noreply.github.com> Date: Mon, 3 Aug 2020 19:42:10 +0200 Subject: [PATCH 3/4] ICP-13200 - longer delay between BasicSet and BasicGet commands (#38875) --- .../fibaro-walli-double-switch.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devicetypes/fibargroup/fibaro-walli-double-switch.src/fibaro-walli-double-switch.groovy b/devicetypes/fibargroup/fibaro-walli-double-switch.src/fibaro-walli-double-switch.groovy index cc5a990f53d..a6357b31202 100644 --- a/devicetypes/fibargroup/fibaro-walli-double-switch.src/fibaro-walli-double-switch.groovy +++ b/devicetypes/fibargroup/fibaro-walli-double-switch.src/fibaro-walli-double-switch.groovy @@ -346,7 +346,7 @@ private onOffCmd(value, endpoint = 1) { delayBetween([ encap(zwave.basicV1.basicSet(value: value), endpoint), encap(zwave.basicV1.basicGet(), endpoint) - ]) + ], 1000) } private refreshAll(includeMeterGet = true) { From 773d630de1c2dd329df09fd28bd65f48923c74e0 Mon Sep 17 00:00:00 2001 From: Steven Green Date: Tue, 4 Aug 2020 10:53:47 -0700 Subject: [PATCH 4/4] CHAD-5355 Zigbee lock event de-duplication (#39101) * Uses logic similar to what we do in z-wave locks to delay events created from lock attribute reports in case we receive a much more detailed operation event later. If the operation event is sent first, the lock attribute event will be marked as not displayed. * always delay lock attribute reports * add log message * fixup * fixup --- .../zigbee-lock-without-codes.groovy | 14 ++++++++++++++ .../smartthings/zigbee-lock.src/zigbee-lock.groovy | 14 ++++++++++++++ 2 files changed, 28 insertions(+) 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 index fe89eca8655..1844303ae48 100644 --- 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 @@ -207,6 +207,15 @@ private def parseAttributeResponse(String description) { responseMap.value = "unknown" responseMap.descriptionText = "Unknown state" } + if (responseMap.value) { + /* delay this event for a second in the hopes that we get the operation event (which has more info). + If we don't get one, then it's okay to send. If we send the event with more info first, the event + with less info will be marked as not displayed + */ + log.debug "Lock attribute report received: ${responseMap.value}. Delaying event." + runIn(1, "delayLockEvent", [data : [map : responseMap]]) + return [:] + } } else { return null } @@ -214,6 +223,11 @@ private def parseAttributeResponse(String description) { return result } +def delayLockEvent(data) { + log.debug "Sending cached lock operation: ${data.map}" + sendEvent(data.map) +} + private def parseIasMessage(String description) { ZoneStatus zs = zigbee.parseZoneStatus(description) def responseMap = [ name: "battery", value: zs.isBatterySet() ? 5 : 55] diff --git a/devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy b/devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy index 0d489842b89..323f6dd7867 100644 --- a/devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy +++ b/devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy @@ -493,6 +493,15 @@ private def parseAttributeResponse(String description) { responseMap.value = "unknown" responseMap.descriptionText = "Unknown state" } + if (responseMap.value) { + /* delay this event for a second in the hopes that we get the operation event (which has more info). + If we don't get one, then it's okay to send. If we send the event with more info first, the event + with less info will be marked as not displayed + */ + log.debug "Lock attribute report received: ${responseMap.value}. Delaying event." + runIn(1, "delayLockEvent", [data : [map : responseMap]]) + return [:] + } } else if (clusterInt == CLUSTER_DOORLOCK && attrInt == DOORLOCK_ATTR_MIN_PIN_LENGTH && descMap.value) { def minCodeLength = Integer.parseInt(descMap.value, 16) responseMap = [name: "minCodeLength", value: minCodeLength, descriptionText: "Minimum PIN length is ${minCodeLength}", displayed: false] @@ -517,6 +526,11 @@ private def parseAttributeResponse(String description) { return result } +def delayLockEvent(data) { + log.debug "Sending cached lock operation: ${data.map}" + sendEvent(data.map) +} + /** * Responsible for handling command responses *