From c1b6fef521df75803f0d6e9667a9b171283c2d51 Mon Sep 17 00:00:00 2001 From: greens Date: Mon, 6 Jul 2020 17:57:22 -0700 Subject: [PATCH 1/7] CHAD-5172 Send follow-ups to verify that window shade level changes occurred We noticed what seems to be a device bug when window shades send us unsolicited battery reports at the same time they are told to open/close. This seems to cause them to send us immediate position updates rather than waiting until the action is completed. This change should send periodic gets until we see the value we want, up to 5 times, or about 25s after the intial command. --- .../springs-window-fashions-shade.groovy | 38 ++++++++++++---- .../zwave-window-shade.groovy | 43 +++++++++++++------ 2 files changed, 59 insertions(+), 22 deletions(-) diff --git a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy index f60918cd15f..ccaf8a64b4d 100644 --- a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy +++ b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy @@ -164,6 +164,7 @@ private handleLevelReport(physicalgraph.zwave.Command cmd) { shadeValue = "partially open" descriptionText = "${device.displayName} shade is ${level}% open" } + checkLevelReport(level) def levelEvent = createEvent(name: "level", value: level, unit: "%", displayed: false) def stateEvent = createEvent(name: "windowShade", value: shadeValue, descriptionText: descriptionText, isStateChange: levelEvent.isStateChange) @@ -181,15 +182,6 @@ def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelS response(zwave.switchMultilevelV1.switchMultilevelGet().format()) ] } -def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) { - def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId) - updateDataValue("MSR", msr) - if (cmd.manufacturerName) { - updateDataValue("manufacturer", cmd.manufacturerName) - } - createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false]) -} - def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) { def map = [ name: "battery", unit: "%" ] if (cmd.batteryLevel == 0xFF || cmd.batteryLevel == 0) { @@ -222,6 +214,7 @@ def zwaveEvent(physicalgraph.zwave.Command cmd) { def open() { log.debug "open()" def level = switchDirection ? 0 : 99 + levelChangeFollowUp(level) zwave.basicV1.basicSet(value: level).format() // zwave.basicV1.basicSet(value: 0xFF).format() } @@ -229,6 +222,7 @@ def open() { def close() { log.debug "close()" def level = switchDirection ? 99 : 0 + levelChangeFollowUp(level) zwave.basicV1.basicSet(value: level).format() //zwave.basicV1.basicSet(value: 0).format() } @@ -239,6 +233,7 @@ def setLevel(value, duration = null) { level = switchDirection ? 99-level : level if (level < 0) level = 0 if (level > 99) level = 99 + levelChangeFollowUp(level) zwave.basicV1.basicSet(value: level).format() } @@ -266,4 +261,29 @@ def refresh() { zwave.switchMultilevelV1.switchMultilevelGet().format(), zwave.batteryV1.batteryGet().format() ], 1500) +} + +def levelChangeFollowUp(expectedLevel) { + state.expectedValue = expectedLevel + state.levelChecks = 0 + runIn(5, "checkLevel") +} + +def checkLevelReport(value) { + if (state.expectedValue) { + if ((state.expectedValue == 99 && value > 99) || + state.expectedValue == value) { + unschedule("checkLevel") + } + } +} + +def checkLevel() { + if (state.levelChecks != null && state.levelChecks < 5) { + state.levelChecks += 1 + runIn(5, "checkLevel") + response(zwave.switchMultilevelV1.switchMultilevelGet()) + } else { + unschedule("checkLevel") + } } \ No newline at end of file diff --git a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy index 044695d0492..226a06b9849 100644 --- a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy +++ b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy @@ -149,6 +149,7 @@ private handleLevelReport(physicalgraph.zwave.Command cmd) { shadeValue = "partially open" descriptionText = "${device.displayName} shade is ${level}% open" } + checkLevelReport(level) def levelEvent = createEvent(name: "level", value: level, unit: "%", displayed: false) def stateEvent = createEvent(name: "windowShade", value: shadeValue, descriptionText: descriptionText, isStateChange: levelEvent.isStateChange) @@ -166,15 +167,6 @@ def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelS response(zwave.switchMultilevelV1.switchMultilevelGet().format()) ] } -def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) { - def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId) - updateDataValue("MSR", msr) - if (cmd.manufacturerName) { - updateDataValue("manufacturer", cmd.manufacturerName) - } - createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false]) -} - def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) { def map = [ name: "battery", unit: "%" ] if (cmd.batteryLevel == 0xFF) { @@ -194,6 +186,7 @@ def zwaveEvent(physicalgraph.zwave.Command cmd) { } def open() { + levelChangeFollowUp(99) log.debug "open()" /*delayBetween([ zwave.basicV1.basicSet(value: 0xFF).format(), @@ -203,6 +196,7 @@ def open() { } def close() { + levelChangeFollowUp(0) log.debug "close()" /*delayBetween([ zwave.basicV1.basicSet(value: 0x00).format(), @@ -216,10 +210,8 @@ def setLevel(value, duration = null) { Integer level = value as Integer if (level < 0) level = 0 if (level > 99) level = 99 - delayBetween([ - zwave.basicV1.basicSet(value: level).format(), - zwave.switchMultilevelV1.switchMultilevelGet().format() - ]) + levelChangeFollowUp(level) + zwave.basicV1.basicSet(value: level).format() } def presetPosition() { @@ -247,3 +239,28 @@ def refresh() { zwave.batteryV1.batteryGet().format() ], 1500) } + +def levelChangeFollowUp(expectedLevel) { + state.expectedValue = expectedLevel + state.levelChecks = 0 + runIn(5, "checkLevel") +} + +def checkLevelReport(value) { + if (state.expectedValue) { + if ((state.expectedValue == 99 && value > 99) || + state.expectedValue == value) { + unschedule("checkLevel") + } + } +} + +def checkLevel() { + if (state.levelChecks != null && state.levelChecks < 5) { + state.levelChecks += 1 + runIn(5, "checkLevel") + response(zwave.switchMultilevelV1.switchMultilevelGet()) + } else { + unschedule("checkLevel") + } +} From ea58dcd519c8f89762d6cc8eb0cd51cb6e2ace33 Mon Sep 17 00:00:00 2001 From: greens Date: Tue, 7 Jul 2020 15:03:25 -0700 Subject: [PATCH 2/7] fixup --- .../springs-window-fashions-shade.groovy | 2 +- .../zwave-window-shade.src/zwave-window-shade.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy index ccaf8a64b4d..6efa1e59246 100644 --- a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy +++ b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy @@ -282,7 +282,7 @@ def checkLevel() { if (state.levelChecks != null && state.levelChecks < 5) { state.levelChecks += 1 runIn(5, "checkLevel") - response(zwave.switchMultilevelV1.switchMultilevelGet()) + sendHubCommand(zwave.switchMultilevelV1.switchMultilevelGet()) } else { unschedule("checkLevel") } diff --git a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy index 226a06b9849..547debd65f1 100644 --- a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy +++ b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy @@ -259,7 +259,7 @@ def checkLevel() { if (state.levelChecks != null && state.levelChecks < 5) { state.levelChecks += 1 runIn(5, "checkLevel") - response(zwave.switchMultilevelV1.switchMultilevelGet()) + sendHubCommand(zwave.switchMultilevelV1.switchMultilevelGet()) } else { unschedule("checkLevel") } From 0cb73e1df1cc84d68eac747131127fd750169952 Mon Sep 17 00:00:00 2001 From: greens Date: Thu, 9 Jul 2020 14:41:20 -0700 Subject: [PATCH 3/7] logic changes --- .../springs-window-fashions-shade.groovy | 4 ++-- .../zwave-window-shade.src/zwave-window-shade.groovy | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy index 6efa1e59246..84efd164352 100644 --- a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy +++ b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy @@ -270,8 +270,8 @@ def levelChangeFollowUp(expectedLevel) { } def checkLevelReport(value) { - if (state.expectedValue) { - if ((state.expectedValue == 99 && value > 99) || + if (state.expectedValue != null) { + if ((state.expectedValue == 99 && value >= 99) || state.expectedValue == value) { unschedule("checkLevel") } diff --git a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy index 547debd65f1..17e337a5913 100644 --- a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy +++ b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy @@ -247,8 +247,8 @@ def levelChangeFollowUp(expectedLevel) { } def checkLevelReport(value) { - if (state.expectedValue) { - if ((state.expectedValue == 99 && value > 99) || + if (state.expectedValue != null) { + if ((state.expectedValue == 99 && value >= 99) || state.expectedValue == value) { unschedule("checkLevel") } From 640e01a3cd54b0b217a42704238ca18ba5b1b8ff Mon Sep 17 00:00:00 2001 From: greens Date: Fri, 17 Jul 2020 15:26:41 -0700 Subject: [PATCH 4/7] guarantee overwrite --- .../springs-window-fashions-shade.groovy | 4 ++-- .../zwave-window-shade.src/zwave-window-shade.groovy | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy index 84efd164352..35fc3d7891c 100644 --- a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy +++ b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy @@ -266,7 +266,7 @@ def refresh() { def levelChangeFollowUp(expectedLevel) { state.expectedValue = expectedLevel state.levelChecks = 0 - runIn(5, "checkLevel") + runIn(5, "checkLevel", [overwrite: true]) } def checkLevelReport(value) { @@ -281,7 +281,7 @@ def checkLevelReport(value) { def checkLevel() { if (state.levelChecks != null && state.levelChecks < 5) { state.levelChecks += 1 - runIn(5, "checkLevel") + runIn(5, "checkLevel", [overwrite: true]) sendHubCommand(zwave.switchMultilevelV1.switchMultilevelGet()) } else { unschedule("checkLevel") diff --git a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy index 17e337a5913..0d67acb8939 100644 --- a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy +++ b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy @@ -243,7 +243,7 @@ def refresh() { def levelChangeFollowUp(expectedLevel) { state.expectedValue = expectedLevel state.levelChecks = 0 - runIn(5, "checkLevel") + runIn(5, "checkLevel", [overwrite: true]) } def checkLevelReport(value) { @@ -258,7 +258,7 @@ def checkLevelReport(value) { def checkLevel() { if (state.levelChecks != null && state.levelChecks < 5) { state.levelChecks += 1 - runIn(5, "checkLevel") + runIn(5, "checkLevel", [overwrite: true]) sendHubCommand(zwave.switchMultilevelV1.switchMultilevelGet()) } else { unschedule("checkLevel") From e7a231240680b7bdfa662118463da7f481e2cebb Mon Sep 17 00:00:00 2001 From: greens Date: Mon, 20 Jul 2020 13:20:26 -0700 Subject: [PATCH 5/7] state variables do not work with += operator --- .../springs-window-fashions-shade.groovy | 2 +- .../zwave-window-shade.src/zwave-window-shade.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy index 35fc3d7891c..74b36d1abf7 100644 --- a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy +++ b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy @@ -280,7 +280,7 @@ def checkLevelReport(value) { def checkLevel() { if (state.levelChecks != null && state.levelChecks < 5) { - state.levelChecks += 1 + state.levelChecks = state.levelChecks + 1 runIn(5, "checkLevel", [overwrite: true]) sendHubCommand(zwave.switchMultilevelV1.switchMultilevelGet()) } else { diff --git a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy index 0d67acb8939..33675bdeef8 100644 --- a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy +++ b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy @@ -257,7 +257,7 @@ def checkLevelReport(value) { def checkLevel() { if (state.levelChecks != null && state.levelChecks < 5) { - state.levelChecks += 1 + state.levelChecks = state.levelChecks + 1 runIn(5, "checkLevel", [overwrite: true]) sendHubCommand(zwave.switchMultilevelV1.switchMultilevelGet()) } else { From 2fa1a4a19035f5ba14393f0ccbdaedef98b5628a Mon Sep 17 00:00:00 2001 From: greens Date: Mon, 20 Jul 2020 13:24:37 -0700 Subject: [PATCH 6/7] add a +/- 2 range for the level --- .../springs-window-fashions-shade.groovy | 2 +- .../zwave-window-shade.src/zwave-window-shade.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy index 74b36d1abf7..8ce39750e8a 100644 --- a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy +++ b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy @@ -272,7 +272,7 @@ def levelChangeFollowUp(expectedLevel) { def checkLevelReport(value) { if (state.expectedValue != null) { if ((state.expectedValue == 99 && value >= 99) || - state.expectedValue == value) { + (state.expectedValue >= value - 2 && state.expectedValue <= value + 2 )) { unschedule("checkLevel") } } diff --git a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy index 33675bdeef8..e1be70a0aec 100644 --- a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy +++ b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy @@ -249,7 +249,7 @@ def levelChangeFollowUp(expectedLevel) { def checkLevelReport(value) { if (state.expectedValue != null) { if ((state.expectedValue == 99 && value >= 99) || - state.expectedValue == value) { + (state.expectedValue >= value - 2 && state.expectedValue <= value + 2 )) { unschedule("checkLevel") } } From 7c2bee0d45de04d6d2c2e6562f97022b7cf52906 Mon Sep 17 00:00:00 2001 From: greens Date: Mon, 20 Jul 2020 14:03:19 -0700 Subject: [PATCH 7/7] spacing fix and re-arrange logic --- .../springs-window-fashions-shade.groovy | 2 +- .../zwave-window-shade.src/zwave-window-shade.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy index 8ce39750e8a..7af556576ba 100644 --- a/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy +++ b/devicetypes/smartthings/springs-window-fashions-shade.src/springs-window-fashions-shade.groovy @@ -272,7 +272,7 @@ def levelChangeFollowUp(expectedLevel) { def checkLevelReport(value) { if (state.expectedValue != null) { if ((state.expectedValue == 99 && value >= 99) || - (state.expectedValue >= value - 2 && state.expectedValue <= value + 2 )) { + (value >= state.expectedValue - 2 && value <= state.expectedValue + 2)) { unschedule("checkLevel") } } diff --git a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy index e1be70a0aec..c43694d37e9 100644 --- a/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy +++ b/devicetypes/smartthings/zwave-window-shade.src/zwave-window-shade.groovy @@ -249,7 +249,7 @@ def levelChangeFollowUp(expectedLevel) { def checkLevelReport(value) { if (state.expectedValue != null) { if ((state.expectedValue == 99 && value >= 99) || - (state.expectedValue >= value - 2 && state.expectedValue <= value + 2 )) { + (value >= state.expectedValue - 2 && value <= state.expectedValue + 2)) { unschedule("checkLevel") } }