From 567e0915624e19aed2983adbf164b366e6b833c9 Mon Sep 17 00:00:00 2001 From: MGoralczykS <42434140+MGoralczykS@users.noreply.github.com> Date: Wed, 22 Jul 2020 19:53:59 +0200 Subject: [PATCH 01/12] [WWST-2446_2447] Add Qubino Relay 1/1D to existing DTH (#37124) * Add Qubino Relay 1/1D to existing DTH --- .../qubino-flush-2-relay.groovy | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/devicetypes/qubino/qubino-flush-2-relay.src/qubino-flush-2-relay.groovy b/devicetypes/qubino/qubino-flush-2-relay.src/qubino-flush-2-relay.groovy index 431dadc8a5e..2dbeb85dd8b 100644 --- a/devicetypes/qubino/qubino-flush-2-relay.src/qubino-flush-2-relay.groovy +++ b/devicetypes/qubino/qubino-flush-2-relay.src/qubino-flush-2-relay.groovy @@ -24,6 +24,8 @@ metadata { command "reset" fingerprint mfr: "0159", prod: "0002", model: "0051", deviceJoinName: "Qubino Switch 1" //Qubino Flush 2 Relay + fingerprint mfr: "0159", prod: "0002", model: "0052", deviceJoinName: "Qubino Switch" //Qubino Flush 1 Relay + fingerprint mfr: "0159", prod: "0002", model: "0053", deviceJoinName: "Qubino Switch" //Qubino Flush 1D Relay } tiles(scale: 2) { @@ -70,7 +72,12 @@ metadata { } def installed() { - state.numberOfSwitches = 2 + if (zwaveInfo?.model.equals("0051")) { + state.numberOfSwitches = 2 + } else { + state.numberOfSwitches = 1 + } + if (!childDevices) { addChildSwitches(state.numberOfSwitches) } @@ -93,7 +100,7 @@ def updated() { } // Preferences template begin parameterMap.each { - if (isPreferenceChanged(it)) { + if (isPreferenceChanged(it) && !excludeParameterFromSync(it)) { log.debug "Preference ${it.key} has been updated from value: ${state.currentPreferencesState."$it.key".value} to ${settings."$it.key"}" state.currentPreferencesState."$it.key".status = "syncPending" } else if (!state.currentPreferencesState."$it.key".value) { @@ -104,6 +111,20 @@ def updated() { // Preferences template end } +def excludeParameterFromSync(preference){ + def exclude = false + if (preference.key == "outputQ2SwitchSelection") { + if (zwaveInfo?.model?.equals("0052") || zwaveInfo?.model?.equals("0053")) { + exclude = true + } + } + + if (exclude) { + log.warn "Preference no ${preference.parameterNumber} - ${preference.key} is not supported by this device" + } + return exclude +} + private syncConfiguration() { def commands = [] parameterMap.each { @@ -446,6 +467,6 @@ private getParameterMap() {[ 0: "When system is turned off the output is 0V (NC).", 1: "When system is turned off the output is 230V (NO).", ], - description: "Set value means the type of the device that is connected to the Q2 output. The device type can be normally open (NO) or normally close (NC). " + description: "(Only for Qubino Flush 2 Relay) Set value means the type of the device that is connected to the Q2 output. The device type can be normally open (NO) or normally close (NC). " ] ]} \ No newline at end of file From 12f6b55a830a418aff6c5ac99e6e5571cc11cd64 Mon Sep 17 00:00:00 2001 From: PKacprowiczS <41617389+PKacprowiczS@users.noreply.github.com> Date: Wed, 22 Jul 2020 19:59:46 +0200 Subject: [PATCH 02/12] [ICP-13246] Stelpro Thermostats preferences changes (#32881) * Changes to Stelpro preferences * fixup! Changes to Stelpro preferences * Copied 'secondsPast' method from another DTH. * Switched back to old logic, with new preference description and events time inverval * Forcing to show every changig current state event * Revert "Forcing to show every changig current state event" This reverts commit 7077e0e2e36baf25fd1ed4d403881b88b3847192. * Minor fixes * Comment change --- .../stelpro-ki-thermostat.groovy | 36 ++++++++++++++++--- .../stelpro-ki-zigbee-thermostat.groovy | 11 +++--- .../stelpro-maestro-thermostat.groovy | 11 +++--- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/devicetypes/stelpro/stelpro-ki-thermostat.src/stelpro-ki-thermostat.groovy b/devicetypes/stelpro/stelpro-ki-thermostat.src/stelpro-ki-thermostat.groovy index 21d0355b679..5d5ad2e97c3 100644 --- a/devicetypes/stelpro/stelpro-ki-thermostat.src/stelpro-ki-thermostat.groovy +++ b/devicetypes/stelpro/stelpro-ki-thermostat.src/stelpro-ki-thermostat.groovy @@ -50,11 +50,12 @@ metadata { preferences { section { - input("heatdetails", "enum", title: "Do you want a detailed operating state notification?", options: ["No", "Yes"], defaultValue: "No", required: true, displayDuringSetup: true) + input("heatdetails", "enum", title: "Do you want to see detailed operating state events in the activity history? There may be many.", options: ["No", "Yes"], defaultValue: "No", required: false, displayDuringSetup: true) } section { - input title: "Outdoor Temperature", description: "To get the current outdoor temperature to display on your thermostat enter your zip code or postal code below and make sure that your SmartThings location has a Geolocation configured (typically used for geofencing).", displayDuringSetup: false, type: "paragraph", element: "paragraph" - input("zipcode", "text", title: "ZipCode (Outdoor Temperature)", description: "[Do not use space](Blank = No Forecast)") + input(title: "Outdoor Temperature", description: "To get the current outdoor temperature to display on your thermostat enter your zip code or postal code below and make sure that your SmartThings location has a Geolocation configured (typically used for geofencing). Do not use space. If you don't want a forecast, leave it blank.", + displayDuringSetup: false, type: "paragraph", element: "paragraph") + input("zipcode", "text", title: "ZipCode (Outdoor Temperature)", description: "") } } @@ -290,7 +291,7 @@ def zwaveEvent(thermostatsetpointv2.ThermostatSetpointReport cmd) { def map = [:] if (cmd.scaledValue >= 327 || - cmd.setpointType != thermostatsetpointv2.ThermostatSetpointReport.SETPOINT_TYPE_HEATING_1) { + cmd.setpointType != thermostatsetpointv2.ThermostatSetpointReport.SETPOINT_TYPE_HEATING_1) { return [:] } temp = convertTemperatureIfNeeded(cmd.scaledValue, cmdScale, cmd.precision) @@ -366,7 +367,10 @@ def zwaveEvent(thermostatoperatingstatev1.ThermostatOperatingStateReport cmd) { map.name = "thermostatOperatingState" map.value = operatingState - if (settings.heatdetails == "No") { + // If the user does not want to see the Idle and Heating events in the event history, + // don't show them. Otherwise, don't show them more frequently than 5 minutes. + if (settings.heatdetails == "No" || + !secondsPast(device.currentState("thermostatOperatingState")?.getLastUpdated(), 60 * 5)) { map.displayed = false } } else { @@ -556,3 +560,25 @@ def fanCirculate() { def setThermostatFanMode() { log.trace "${device.displayName} does not support fan mode" } + +/** + * Checks if the time elapsed from the provided timestamp is greater than the number of senconds provided + * + * @param timestamp: The timestamp + * + * @param seconds: The number of seconds + * + * @returns true if elapsed time is greater than number of seconds provided, else false + */ +private Boolean secondsPast(timestamp, seconds) { + if (!(timestamp instanceof Number)) { + if (timestamp instanceof Date) { + timestamp = timestamp.time + } else if ((timestamp instanceof String) && timestamp.isNumber()) { + timestamp = timestamp.toLong() + } else { + return true + } + } + return (now() - timestamp) > (seconds * 1000) +} diff --git a/devicetypes/stelpro/stelpro-ki-zigbee-thermostat.src/stelpro-ki-zigbee-thermostat.groovy b/devicetypes/stelpro/stelpro-ki-zigbee-thermostat.src/stelpro-ki-zigbee-thermostat.groovy index 997addd618b..7be4b28616a 100644 --- a/devicetypes/stelpro/stelpro-ki-zigbee-thermostat.src/stelpro-ki-zigbee-thermostat.groovy +++ b/devicetypes/stelpro/stelpro-ki-zigbee-thermostat.src/stelpro-ki-zigbee-thermostat.groovy @@ -53,11 +53,12 @@ metadata { preferences { section { input("lock", "enum", title: "Do you want to lock your thermostat's physical keypad?", options: ["No", "Yes"], defaultValue: "No", required: false, displayDuringSetup: false) - input("heatdetails", "enum", title: "Do you want a detailed operating state notification?", options: ["No", "Yes"], defaultValue: "No", required: false, displayDuringSetup: true) + input("heatdetails", "enum", title: "Do you want to see detailed operating state events in the activity history? There may be many.", options: ["No", "Yes"], defaultValue: "No", required: false, displayDuringSetup: true) } section { - input title: "Outdoor Temperature", description: "To get the current outdoor temperature to display on your thermostat enter your zip code or postal code below and make sure that your SmartThings location has a Geolocation configured (typically used for geofencing).", displayDuringSetup: false, type: "paragraph", element: "paragraph" - input("zipcode", "text", title: "ZipCode (Outdoor Temperature)", description: "[Do not use space](Blank = No Forecast)") + input(title: "Outdoor Temperature", description: "To get the current outdoor temperature to display on your thermostat enter your zip code or postal code below and make sure that your SmartThings location has a Geolocation configured (typically used for geofencing). Do not use space. If you don't want a forecast, leave it blank.", + displayDuringSetup: false, type: "paragraph", element: "paragraph") + input("zipcode", "text", title: "ZipCode (Outdoor Temperature)", description: "") } } @@ -308,9 +309,9 @@ def parse(String description) { } // If the user does not want to see the Idle and Heating events in the event history, - // don't show them. Otherwise, don't show them more frequently than 30 seconds. + // don't show them. Otherwise, don't show them more frequently than 5 minutes. if (settings.heatdetails == "No" || - !secondsPast(device.currentState("thermostatOperatingState")?.getLastUpdated(), 30)) { + !secondsPast(device.currentState("thermostatOperatingState")?.getLastUpdated(), 60 * 5)) { map.displayed = false } map = validateOperatingStateBugfix(map) diff --git a/devicetypes/stelpro/stelpro-maestro-thermostat.src/stelpro-maestro-thermostat.groovy b/devicetypes/stelpro/stelpro-maestro-thermostat.src/stelpro-maestro-thermostat.groovy index 0a316f4de85..59f1aae7773 100644 --- a/devicetypes/stelpro/stelpro-maestro-thermostat.src/stelpro-maestro-thermostat.groovy +++ b/devicetypes/stelpro/stelpro-maestro-thermostat.src/stelpro-maestro-thermostat.groovy @@ -54,11 +54,12 @@ metadata { preferences { section { input("lock", "enum", title: "Do you want to lock your thermostat's physical keypad?", options: ["No", "Yes"], defaultValue: "No", required: false, displayDuringSetup: false) - input("heatdetails", "enum", title: "Do you want a detailed operating state notification?", options: ["No", "Yes"], defaultValue: "No", required: false, displayDuringSetup: true) + input("heatdetails", "enum", title: "Do you want to see detailed operating state events in the activity history? There may be many.", options: ["No", "Yes"], defaultValue: "No", required: false, displayDuringSetup: true) } section { - input title: "Outdoor Temperature", description: "To get the current outdoor temperature to display on your thermostat enter your zip code or postal code below and make sure that your SmartThings location has a Geolocation configured (typically used for geofencing).", displayDuringSetup: false, type: "paragraph", element: "paragraph" - input("zipcode", "text", title: "ZipCode (Outdoor Temperature)", description: "[Do not use space](Blank = No Forecast)") + input(title: "Outdoor Temperature", description: "To get the current outdoor temperature to display on your thermostat enter your zip code or postal code below and make sure that your SmartThings location has a Geolocation configured (typically used for geofencing). Do not use space. If you don't want a forecast, leave it blank.", + displayDuringSetup: false, type: "paragraph", element: "paragraph") + input("zipcode", "text", title: "ZipCode (Outdoor Temperature)", description: "") } /* input("away_setpoint", "enum", title: "Away setpoint", options: ["5", "5.5", "6", "6.5", "7", "7.5", "8", "8.5", "9", "9.5", "10", "10.5", "11", "11.5", "12", "12.5", "13", "13.5", "14", "14.5", "15", "5.5", "15.5", "16", "16.5", "17", "17.5", "18", "18.5", "19", "19.5", "20", "20.5", "21", "21.5", "22", "22.5", "23", "24", "24.5", "25", "25.5", "26", "26.5", "27", "27.5", "28", "28.5", "29", "29.5", "30"], defaultValue: "21", required: true) @@ -279,9 +280,9 @@ def parse(String description) { } // If the user does not want to see the Idle and Heating events in the event history, - // don't show them. Otherwise, don't show them more frequently than 30 seconds. + // don't show them. Otherwise, don't show them more frequently than 5 minutes. if (settings.heatdetails == "No" || - !secondsPast(device.currentState("thermostatOperatingState")?.getLastUpdated(), 30)) { + !secondsPast(device.currentState("thermostatOperatingState")?.getLastUpdated(), 60 * 5)) { map.displayed = false } } From e6a30056e8e6b12c17e36f1d57df9bdd37d2030d Mon Sep 17 00:00:00 2001 From: Konrad K <33450498+KKlimczukS@users.noreply.github.com> Date: Wed, 22 Jul 2020 21:34:25 +0200 Subject: [PATCH 03/12] [ICP-13322, ICP-13326, ICP-13336, ICP-13345, ICP-13346, ICP-13355] - fixes for Qubino Dimmers (#37228) * fixes: ICP-13322, ICP-13326, ICP-13355 * fixes2: ICP-13322, ICP-13326, ICP-13355 * fixes3: ICP-13322, ICP-13326, ICP-13355 * fix for ICP-13345 - add meterGet commands * Fix for adding elements to commands collection * ICP-13336 - Removed option 3, because it does not apply to Qubino Temperature Sensor ZMNHEA1. --- .../qubino-dimmer.src/qubino-dimmer.groovy | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/devicetypes/qubino/qubino-dimmer.src/qubino-dimmer.groovy b/devicetypes/qubino/qubino-dimmer.src/qubino-dimmer.groovy index f364229a214..8cea8b62461 100644 --- a/devicetypes/qubino/qubino-dimmer.src/qubino-dimmer.groovy +++ b/devicetypes/qubino/qubino-dimmer.src/qubino-dimmer.groovy @@ -122,7 +122,6 @@ def installed() { state.currentPreferencesState."$it.key".value = getPreferenceValue(it) state.currentPreferencesState."$it.key".status = "synced" } - readConfigurationFromTheDevice() // Preferences template end } @@ -167,13 +166,13 @@ def excludeParameterFromSync(preference){ return exclude } -private readConfigurationFromTheDevice() { +private getReadConfigurationFromTheDeviceCommands() { def commands = [] parameterMap.each { state.currentPreferencesState."$it.key".status = "reverseSyncPending" commands += zwave.configurationV2.configurationGet(parameterNumber: it.parameterNumber) } - sendHubCommand(encapCommands(commands)) + commands } private syncConfiguration() { @@ -232,7 +231,15 @@ def configure() { commands << zwave.associationV1.associationSet(groupingIdentifier:5, nodeId:[zwaveHubNodeId]) commands << zwave.associationV1.associationSet(groupingIdentifier:6, nodeId:[zwaveHubNodeId]) commands << zwave.multiChannelV3.multiChannelEndPointGet() - commands + getRefreshCommands() + commands += getRefreshCommands() + + // 1% is default Minimum dimming value for dimmers, + // when device is set to 1% - it turns off and device does not send any level reports + // Minimum dimming value has to be set to 2%, so the device's internal range would be 2-100% + // Still, for users it will relatively be 1-100% on the UI and device will report it. + // Parameter no. 60 – Minimum dimming value + commands << zwave.configurationV2.configurationSet(scaledConfigurationValue: 2, parameterNumber: 60, size: 1) + commands += getReadConfigurationFromTheDeviceCommands() encapCommands(commands) } @@ -334,7 +341,7 @@ def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd, ep = null) { if(input1SwitchType == INPUT_TYPE_POTENTIOMETER) { log.debug "BasicSet: ${cmd} / INPUT_TYPE_POTENTfIOMETER" - response(zwave.switchMultilevelV3.switchMultilevelGet()) + sendHubCommand(encap(zwave.switchMultilevelV3.switchMultilevelGet())) } else if (input1SwitchType == INPUT_TYPE_BI_STABLE_SWITCH) { log.debug "BasicSet: ${cmd} / INPUT_TYPE_BI_STABLE_SWITCH" dimmerEvents(cmd) @@ -482,6 +489,11 @@ def setLevel(value, duration = null) { commands << zwave.switchMultilevelV3.switchMultilevelSet(value: level, dimmingDuration: dimmingDuration) commands << zwave.switchMultilevelV3.switchMultilevelGet() + if(supportsPowerMeter()){ + commands << zwave.meterV2.meterGet(scale: 0) + commands << zwave.meterV2.meterGet(scale: 2) + } + encapCommands(commands, getStatusDelay) } @@ -570,11 +582,9 @@ private getParameterMap() {[ values: [ 0: "Default value - Mono-stable switch type (push button) – button quick press turns between previous set dimmer value and zero)", 1: "Bi-stable switch type (on/off toggle switch)", - 2: "Potentiometer (applies to Flush Dimmer 0-10V only, dimmer is using set value the last received from potentiometer or from z-wave controller)", - 3: "0-10V Temperature sensor (regulated output, applies to Flush Dimmer 0-10V only)" + 2: "Potentiometer (applies to Flush Dimmer 0-10V only, dimmer is using set value the last received from potentiometer or from z-wave controller)" ], - description: "Set input based on device type (switch, potentiometer, temperature sensor,..)." + - "After parameter change to value 3 first exclude module (without setting parameters to default value) then wait at least 30s and then re include the module! " + description: "Set input based on device type (mono-stable switch, bi-stable switch, potentiometer)." ], [ name: "Input 2 switch type (applies to Qubino Flush Dimmer only)", key: "inputsSwitchTypes", type: "enum", From 455802177ec9ba071aa65824353fa527a3fb2aa3 Mon Sep 17 00:00:00 2001 From: PKacprowiczS <41617389+PKacprowiczS@users.noreply.github.com> Date: Thu, 23 Jul 2020 00:36:05 +0200 Subject: [PATCH 04/12] Added fingerprint for Ajax Online Filament Bulb (#38132) --- .../zigbee-white-color-temperature-bulb.groovy | 3 +++ 1 file changed, 3 insertions(+) diff --git a/devicetypes/smartthings/zigbee-white-color-temperature-bulb.src/zigbee-white-color-temperature-bulb.groovy b/devicetypes/smartthings/zigbee-white-color-temperature-bulb.src/zigbee-white-color-temperature-bulb.groovy index 6606b52bc79..fe9fc667764 100644 --- a/devicetypes/smartthings/zigbee-white-color-temperature-bulb.src/zigbee-white-color-temperature-bulb.groovy +++ b/devicetypes/smartthings/zigbee-white-color-temperature-bulb.src/zigbee-white-color-temperature-bulb.groovy @@ -117,6 +117,9 @@ metadata { // Third Reality fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300", outClusters: "0019", manufacturer: "Third Reality, Inc", model: "3RSL011Z", deviceJoinName: "RealityLight Light" //RealityLight fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300", outClusters: "0019", manufacturer: "Third Reality, Inc", model: "3RSL012Z", deviceJoinName: "RealityLight Light" //RealityLight + + // Ajax Online + fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 1000", outClusters: "0019", manufacturer: "Ajax Online", model: "CCT", deviceJoinName: "Ajax Light", mnmn: "SmartThings", vid: "generic-color-temperature-bulb-2200K-6500K" // Ajax Online Filament Bulb } // UI tile definitions From de4ddded1ca31ac503a4e61e1699c4746bee274d Mon Sep 17 00:00:00 2001 From: PKacprowiczS <41617389+PKacprowiczS@users.noreply.github.com> Date: Thu, 23 Jul 2020 23:24:52 +0200 Subject: [PATCH 05/12] ICP-13392 Added fingerprints of device with updated firmware alongside one configuration command (#38227) --- .../zwave-basic-window-shade.groovy | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/devicetypes/smartthings/zwave-basic-window-shade.src/zwave-basic-window-shade.groovy b/devicetypes/smartthings/zwave-basic-window-shade.src/zwave-basic-window-shade.groovy index b9e91c4e904..1f8ced29483 100644 --- a/devicetypes/smartthings/zwave-basic-window-shade.src/zwave-basic-window-shade.groovy +++ b/devicetypes/smartthings/zwave-basic-window-shade.src/zwave-basic-window-shade.groovy @@ -27,6 +27,8 @@ metadata { fingerprint mfr:"0086", prod:"0003", model:"008D", deviceJoinName: "Aeotec Window Treatment" //Aeotec Nano Shutter fingerprint mfr:"0086", prod:"0103", model:"008D", deviceJoinName: "Aeotec Window Treatment" //Aeotec Nano Shutter + fingerprint mfr:"0371", prod:"0003", model:"008D", deviceJoinName: "Aeotec Window Treatment" //Aeotec Nano Shutter + fingerprint mfr:"0371", prod:"0103", model:"008D", deviceJoinName: "Aeotec Window Treatment" //Aeotec Nano Shutter } tiles(scale: 2) { @@ -149,7 +151,10 @@ def updated() { def configure() { log.debug "Configure..." - response(secure(zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, scaledConfigurationValue: 1))) + response([ + secure(zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, scaledConfigurationValue: 1)), + secure(zwave.configurationV1.configurationSet(parameterNumber: 85, size: 1, scaledConfigurationValue: 1)) + ]) } private secure(cmd) { From 6be0c351ffea4e735d139a1310b8645cd6c37ed9 Mon Sep 17 00:00:00 2001 From: PKacprowiczS <41617389+PKacprowiczS@users.noreply.github.com> Date: Fri, 24 Jul 2020 15:44:20 +0200 Subject: [PATCH 06/12] 'displayed' flag set to false for configuration event (#21920) --- .../zwave-basic-window-shade.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devicetypes/smartthings/zwave-basic-window-shade.src/zwave-basic-window-shade.groovy b/devicetypes/smartthings/zwave-basic-window-shade.src/zwave-basic-window-shade.groovy index 1f8ced29483..eb670ddf29b 100644 --- a/devicetypes/smartthings/zwave-basic-window-shade.src/zwave-basic-window-shade.groovy +++ b/devicetypes/smartthings/zwave-basic-window-shade.src/zwave-basic-window-shade.groovy @@ -139,7 +139,7 @@ def ping() { def installed() { log.debug "Installed ${device.displayName}" sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) - sendEvent(name: "availableCurtainPowerButtons", value: JsonOutput.toJson(["open", "close", "pause"])) + sendEvent(name: "availableCurtainPowerButtons", value: JsonOutput.toJson(["open", "close", "pause"]), displayed: false) state.shadeState = "paused" state.reverseDirection = reverseDirection ? reverseDirection : false } From 0cd26a3261f456157abb082e3183d430c1c59176 Mon Sep 17 00:00:00 2001 From: PKacprowiczS <41617389+PKacprowiczS@users.noreply.github.com> Date: Fri, 24 Jul 2020 20:44:21 +0200 Subject: [PATCH 07/12] [WWST-6159] Qubino Flush Shutter DC - fingerprint and improvements (#38295) * Added fingerprint for Qubino Flush Shutter DC * Opening/closing report also for manual actions --- .../qubino-flush-shutter.groovy | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/devicetypes/qubino/qubino-flush-shutter.src/qubino-flush-shutter.groovy b/devicetypes/qubino/qubino-flush-shutter.src/qubino-flush-shutter.groovy index 90916e144e1..22cd56f40f1 100644 --- a/devicetypes/qubino/qubino-flush-shutter.src/qubino-flush-shutter.groovy +++ b/devicetypes/qubino/qubino-flush-shutter.src/qubino-flush-shutter.groovy @@ -24,7 +24,9 @@ metadata { capability "Configuration" //zw:L type:1107 mfr:0159 prod:0003 model:0052 ver:1.01 zwv:4.05 lib:03 cc:5E,86,72,5A,73,20,27,25,26,32,60,85,8E,59,70 ccOut:20,26 epc:2 - fingerprint mfr: "0159", prod: "0003", model: "0052", deviceJoinName: "Qubino Window Treatment" + fingerprint mfr: "0159", prod: "0003", model: "0052", deviceJoinName: "Qubino Window Treatment" // Qubino Flush Shutter (110-230 VAC) + //zw:L type:1107 mfr:0159 prod:0003 model:0053 ver:1.01 zwv:4.05 lib:03 cc:5E,86,72,5A,73,20,27,25,26,32,85,8E,59,70 ccOut:20,26 + fingerprint mfr: "0159", prod: "0003", model: "0053", deviceJoinName: "Qubino Window Treatment" // Qubino Flush Shutter DC } tiles(scale: 2) { @@ -227,7 +229,12 @@ def open() { } def pause() { - sendHubCommand(encap(zwave.switchMultilevelV3.switchMultilevelStopLevelChange())) + def currentShadeState = device.currentState("windowShade").value + if (currentShadeState == "opening" || currentShadeState == "closing") { + encap(zwave.switchMultilevelV3.switchMultilevelStopLevelChange()) + } else { + encap(zwave.switchMultilevelV3.switchMultilevelGet()) + } } def setLevelChild(level, childDni) { @@ -235,15 +242,11 @@ def setLevelChild(level, childDni) { } def setLevel(level) { - state.blindsLastCommand = currentLevel > level ? "opening" : "closing" setShadeLevel(level) } def setShadeLevel(level) { log.debug "Setting shade level: ${level}" - def currentLevel = Integer.parseInt(device.currentState("shadeLevel").value) - state.blindsLastCommand = currentLevel > level ? "opening" : "closing" - state.shadeTarget = level encap(zwave.switchMultilevelV3.switchMultilevelSet(value: Math.min(0x63, level))) } @@ -257,7 +260,10 @@ def setSlats(level) { } def refresh() { - encap(zwave.switchMultilevelV3.switchMultilevelGet()) + [ + encap(zwave.switchMultilevelV3.switchMultilevelGet()), + encap(zwave.meterV3.meterGet(scale: 0x00)), + ] } def ping() { @@ -313,6 +319,9 @@ def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelR } def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelSet cmd, ep = null) { + def currentLevel = Integer.parseInt(device.currentState("shadeLevel").value) + state.blindsLastCommand = currentLevel > cmd.value ? "opening" : "closing" + state.shadeTarget = cmd.value sendHubCommand(encap(zwave.meterV3.meterGet(scale: 0x02))) } @@ -355,7 +364,7 @@ def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd, ep = null) eventMap.value = Math.round(cmd.scaledMeterValue) eventMap.unit = "W" events += createEvent(eventMap) - if (cmd.scaledMeterValue) { + if (Math.round(cmd.scaledMeterValue)) { events += createEvent([name: "windowShade", value: state.blindsLastCommand]) events += createEvent([name: "shadeLevel", value: state.shadeTarget, displayed: false]) } else { From 07e3bb3aff32a3765ec0e59ad4a5d18a74420a74 Mon Sep 17 00:00:00 2001 From: PKacprowiczS <41617389+PKacprowiczS@users.noreply.github.com> Date: Fri, 24 Jul 2020 20:51:24 +0200 Subject: [PATCH 08/12] [ICP-13423] Qubino Flush 2 Relay - Added initial poll (#38316) --- .../qubino-flush-2-relay.src/qubino-flush-2-relay.groovy | 3 +++ 1 file changed, 3 insertions(+) diff --git a/devicetypes/qubino/qubino-flush-2-relay.src/qubino-flush-2-relay.groovy b/devicetypes/qubino/qubino-flush-2-relay.src/qubino-flush-2-relay.groovy index 2dbeb85dd8b..9a1d7e87193 100644 --- a/devicetypes/qubino/qubino-flush-2-relay.src/qubino-flush-2-relay.groovy +++ b/devicetypes/qubino/qubino-flush-2-relay.src/qubino-flush-2-relay.groovy @@ -92,6 +92,9 @@ def installed() { state.currentPreferencesState."$it.key".status = "synced" } // Preferences template end + response([ + refresh((1..state.numberOfSwitches).toList()) + ]) } def updated() { From 7cfa6466863a276559ea8929a43e33490d476599 Mon Sep 17 00:00:00 2001 From: PKacprowiczS <41617389+PKacprowiczS@users.noreply.github.com> Date: Fri, 24 Jul 2020 20:54:21 +0200 Subject: [PATCH 09/12] WWST-6946 Somfy Glydea Ultra fingerprint (#38386) --- .../zigbee-window-shade.src/zigbee-window-shade.groovy | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/devicetypes/smartthings/zigbee-window-shade.src/zigbee-window-shade.groovy b/devicetypes/smartthings/zigbee-window-shade.src/zigbee-window-shade.groovy index c2ac0d29c7d..98f1a878f1b 100755 --- a/devicetypes/smartthings/zigbee-window-shade.src/zigbee-window-shade.groovy +++ b/devicetypes/smartthings/zigbee-window-shade.src/zigbee-window-shade.groovy @@ -33,6 +33,7 @@ metadata { fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0102", outClusters: "000A", manufacturer: "Feibit Co.Ltd", model: "FTB56-ZT218AK1.8", deviceJoinName: "Wistar Window Treatment" //Wistar Curtain Motor(CMJ) fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0102", outClusters: "0003", manufacturer: "REXENSE", model: "KG0001", deviceJoinName: "Window Treatment" //Smart Curtain Motor(BCM300D) fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0102", outClusters: "0003", manufacturer: "REXENSE", model: "DY0010", deviceJoinName: "Window Treatment" //Smart Curtain Motor(DT82TV) + fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0102", outClusters: "0003", manufacturer: "SOMFY", model: "Glydea Somfy", deviceJoinName: "Somfy Window Treatment" //Somfy Glydea Ultra } preferences { @@ -193,7 +194,7 @@ def pause() { } def presetPosition() { - setLevel(preset ?: 50) + setLevel(preset ?: 50) } /** @@ -271,7 +272,7 @@ private List readDeviceBindingTable() { } def shouldInvertLiftPercentage() { - return isIkeaKadrilj() || isIkeaFyrtur() + return isIkeaKadrilj() || isIkeaFyrtur() || isSomfyGlydea() } def reportsBatteryPercentage() { @@ -285,3 +286,7 @@ def isIkeaKadrilj() { def isIkeaFyrtur() { device.getDataValue("model") == "FYRTUR block-out roller blind" } + +def isSomfyGlydea() { + device.getDataValue("model") == "Glydea Somfy" +} \ No newline at end of file From 40889471d5583b425b4514e30ffa49549bbf8cf3 Mon Sep 17 00:00:00 2001 From: Steven Green Date: Mon, 27 Jul 2020 16:06:07 -0700 Subject: [PATCH 10/12] DevWS add fingerprint for Ecolink DWZB1-ECO door/window sensor (#38312) --- .../smartsense-open-closed-sensor.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy b/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy index c4d67acc681..bc297558972 100644 --- a/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy +++ b/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy @@ -33,6 +33,7 @@ metadata { fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "Contact Sensor-A", deviceJoinName: "SYLVANIA Open/Closed Sensor" //Sylvania SMART+ Contact and Temperature Smart Sensor fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "Visonic", model: "MCT-340 E", deviceJoinName: "Visonic Open/Closed Sensor" //Visonic Door/Window Sensor fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "Ecolink", model: "4655BC0-R", deviceJoinName: "Ecolink Open/Closed Sensor", mnmn: "SmartThings", vid: "ecolink-door-sensor" //Ecolink Door/Window Sensor + fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "Ecolink", model: "DWZB1-ECO", deviceJoinName: "Ecolink Open/Closed Sensor", mnmn: "SmartThings", vid: "ecolink-door-sensor" //Ecolink Door/Window Sensor fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05,FC01,FC02", outClusters: "0003,0019", manufacturer: "iMagic by GreatStar", model: "1116-S", deviceJoinName: "Iris Open/Closed Sensor" //Iris Contact Sensor fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "Bosch", model: "RFMS-ZBMS", deviceJoinName: "Bosch Open/Closed Sensor" //Bosch multi-sensor fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "Megaman", model: "MS601/z1", deviceJoinName: "INGENIUM Open/Closed Sensor" //INGENIUM ZB Magnetic ON/OFF Sensor From 54f88e5c1deeaac960d9c234fd4f1e03d818da05 Mon Sep 17 00:00:00 2001 From: Konrad K <33450498+KKlimczukS@users.noreply.github.com> Date: Tue, 28 Jul 2020 13:20:08 +0200 Subject: [PATCH 11/12] ICP-12883,ICP-12849, ICP-12851 - Add mnmn and VID to: Dome DMMS1 and NEO Coolcam Motion Light Sensor fingerprints (#30195) * ICP-12883 - added mnmn and VID to Dome Motion/Light Sensor DMMS1 fingerprint * ICP-12883 - Device specific VID in Dome Motion/Light Sensor DMMS1 fingerprint * ICP-12849, ICP-12851 - Add mnmn and a device specific VID to NEO Coolcam Motion/Light Sensor fingerprints --- .../zwave-motion-light-sensor.groovy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/devicetypes/smartthings/zwave-motion-light-sensor.src/zwave-motion-light-sensor.groovy b/devicetypes/smartthings/zwave-motion-light-sensor.src/zwave-motion-light-sensor.groovy index 5ad9cfc9084..e17f6f69651 100644 --- a/devicetypes/smartthings/zwave-motion-light-sensor.src/zwave-motion-light-sensor.groovy +++ b/devicetypes/smartthings/zwave-motion-light-sensor.src/zwave-motion-light-sensor.groovy @@ -26,11 +26,11 @@ metadata { capability "Configuration" //zw:S type:0701 mfr:021F prod:0003 model:0083 ver:3.92 zwv:4.05 lib:06 cc:5E,86,72,5A,73,80,31,71,30,70,85,59,84 role:06 ff:8C07 ui:8C07 - fingerprint mfr: "021F", prod: "0003", model: "0083", deviceJoinName: "Dome Motion Sensor" //Dome Motion/Light Sensor + fingerprint mfr: "021F", prod: "0003", model: "0083", deviceJoinName: "Dome Motion/Light Sensor", mnmn: "SmartThings", vid: "SmartThings-smartthings-Dome_Motion_Light_Sensor_DMMS1" //zw:S type:0701 mfr:0258 prod:0003 model:008D ver:3.80 zwv:4.38 lib:06 cc:5E,86,72,5A,73,80,31,71,30,70,85,59,84 role:06 ff:8C07 ui:8C07 - fingerprint mfr: "0258", prod: "0003", model: "008D", deviceJoinName: "NEO Coolcam Motion Sensor" //NEO Coolcam Motion/Light Sensor + fingerprint mfr: "0258", prod: "0003", model: "008D", deviceJoinName: "NEO Coolcam Motion/Light Sensor", mnmn: "SmartThings", vid: "SmartThings-smartthings-NEO_Coolcam_Motion_Light_Sensor" //zw:S type:0701 mfr:0258 prod:0003 model:108D ver:3.80 zwv:4.38 lib:06 cc:5E,86,72,5A,73,80,31,71,30,70,85,59,84 role:06 ff:8C07 ui:8C07 EU version - fingerprint mfr: "0258", prod: "0003", model: "108D", deviceJoinName: "NEO Coolcam Motion Sensor" //NEO Coolcam Motion/Light Sensor + fingerprint mfr: "0258", prod: "0003", model: "108D", deviceJoinName: "NEO Coolcam Motion/Light Sensor", mnmn: "SmartThings", vid: "SmartThings-smartthings-NEO_Coolcam_Motion_Light_Sensor" fingerprint mfr: "017F", prod: "0101", model: "0001", deviceJoinName: "Wink Motion Sensor" } From ed676f0e3df0970a2573904746d23c6a7a1b50eb Mon Sep 17 00:00:00 2001 From: Konrad K <33450498+KKlimczukS@users.noreply.github.com> Date: Tue, 28 Jul 2020 18:53:25 +0200 Subject: [PATCH 12/12] ICP-10928 - Zigbee RGBW Bulb: Fix color temperature value on initial join, code refactoring. (#30421) Set the color temperature to 5000K on initial join. 5000K was chosen because it is one of the values that is doesn't change when converted to mireds and back again and because it is in the supported range of all the devices that have fingerprints in this DTH. The code was also refactored to make more use of the Zigbee library. --- .../zigbee-rgbw-bulb.groovy | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/devicetypes/smartthings/zigbee-rgbw-bulb.src/zigbee-rgbw-bulb.groovy b/devicetypes/smartthings/zigbee-rgbw-bulb.src/zigbee-rgbw-bulb.groovy index 4e6e539a8e8..87e0ffab340 100644 --- a/devicetypes/smartthings/zigbee-rgbw-bulb.src/zigbee-rgbw-bulb.groovy +++ b/devicetypes/smartthings/zigbee-rgbw-bulb.src/zigbee-rgbw-bulb.groovy @@ -135,7 +135,6 @@ private getHUE_COMMAND() { 0x00 } private getSATURATION_COMMAND() { 0x03 } private getMOVE_TO_HUE_AND_SATURATION_COMMAND() { 0x06 } private getCOLOR_CONTROL_CLUSTER() { 0x0300 } -private getATTRIBUTE_COLOR_TEMPERATURE() { 0x0007 } // Parse incoming device messages to generate events def parse(String description) { @@ -203,12 +202,9 @@ def ping() { def refresh() { zigbee.onOffRefresh() + - zigbee.levelRefresh() + - zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_COLOR_TEMPERATURE) + - zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + - zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) + - zigbee.onOffConfig(0, 300) + - zigbee.levelConfig() + zigbee.levelRefresh() + + zigbee.colorTemperatureRefresh() + + zigbee.hueSaturationRefresh() } def configure() { @@ -217,17 +213,24 @@ def configure() { // enrolls with default periodic reporting until newer 5 min interval is confirmed sendEvent(name: "checkInterval", value: 2 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) - // OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity - refresh() + + def cmds = [] + if(device.currentState("colorTemperature")?.value == null) { + cmds += zigbee.setColorTemperature(5000) + } + + cmds += refresh() + + // OnOff, level minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity + zigbee.onOffConfig(0, 300) + + zigbee.levelConfig(0, 300) + cmds } def setColorTemperature(value) { value = value as Integer - def tempInMired = Math.round(1000000 / value) - def finalHex = zigbee.swapEndianHex(zigbee.convertToHexString(tempInMired, 4)) - zigbee.command(COLOR_CONTROL_CLUSTER, 0x0A, "$finalHex 0000") + - zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.setColorTemperature(value) + + zigbee.colorTemperatureRefresh() } //Naming based on the wiki article here: http://en.wikipedia.org/wiki/Color_temperature @@ -262,20 +265,19 @@ private getScaledSaturation(value) { def setColor(value){ log.trace "setColor($value)" zigbee.on() + - zigbee.command(COLOR_CONTROL_CLUSTER, MOVE_TO_HUE_AND_SATURATION_COMMAND, - getScaledHue(value.hue), getScaledSaturation(value.saturation), "0000") + - zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) + - zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.command(COLOR_CONTROL_CLUSTER, MOVE_TO_HUE_AND_SATURATION_COMMAND, + getScaledHue(value.hue), getScaledSaturation(value.saturation), "0000") + + zigbee.hueSaturationRefresh() } def setHue(value) { zigbee.command(COLOR_CONTROL_CLUSTER, HUE_COMMAND, getScaledHue(value), "00", "0000") + - zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) } def setSaturation(value) { zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, getScaledSaturation(value), "0000") + - zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) } def installed() {