From aae45d27a502c680908f36d3fe224ce9e2549951 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 4 Aug 2023 23:33:56 -0400 Subject: [PATCH 01/41] Adding Power consumption measurment to stelpro device Adding Power consumption measurment to stelpro device ( custom attribute 0x4008) Also added init function to trigger proper config of device (which was not always being properly triggered) Combined all stelar files into init.lua (as stelar_maestrostat.lua and stelar_sorb.lus a duplicates) --- .../zigbee-thermostat/src/stelpro/init.lua | 89 +++++++++++++++---- 1 file changed, 72 insertions(+), 17 deletions(-) diff --git a/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua b/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua index 1009b3dc55..e23cb4ed0c 100644 --- a/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua +++ b/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua @@ -14,11 +14,20 @@ local capabilities = require "st.capabilities" local clusters = require "st.zigbee.zcl.clusters" +local device_management = require "st.zigbee.device_management" +local cluster_base = require "st.zigbee.cluster_base" +local data_types = require "st.zigbee.data_types" +local RelativeHumidity = clusters.RelativeHumidity local Thermostat = clusters.Thermostat local ThermostatUserInterfaceConfiguration = clusters.ThermostatUserInterfaceConfiguration +local ThermostatMode = capabilities.thermostatMode local ThermostatOperatingState = capabilities.thermostatOperatingState +local ThermostatPower = capabilities.powerMeter + +local POWER_ATTTRIBUTE = 0x4008 +local MFG_CODE = 0x1185 local RX_FREEZE_VALUE = 0x7ffd local RX_HEAT_VALUE = 0x7fff @@ -28,18 +37,56 @@ local HEAT_ALRAM_TEMPERATURE = 50 local STELPRO_THERMOSTAT_FINGERPRINTS = { { mfr = "Stelpro", model = "MaestroStat" }, { mfr = "Stelpro", model = "SORB" }, - { mfr = "Stelpro", model = "SonomaStyle" } + { mfr = "Stelpro", model = "SonomaStyle" }, + { mfr = "Stelpro", model = "SMT402AD" } -- added M.Colmenarejo } local is_stelpro_thermostat = function(opts, driver, device) for _, fingerprint in ipairs(STELPRO_THERMOSTAT_FINGERPRINTS) do - if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then - return true - end + if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then + return true + end end return false end +local do_refresh = function(self, device) + local attributes = { + Thermostat.attributes.LocalTemperature, + Thermostat.attributes.PIHeatingDemand, + Thermostat.attributes.OccupiedHeatingSetpoint, + ThermostatUserInterfaceConfiguration.attributes.TemperatureDisplayMode, + ThermostatUserInterfaceConfiguration.attributes.KeypadLockout, + RelativeHumidity.attributes.MeasuredValue + } + for _, attribute in pairs(attributes) do + device:send(attribute:read(device)) + end + device:send(cluster_base.read_manufacturer_specific_attribute(device, Thermostat.ID, POWER_ATTTRIBUTE, MFG_CODE)) +end + +local device_added = function(self, device) + device:emit_event(capabilities.temperatureAlarm.temperatureAlarm.cleared()) + do_refresh(self, device) +end + +local do_configure = function(self, device) + device:send(Thermostat.attributes.LocalTemperature:configure_reporting(device, 10, 60, 50)) + device:send(Thermostat.attributes.OccupiedHeatingSetpoint:configure_reporting(device, 1, 600, 50)) + device:send(Thermostat.attributes.PIHeatingDemand:configure_reporting(device, 1, 60, 1)) + device:send(cluster_base.configure_reporting(device, data_types.ClusterId(Thermostat.ID) , POWER_ATTTRIBUTE, 0x23 , 1, 60, 1)) + + device:send(ThermostatUserInterfaceConfiguration.attributes.TemperatureDisplayMode:configure_reporting(device, 1, 0, 1)) + device:send(ThermostatUserInterfaceConfiguration.attributes.KeypadLockout:configure_reporting(device, 1, 0, 1)) + device:send(RelativeHumidity.attributes.MeasuredValue:configure_reporting(device, 10, 300, 1)) + + device:emit_event(ThermostatMode.thermostatMode.heat()) +end + +local device_init = function(self, device) + do_configure(self, device) +end + local function get_temperature(temperature) return temperature / 100 end @@ -73,11 +120,11 @@ local function thermostat_local_temp_attr_handler(driver, device, value, zb_rx) (last_alarm == "freeze" and temperature > FREEZE_ALRAM_TEMPERATURE) or (last_alarm == "heat" and temperature < HEAT_ALRAM_TEMPERATURE) ) then - if last_alarm == "freeze" then - event = capabilities.temperatureAlarm.temperatureAlarm.freeze() - else - event = capabilities.temperatureAlarm.temperatureAlarm.heat() - end + if last_alarm == "freeze" then + event = capabilities.temperatureAlarm.temperatureAlarm.freeze() + else + event = capabilities.temperatureAlarm.temperatureAlarm.heat() + end end else if temperature <= FREEZE_ALRAM_TEMPERATURE then @@ -98,21 +145,22 @@ local function thermostat_heating_set_point_attr_handler(driver, device, value, end local function thermostat_heating_demand_attr_handler(driver, device, value, zb_rx) - local event = value.value < 10 and ThermostatOperatingState.thermostatOperatingState.idle() or - ThermostatOperatingState.thermostatOperatingState.heating() + local event = value.value < 1 and ThermostatOperatingState.thermostatOperatingState.idle() or + ThermostatOperatingState.thermostatOperatingState.heating() device:emit_event(event) end +local function thermostat_power_attr_handler(driver, device, zb_rx) + local point_value = zb_rx.value + device:emit_event(capabilities.powerMeter.power({value = point_value, unit = "W"})) +end + local function info_changed(driver, device, event, args) if device.preferences ~= nil and device.preferences.lock ~= args.old_st_store.preferences.lock then device:send(ThermostatUserInterfaceConfiguration.attributes.KeypadLockout:write(device, tonumber(device.preferences.lock))) end end -local device_added = function(self, device) - -- device:emit_event(capabilities.temperatureAlarm.temperatureAlarm.cleared()) -end - local stelpro_thermostat = { NAME = "Stelpro Thermostat Handler", zigbee_handlers = { @@ -121,15 +169,22 @@ local stelpro_thermostat = { [Thermostat.attributes.PIHeatingDemand.ID] = thermostat_heating_demand_attr_handler, [Thermostat.attributes.LocalTemperature.ID] = thermostat_local_temp_attr_handler, [Thermostat.attributes.OccupiedHeatingSetpoint.ID] = thermostat_heating_set_point_attr_handler, + [POWER_ATTTRIBUTE] = thermostat_power_attr_handler } } }, lifecycle_handlers = { + init = device_init, + doConfigure = do_configure, added = device_added, infoChanged = info_changed }, - sub_drivers = { require("stelpro.stelpro_sorb"), require("stelpro.stelpro_maestrostat") }, - can_handle = is_stelpro_thermostat + capability_handlers = { + [capabilities.refresh.ID] = { + [capabilities.refresh.commands.refresh.NAME] = do_refresh, + } + }, + can_handle = is_stelpro_thermostat, } return stelpro_thermostat From e590f43db497968c65ab2a2bb093cb6851e0a405 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 4 Aug 2023 23:39:48 -0400 Subject: [PATCH 02/41] Update init.lua --- drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua b/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua index e23cb4ed0c..5c9e580dec 100644 --- a/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua +++ b/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua @@ -38,7 +38,7 @@ local STELPRO_THERMOSTAT_FINGERPRINTS = { { mfr = "Stelpro", model = "MaestroStat" }, { mfr = "Stelpro", model = "SORB" }, { mfr = "Stelpro", model = "SonomaStyle" }, - { mfr = "Stelpro", model = "SMT402AD" } -- added M.Colmenarejo + { mfr = "Stelpro", model = "SMT402AD" } } local is_stelpro_thermostat = function(opts, driver, device) From 7db786413ca3ce251877f0e06eaa6ceaa0acb029 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 4 Aug 2023 23:40:20 -0400 Subject: [PATCH 03/41] Delete stelpro_maestrostat.lua --- .../src/stelpro/stelpro_maestrostat.lua | 80 ------------------- 1 file changed, 80 deletions(-) delete mode 100644 drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_maestrostat.lua diff --git a/drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_maestrostat.lua b/drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_maestrostat.lua deleted file mode 100644 index e7742e8195..0000000000 --- a/drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_maestrostat.lua +++ /dev/null @@ -1,80 +0,0 @@ --- Copyright 2022 SmartThings --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - -local capabilities = require "st.capabilities" -local clusters = require "st.zigbee.zcl.clusters" -local device_management = require "st.zigbee.device_management" - -local RelativeHumidity = clusters.RelativeHumidity -local Thermostat = clusters.Thermostat -local ThermostatUserInterfaceConfiguration = clusters.ThermostatUserInterfaceConfiguration - -local STELPRO_THERMOSTAT_FINGERPRINTS = { - { mfr = "Stelpro", model = "MaestroStat" }, -} - -local is_stelpro_thermostat = function(opts, driver, device) - for _, fingerprint in ipairs(STELPRO_THERMOSTAT_FINGERPRINTS) do - if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then - return true - end - end - return false -end - -local do_refresh = function(self, device) - local attributes = { - Thermostat.attributes.LocalTemperature, - Thermostat.attributes.PIHeatingDemand, - Thermostat.attributes.OccupiedHeatingSetpoint, - ThermostatUserInterfaceConfiguration.attributes.TemperatureDisplayMode, - ThermostatUserInterfaceConfiguration.attributes.KeypadLockout, - RelativeHumidity.attributes.MeasuredValue - } - for _, attribute in pairs(attributes) do - device:send(attribute:read(device)) - end -end - -local device_added = function(self, device) - -- device:emit_event(capabilities.temperatureAlarm.temperatureAlarm.cleared()) - do_refresh(self, device) -end - -local function do_configure(self, device) - device:send(device_management.build_bind_request(device, Thermostat.ID, self.environment_info.hub_zigbee_eui)) - device:send(Thermostat.attributes.LocalTemperature:configure_reporting(device, 10, 60, 50)) - device:send(Thermostat.attributes.OccupiedHeatingSetpoint:configure_reporting(device, 1, 600, 50)) - device:send(Thermostat.attributes.PIHeatingDemand:configure_reporting(device, 1, 3600, 1)) - - device:send(ThermostatUserInterfaceConfiguration.attributes.TemperatureDisplayMode:configure_reporting(device, 1, 0, 1)) - device:send(ThermostatUserInterfaceConfiguration.attributes.KeypadLockout:configure_reporting(device, 1, 0, 1)) - device:send(RelativeHumidity.attributes.MeasuredValue:configure_reporting(device, 10, 300, 1)) -end - -local stelpro_maestro_othermostat = { - NAME = "Stelpro Maestro Thermostat Handler", - capability_handlers = { - [capabilities.refresh.ID] = { - [capabilities.refresh.commands.refresh.NAME] = do_refresh, - } - }, - lifecycle_handlers = { - added = device_added, - doConfigure = do_configure - }, - can_handle = is_stelpro_thermostat -} - -return stelpro_maestro_othermostat From c377860f38fa7d8cbee12c7b5889a650beab0d17 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 4 Aug 2023 23:40:29 -0400 Subject: [PATCH 04/41] Delete stelpro_sorb.lua --- .../src/stelpro/stelpro_sorb.lua | 81 ------------------- 1 file changed, 81 deletions(-) delete mode 100644 drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_sorb.lua diff --git a/drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_sorb.lua b/drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_sorb.lua deleted file mode 100644 index 1a43347239..0000000000 --- a/drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_sorb.lua +++ /dev/null @@ -1,81 +0,0 @@ --- Copyright 2022 SmartThings --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - -local capabilities = require "st.capabilities" -local clusters = require "st.zigbee.zcl.clusters" -local device_management = require "st.zigbee.device_management" - -local RelativeHumidity = clusters.RelativeHumidity -local Thermostat = clusters.Thermostat -local ThermostatUserInterfaceConfiguration = clusters.ThermostatUserInterfaceConfiguration - -local STELPRO_THERMOSTAT_FINGERPRINTS = { - { mfr = "Stelpro", model = "SORB" }, - { mfr = "Stelpro", model = "SonomaStyle" } -} - -local is_stelpro_sorb_thermostat = function(opts, driver, device) - for _, fingerprint in ipairs(STELPRO_THERMOSTAT_FINGERPRINTS) do - if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then - return true - end - end - return false -end - -local do_refresh = function(self, device) - local attributes = { - Thermostat.attributes.LocalTemperature, - Thermostat.attributes.PIHeatingDemand, - Thermostat.attributes.OccupiedHeatingSetpoint, - ThermostatUserInterfaceConfiguration.attributes.TemperatureDisplayMode, - ThermostatUserInterfaceConfiguration.attributes.KeypadLockout, - RelativeHumidity.attributes.MeasuredValue - } - for _, attribute in pairs(attributes) do - device:send(attribute:read(device)) - end -end - -local device_added = function(self, device) - -- device:emit_event(capabilities.temperatureAlarm.temperatureAlarm.cleared()) - do_refresh(self, device) -end - -local function do_configure(self, device) - device:send(device_management.build_bind_request(device, Thermostat.ID, self.environment_info.hub_zigbee_eui)) - device:send(Thermostat.attributes.LocalTemperature:configure_reporting(device, 10, 60, 50)) - device:send(Thermostat.attributes.OccupiedHeatingSetpoint:configure_reporting(device, 1, 600, 50)) - device:send(Thermostat.attributes.PIHeatingDemand:configure_reporting(device, 1, 3600, 1)) - - device:send(ThermostatUserInterfaceConfiguration.attributes.TemperatureDisplayMode:configure_reporting(device, 1, 0, 1)) - device:send(ThermostatUserInterfaceConfiguration.attributes.KeypadLockout:configure_reporting(device, 1, 0, 1)) - device:send(RelativeHumidity.attributes.MeasuredValue:configure_reporting(device, 10, 300, 1)) -end - -local stelpro_sorb_thermostat = { - NAME = "Stelpro SORB SonomaStyle Thermostat Handler", - capability_handlers = { - [capabilities.refresh.ID] = { - [capabilities.refresh.commands.refresh.NAME] = do_refresh, - } - }, - lifecycle_handlers = { - added = device_added, - doConfigure = do_configure - }, - can_handle = is_stelpro_sorb_thermostat -} - -return stelpro_sorb_thermostat From 56769274527d02b6576386a6f5f1d179ab6456cd Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 4 Aug 2023 23:41:26 -0400 Subject: [PATCH 05/41] Update thermostat-stelpro-profile.yml Adding missing capabilities needed for HomeAssistant support --- .../profiles/thermostat-stelpro-profile.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/SmartThings/zigbee-thermostat/profiles/thermostat-stelpro-profile.yml b/drivers/SmartThings/zigbee-thermostat/profiles/thermostat-stelpro-profile.yml index aee0c42f2d..02ddb08a4f 100644 --- a/drivers/SmartThings/zigbee-thermostat/profiles/thermostat-stelpro-profile.yml +++ b/drivers/SmartThings/zigbee-thermostat/profiles/thermostat-stelpro-profile.yml @@ -14,6 +14,15 @@ components: values: - key: "heatingSetpoint.value" range: [ 5, 30 ] + - id: thermostatCoolingSetpoint + - id: thermostatMode + version: 1 + config: + values: + - key: "thermostatMode.value" + enabledValues: + - heat + default: heat - id: thermostatOperatingState version: 1 config: @@ -22,6 +31,11 @@ components: enabledValues: - heating - idle + - id: powerMeter + version: 1 + config: + values: + - key: "powerMeter.value" - id: temperatureAlarm version: 1 config: From 20b1ddc8a7b1d9f5067def0fb297f93e17bac4cc Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 4 Aug 2023 23:43:25 -0400 Subject: [PATCH 06/41] Adding support for SMT402AD Thanks to M.colmenarejo --- drivers/SmartThings/zigbee-thermostat/fingerprints.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/zigbee-thermostat/fingerprints.yml b/drivers/SmartThings/zigbee-thermostat/fingerprints.yml index d1ced3a2cf..0d6640947b 100644 --- a/drivers/SmartThings/zigbee-thermostat/fingerprints.yml +++ b/drivers/SmartThings/zigbee-thermostat/fingerprints.yml @@ -69,6 +69,11 @@ zigbeeManufacturer: manufacturer: Stelpro model: STZB402+ deviceProfileName: thermostat-temperature-temperaturealarm + - id: "Stelpro/SMT402AD" + deviceLabel: Stelpro Thermostat + manufacturer: Stelpro + model: SMT402AD + deviceProfileName: thermostat-stelpro-profile - id: "Stelpro/ST218" deviceLabel: Stelpro Thermostat manufacturer: Stelpro From 1a90c02322b9bf3a0af385ead0e5a165e53fa046 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 4 Aug 2023 23:46:08 -0400 Subject: [PATCH 07/41] Update init.lua --- drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua b/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua index 5c9e580dec..35bca818b3 100644 --- a/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua +++ b/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua @@ -43,9 +43,9 @@ local STELPRO_THERMOSTAT_FINGERPRINTS = { local is_stelpro_thermostat = function(opts, driver, device) for _, fingerprint in ipairs(STELPRO_THERMOSTAT_FINGERPRINTS) do - if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then - return true - end + if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then + return true + end end return false end From 1e176c43e48579c9ff3129539fce426d2ad828fd Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 5 Aug 2023 21:52:55 -0400 Subject: [PATCH 08/41] Update fingerprints.yml Corrected indentation error --- drivers/SmartThings/zigbee-thermostat/fingerprints.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/SmartThings/zigbee-thermostat/fingerprints.yml b/drivers/SmartThings/zigbee-thermostat/fingerprints.yml index 0d6640947b..34bc0d6dd1 100644 --- a/drivers/SmartThings/zigbee-thermostat/fingerprints.yml +++ b/drivers/SmartThings/zigbee-thermostat/fingerprints.yml @@ -69,7 +69,7 @@ zigbeeManufacturer: manufacturer: Stelpro model: STZB402+ deviceProfileName: thermostat-temperature-temperaturealarm - - id: "Stelpro/SMT402AD" + - id: "Stelpro/SMT402AD" deviceLabel: Stelpro Thermostat manufacturer: Stelpro model: SMT402AD From 9da09d43932a0abe009780f9059e83d7f35a1420 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 6 Oct 2023 23:08:39 -0400 Subject: [PATCH 09/41] Update init.lua --- .../zigbee-thermostat/src/stelpro/init.lua | 88 ++++++++++++++++--- 1 file changed, 75 insertions(+), 13 deletions(-) diff --git a/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua b/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua index 063f423517..6188ae72d7 100644 --- a/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua +++ b/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua @@ -14,11 +14,20 @@ local capabilities = require "st.capabilities" local clusters = require "st.zigbee.zcl.clusters" +local device_management = require "st.zigbee.device_management" +local cluster_base = require "st.zigbee.cluster_base" +local data_types = require "st.zigbee.data_types" +local RelativeHumidity = clusters.RelativeHumidity local Thermostat = clusters.Thermostat local ThermostatUserInterfaceConfiguration = clusters.ThermostatUserInterfaceConfiguration +local ThermostatMode = capabilities.thermostatMode local ThermostatOperatingState = capabilities.thermostatOperatingState +local ThermostatPower = capabilities.powerMeter + +local POWER_ATTTRIBUTE = 0x4008 +local MFG_CODE = 0x1185 local RX_FREEZE_VALUE = 0x7ffd local RX_HEAT_VALUE = 0x7fff @@ -28,18 +37,56 @@ local HEAT_ALRAM_TEMPERATURE = 50 local STELPRO_THERMOSTAT_FINGERPRINTS = { { mfr = "Stelpro", model = "MaestroStat" }, { mfr = "Stelpro", model = "SORB" }, - { mfr = "Stelpro", model = "SonomaStyle" } + { mfr = "Stelpro", model = "SonomaStyle" }, + { mfr = "Stelpro", model = "SMT402AD" } -- added M.Colmenarejo } local is_stelpro_thermostat = function(opts, driver, device) for _, fingerprint in ipairs(STELPRO_THERMOSTAT_FINGERPRINTS) do - if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then - return true - end + if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then + return true + end end return false end +local do_refresh = function(self, device) + local attributes = { + Thermostat.attributes.LocalTemperature, + Thermostat.attributes.PIHeatingDemand, + Thermostat.attributes.OccupiedHeatingSetpoint, + ThermostatUserInterfaceConfiguration.attributes.TemperatureDisplayMode, + ThermostatUserInterfaceConfiguration.attributes.KeypadLockout, + RelativeHumidity.attributes.MeasuredValue + } + for _, attribute in pairs(attributes) do + device:send(attribute:read(device)) + end + device:send(cluster_base.read_manufacturer_specific_attribute(device, Thermostat.ID, POWER_ATTTRIBUTE, MFG_CODE)) +end + +local device_added = function(self, device) + device:emit_event(capabilities.temperatureAlarm.temperatureAlarm.cleared()) + do_refresh(self, device) +end + +local do_configure = function(self, device) + device:send(Thermostat.attributes.LocalTemperature:configure_reporting(device, 10, 60, 50)) + device:send(Thermostat.attributes.OccupiedHeatingSetpoint:configure_reporting(device, 1, 600, 50)) + device:send(Thermostat.attributes.PIHeatingDemand:configure_reporting(device, 1, 60, 1)) + device:send(cluster_base.configure_reporting(device, data_types.ClusterId(Thermostat.ID) , POWER_ATTTRIBUTE, 0x23 , 1, 60, 1)) + + device:send(ThermostatUserInterfaceConfiguration.attributes.TemperatureDisplayMode:configure_reporting(device, 1, 0, 1)) + device:send(ThermostatUserInterfaceConfiguration.attributes.KeypadLockout:configure_reporting(device, 1, 0, 1)) + device:send(RelativeHumidity.attributes.MeasuredValue:configure_reporting(device, 10, 300, 1)) + + device:emit_event(ThermostatMode.thermostatMode.heat()) +end + +local device_init = function(self, device) + do_configure(self, device) +end + local function get_temperature(temperature) return temperature / 100 end @@ -73,11 +120,11 @@ local function thermostat_local_temp_attr_handler(driver, device, value, zb_rx) (last_alarm == "freeze" and temperature > FREEZE_ALRAM_TEMPERATURE) or (last_alarm == "heat" and temperature < HEAT_ALRAM_TEMPERATURE) ) then - if last_alarm == "freeze" then - event = capabilities.temperatureAlarm.temperatureAlarm.freeze() - else - event = capabilities.temperatureAlarm.temperatureAlarm.heat() - end + if last_alarm == "freeze" then + event = capabilities.temperatureAlarm.temperatureAlarm.freeze() + else + event = capabilities.temperatureAlarm.temperatureAlarm.heat() + end end else if temperature <= FREEZE_ALRAM_TEMPERATURE then @@ -98,21 +145,29 @@ local function thermostat_heating_set_point_attr_handler(driver, device, value, end local function thermostat_heating_demand_attr_handler(driver, device, value, zb_rx) - local event = value.value < 10 and ThermostatOperatingState.thermostatOperatingState.idle() or - ThermostatOperatingState.thermostatOperatingState.heating() + local event = value.value < 1 and ThermostatOperatingState.thermostatOperatingState.idle() or + ThermostatOperatingState.thermostatOperatingState.heating() device:emit_event(event) end +local function thermostat_power_attr_handler(driver, device, zb_rx) + local point_value = zb_rx.value + device:emit_event(capabilities.powerMeter.power({value = point_value, unit = "W"})) +end + local function info_changed(driver, device, event, args) if device.preferences ~= nil and device.preferences.lock ~= args.old_st_store.preferences.lock then device:send(ThermostatUserInterfaceConfiguration.attributes.KeypadLockout:write(device, tonumber(device.preferences.lock))) end end +<<<<<<< HEAD local device_added = function(self, device) device:emit_event(capabilities.temperatureAlarm.temperatureAlarm.cleared()) end +======= +>>>>>>> aae45d2 (Adding Power consumption measurment to stelpro device ) local stelpro_thermostat = { NAME = "Stelpro Thermostat Handler", zigbee_handlers = { @@ -121,15 +176,22 @@ local stelpro_thermostat = { [Thermostat.attributes.PIHeatingDemand.ID] = thermostat_heating_demand_attr_handler, [Thermostat.attributes.LocalTemperature.ID] = thermostat_local_temp_attr_handler, [Thermostat.attributes.OccupiedHeatingSetpoint.ID] = thermostat_heating_set_point_attr_handler, + [POWER_ATTTRIBUTE] = thermostat_power_attr_handler } } }, lifecycle_handlers = { + init = device_init, + doConfigure = do_configure, added = device_added, infoChanged = info_changed }, - sub_drivers = { require("stelpro.stelpro_sorb"), require("stelpro.stelpro_maestrostat") }, - can_handle = is_stelpro_thermostat + capability_handlers = { + [capabilities.refresh.ID] = { + [capabilities.refresh.commands.refresh.NAME] = do_refresh, + } + }, + can_handle = is_stelpro_thermostat, } return stelpro_thermostat From a03d971097027109aa379a14ff51d3f580092dca Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 6 Oct 2023 23:19:51 -0400 Subject: [PATCH 10/41] Update fingerprints.yml From e3f207a41d9ae9beb4549b5a4ec7b8da36542e85 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 6 Oct 2023 23:21:08 -0400 Subject: [PATCH 11/41] Update init.lua --- .../zigbee-thermostat/src/stelpro/init.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua b/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua index 35bca818b3..a6c46fb6a9 100644 --- a/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua +++ b/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua @@ -38,14 +38,14 @@ local STELPRO_THERMOSTAT_FINGERPRINTS = { { mfr = "Stelpro", model = "MaestroStat" }, { mfr = "Stelpro", model = "SORB" }, { mfr = "Stelpro", model = "SonomaStyle" }, - { mfr = "Stelpro", model = "SMT402AD" } + { mfr = "Stelpro", model = "SMT402AD" } -- added M.Colmenarejo } local is_stelpro_thermostat = function(opts, driver, device) for _, fingerprint in ipairs(STELPRO_THERMOSTAT_FINGERPRINTS) do - if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then - return true - end + if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then + return true + end end return false end @@ -161,6 +161,10 @@ local function info_changed(driver, device, event, args) end end +local device_added = function(self, device) + device:emit_event(capabilities.temperatureAlarm.temperatureAlarm.cleared()) +end + local stelpro_thermostat = { NAME = "Stelpro Thermostat Handler", zigbee_handlers = { From 06a6735cede63c2f00ec47da3bf7e7adb13f9575 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 6 Oct 2023 23:34:45 -0400 Subject: [PATCH 12/41] Delete drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_maestrostat.lua --- .../src/stelpro/stelpro_maestrostat.lua | 80 ------------------- 1 file changed, 80 deletions(-) delete mode 100644 drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_maestrostat.lua diff --git a/drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_maestrostat.lua b/drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_maestrostat.lua deleted file mode 100644 index c4d81b944a..0000000000 --- a/drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_maestrostat.lua +++ /dev/null @@ -1,80 +0,0 @@ --- Copyright 2022 SmartThings --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - -local capabilities = require "st.capabilities" -local clusters = require "st.zigbee.zcl.clusters" -local device_management = require "st.zigbee.device_management" - -local RelativeHumidity = clusters.RelativeHumidity -local Thermostat = clusters.Thermostat -local ThermostatUserInterfaceConfiguration = clusters.ThermostatUserInterfaceConfiguration - -local STELPRO_THERMOSTAT_FINGERPRINTS = { - { mfr = "Stelpro", model = "MaestroStat" }, -} - -local is_stelpro_thermostat = function(opts, driver, device) - for _, fingerprint in ipairs(STELPRO_THERMOSTAT_FINGERPRINTS) do - if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then - return true - end - end - return false -end - -local do_refresh = function(self, device) - local attributes = { - Thermostat.attributes.LocalTemperature, - Thermostat.attributes.PIHeatingDemand, - Thermostat.attributes.OccupiedHeatingSetpoint, - ThermostatUserInterfaceConfiguration.attributes.TemperatureDisplayMode, - ThermostatUserInterfaceConfiguration.attributes.KeypadLockout, - RelativeHumidity.attributes.MeasuredValue - } - for _, attribute in pairs(attributes) do - device:send(attribute:read(device)) - end -end - -local device_added = function(self, device) - device:emit_event(capabilities.temperatureAlarm.temperatureAlarm.cleared()) - do_refresh(self, device) -end - -local function do_configure(self, device) - device:send(device_management.build_bind_request(device, Thermostat.ID, self.environment_info.hub_zigbee_eui)) - device:send(Thermostat.attributes.LocalTemperature:configure_reporting(device, 10, 60, 50)) - device:send(Thermostat.attributes.OccupiedHeatingSetpoint:configure_reporting(device, 1, 600, 50)) - device:send(Thermostat.attributes.PIHeatingDemand:configure_reporting(device, 1, 3600, 1)) - - device:send(ThermostatUserInterfaceConfiguration.attributes.TemperatureDisplayMode:configure_reporting(device, 1, 0, 1)) - device:send(ThermostatUserInterfaceConfiguration.attributes.KeypadLockout:configure_reporting(device, 1, 0, 1)) - device:send(RelativeHumidity.attributes.MeasuredValue:configure_reporting(device, 10, 300, 1)) -end - -local stelpro_maestro_othermostat = { - NAME = "Stelpro Maestro Thermostat Handler", - capability_handlers = { - [capabilities.refresh.ID] = { - [capabilities.refresh.commands.refresh.NAME] = do_refresh, - } - }, - lifecycle_handlers = { - added = device_added, - doConfigure = do_configure - }, - can_handle = is_stelpro_thermostat -} - -return stelpro_maestro_othermostat From 623d89bec24d005c466583a0fc99b40c5bb61818 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 6 Oct 2023 23:34:52 -0400 Subject: [PATCH 13/41] Delete drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_sorb.lua --- .../src/stelpro/stelpro_sorb.lua | 81 ------------------- 1 file changed, 81 deletions(-) delete mode 100644 drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_sorb.lua diff --git a/drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_sorb.lua b/drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_sorb.lua deleted file mode 100644 index 504d4351e0..0000000000 --- a/drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_sorb.lua +++ /dev/null @@ -1,81 +0,0 @@ --- Copyright 2022 SmartThings --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - -local capabilities = require "st.capabilities" -local clusters = require "st.zigbee.zcl.clusters" -local device_management = require "st.zigbee.device_management" - -local RelativeHumidity = clusters.RelativeHumidity -local Thermostat = clusters.Thermostat -local ThermostatUserInterfaceConfiguration = clusters.ThermostatUserInterfaceConfiguration - -local STELPRO_THERMOSTAT_FINGERPRINTS = { - { mfr = "Stelpro", model = "SORB" }, - { mfr = "Stelpro", model = "SonomaStyle" } -} - -local is_stelpro_sorb_thermostat = function(opts, driver, device) - for _, fingerprint in ipairs(STELPRO_THERMOSTAT_FINGERPRINTS) do - if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then - return true - end - end - return false -end - -local do_refresh = function(self, device) - local attributes = { - Thermostat.attributes.LocalTemperature, - Thermostat.attributes.PIHeatingDemand, - Thermostat.attributes.OccupiedHeatingSetpoint, - ThermostatUserInterfaceConfiguration.attributes.TemperatureDisplayMode, - ThermostatUserInterfaceConfiguration.attributes.KeypadLockout, - RelativeHumidity.attributes.MeasuredValue - } - for _, attribute in pairs(attributes) do - device:send(attribute:read(device)) - end -end - -local device_added = function(self, device) - device:emit_event(capabilities.temperatureAlarm.temperatureAlarm.cleared()) - do_refresh(self, device) -end - -local function do_configure(self, device) - device:send(device_management.build_bind_request(device, Thermostat.ID, self.environment_info.hub_zigbee_eui)) - device:send(Thermostat.attributes.LocalTemperature:configure_reporting(device, 10, 60, 50)) - device:send(Thermostat.attributes.OccupiedHeatingSetpoint:configure_reporting(device, 1, 600, 50)) - device:send(Thermostat.attributes.PIHeatingDemand:configure_reporting(device, 1, 3600, 1)) - - device:send(ThermostatUserInterfaceConfiguration.attributes.TemperatureDisplayMode:configure_reporting(device, 1, 0, 1)) - device:send(ThermostatUserInterfaceConfiguration.attributes.KeypadLockout:configure_reporting(device, 1, 0, 1)) - device:send(RelativeHumidity.attributes.MeasuredValue:configure_reporting(device, 10, 300, 1)) -end - -local stelpro_sorb_thermostat = { - NAME = "Stelpro SORB SonomaStyle Thermostat Handler", - capability_handlers = { - [capabilities.refresh.ID] = { - [capabilities.refresh.commands.refresh.NAME] = do_refresh, - } - }, - lifecycle_handlers = { - added = device_added, - doConfigure = do_configure - }, - can_handle = is_stelpro_sorb_thermostat -} - -return stelpro_sorb_thermostat From def353dea342a40ec38b80a3a5521d0cfa567767 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 6 Oct 2023 23:48:52 -0400 Subject: [PATCH 14/41] Update fingerprints.yml --- drivers/SmartThings/zigbee-motion-sensor/fingerprints.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/zigbee-motion-sensor/fingerprints.yml b/drivers/SmartThings/zigbee-motion-sensor/fingerprints.yml index 79b98bc247..301c2d8cf2 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/fingerprints.yml +++ b/drivers/SmartThings/zigbee-motion-sensor/fingerprints.yml @@ -4,6 +4,11 @@ zigbeeManufacturer: manufacturer: LUMI model: lumi.motion.agl02 deviceProfileName: motion-illuminance-battery-aqara + - id: "LUMI/lumi.motion.ac02" + deviceLabel: Aqara Motion Sensor P1 + manufacturer: LUMI + model: lumi.motion.ac02 + deviceProfileName: motion-illuminance-battery-aqara - id: "LUMI/lumi.motion.agl04" deviceLabel: Aqara High Precision Motion Sensor manufacturer: LUMI From c1cfa856e5b265fbe993b8705d77145377ad7f98 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 6 Oct 2023 23:51:06 -0400 Subject: [PATCH 15/41] Update motion-illuminance-battery-aqara.yml --- .../profiles/motion-illuminance-battery-aqara.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/SmartThings/zigbee-motion-sensor/profiles/motion-illuminance-battery-aqara.yml b/drivers/SmartThings/zigbee-motion-sensor/profiles/motion-illuminance-battery-aqara.yml index ff58019d63..73ba1816e6 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/profiles/motion-illuminance-battery-aqara.yml +++ b/drivers/SmartThings/zigbee-motion-sensor/profiles/motion-illuminance-battery-aqara.yml @@ -14,5 +14,9 @@ components: version: 1 - id: refresh version: 1 + - id: Voltage + version: 1 + - id: Signal Strenght + version: 1 categories: - name: MotionSensor From 435dbc65f7bc80c7d53f9baa70486a528d2c0fa6 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 6 Oct 2023 23:52:37 -0400 Subject: [PATCH 16/41] Update motion-illuminance-battery-aqara.yml --- .../profiles/motion-illuminance-battery-aqara.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/SmartThings/zigbee-motion-sensor/profiles/motion-illuminance-battery-aqara.yml b/drivers/SmartThings/zigbee-motion-sensor/profiles/motion-illuminance-battery-aqara.yml index 73ba1816e6..23b3f027d1 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/profiles/motion-illuminance-battery-aqara.yml +++ b/drivers/SmartThings/zigbee-motion-sensor/profiles/motion-illuminance-battery-aqara.yml @@ -6,9 +6,11 @@ components: version: 1 - id: illuminanceMeasurement version: 1 + - id: battery + version: 1 - id: stse.detectionFrequency version: 1 - - id: battery + - id: stse.sensitivityAdjustment version: 1 - id: firmwareUpdate version: 1 From c12d2cc9267609c834de311214eda73ae5ee7b64 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 7 Oct 2023 10:46:54 -0400 Subject: [PATCH 17/41] Update fingerprints.yml --- drivers/SmartThings/zigbee-thermostat/fingerprints.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/SmartThings/zigbee-thermostat/fingerprints.yml b/drivers/SmartThings/zigbee-thermostat/fingerprints.yml index 82a1ad7860..0ddfe161fe 100644 --- a/drivers/SmartThings/zigbee-thermostat/fingerprints.yml +++ b/drivers/SmartThings/zigbee-thermostat/fingerprints.yml @@ -75,7 +75,7 @@ zigbeeManufacturer: model: STZB402+ deviceProfileName: thermostat-temperature-temperaturealarm - id: "Stelpro/SMT402AD" - deviceLabel: Stelpro Thermostat + deviceLabel: Stelpro Thermostat vX manufacturer: Stelpro model: SMT402AD deviceProfileName: thermostat-stelpro-profile From 2f93ca16428cafd1ac329119ae0cd18251c4420d Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 7 Oct 2023 11:15:42 -0400 Subject: [PATCH 18/41] commit --- drivers/SmartThings/zigbee-thermostat/fingerprints.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/SmartThings/zigbee-thermostat/fingerprints.yml b/drivers/SmartThings/zigbee-thermostat/fingerprints.yml index 0ddfe161fe..82a1ad7860 100644 --- a/drivers/SmartThings/zigbee-thermostat/fingerprints.yml +++ b/drivers/SmartThings/zigbee-thermostat/fingerprints.yml @@ -75,7 +75,7 @@ zigbeeManufacturer: model: STZB402+ deviceProfileName: thermostat-temperature-temperaturealarm - id: "Stelpro/SMT402AD" - deviceLabel: Stelpro Thermostat vX + deviceLabel: Stelpro Thermostat manufacturer: Stelpro model: SMT402AD deviceProfileName: thermostat-stelpro-profile From 5471edfcd91c989a581ed5f6b1bf0ab36c78323b Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 7 Oct 2023 11:15:54 -0400 Subject: [PATCH 19/41] commit --- drivers/SmartThings/zigbee-thermostat/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/SmartThings/zigbee-thermostat/config.yml b/drivers/SmartThings/zigbee-thermostat/config.yml index 8c0d6d79fd..f36485b693 100644 --- a/drivers/SmartThings/zigbee-thermostat/config.yml +++ b/drivers/SmartThings/zigbee-thermostat/config.yml @@ -1,4 +1,4 @@ -name: 'Zigbee Thermostat' +name: 'Zigbee Thermostat vX' defaultProfile: 'thermostat-battery-powerSource' packageKey: 'zigbee-thermostat' permissions: From 3d0d0cd01dd1c1271962c73f63b36d0abe3513c5 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 7 Oct 2023 11:34:04 -0400 Subject: [PATCH 20/41] removed bad headers --- drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua b/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua index 6188ae72d7..a6c46fb6a9 100644 --- a/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua +++ b/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua @@ -161,13 +161,10 @@ local function info_changed(driver, device, event, args) end end -<<<<<<< HEAD local device_added = function(self, device) device:emit_event(capabilities.temperatureAlarm.temperatureAlarm.cleared()) end -======= ->>>>>>> aae45d2 (Adding Power consumption measurment to stelpro device ) local stelpro_thermostat = { NAME = "Stelpro Thermostat Handler", zigbee_handlers = { From 882e684cb263164acd513a193a77efda42251fbf Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 7 Oct 2023 12:00:50 -0400 Subject: [PATCH 21/41] aqara comit --- drivers/SmartThings/zigbee-motion-sensor/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/SmartThings/zigbee-motion-sensor/config.yml b/drivers/SmartThings/zigbee-motion-sensor/config.yml index 209ccb2762..da33a7cb38 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/config.yml +++ b/drivers/SmartThings/zigbee-motion-sensor/config.yml @@ -1,4 +1,4 @@ -name: 'Zigbee Motion Sensor' +name: 'Zigbee Motion Sensor vX' packageKey: 'zigbee-motion-sensor' permissions: zigbee: {} From 9cd7026ac5adcd2847c74708f554e1f1e626f8bc Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 7 Oct 2023 12:05:03 -0400 Subject: [PATCH 22/41] capabilities --- .../profiles/motion-illuminance-battery-aqara.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/SmartThings/zigbee-motion-sensor/profiles/motion-illuminance-battery-aqara.yml b/drivers/SmartThings/zigbee-motion-sensor/profiles/motion-illuminance-battery-aqara.yml index 23b3f027d1..4e5f20b2da 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/profiles/motion-illuminance-battery-aqara.yml +++ b/drivers/SmartThings/zigbee-motion-sensor/profiles/motion-illuminance-battery-aqara.yml @@ -16,9 +16,9 @@ components: version: 1 - id: refresh version: 1 - - id: Voltage + - id: voltageMeasurement version: 1 - - id: Signal Strenght + - id: signalStrength version: 1 categories: - name: MotionSensor From 5df33994cf68a8a142d55ca33cd34b55e0e40cd5 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 7 Oct 2023 12:17:26 -0400 Subject: [PATCH 23/41] commit aqara P1 --- drivers/SmartThings/zigbee-motion-sensor/src/aqara/init.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/SmartThings/zigbee-motion-sensor/src/aqara/init.lua b/drivers/SmartThings/zigbee-motion-sensor/src/aqara/init.lua index 989e41655b..a08856fa69 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/src/aqara/init.lua +++ b/drivers/SmartThings/zigbee-motion-sensor/src/aqara/init.lua @@ -18,7 +18,8 @@ local MOTION_DETECTED_UINT32 = 65536 local FINGERPRINTS = { { mfr = "LUMI", model = "lumi.motion.agl02" }, - { mfr = "LUMI", model = "lumi.motion.agl04" } + { mfr = "LUMI", model = "lumi.motion.agl04" }, + { mfr = "LUMI", model = "lumi.motion.ac02" } } local CONFIGURATIONS = { From 5780f0a5968d9aba174c04e107b638bceba787ab Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:20:35 -0500 Subject: [PATCH 24/41] Add profile for sinope-switch-rm3500zb --- .../profiles/sinope-switch-rm3500zb | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm3500zb diff --git a/drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm3500zb b/drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm3500zb new file mode 100644 index 0000000000..882f81440e --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm3500zb @@ -0,0 +1,26 @@ +name: sinope-switch-rm3500zb +components: + - id: main + capabilities: + - id: switch + version: 1 + - id: powerMeter + version: 1 + - id: voltageMeasurement + version: 1 + - id: currentMeter + version: 1 + - id: energyMeter + version: 1 + - id: temperatureMeasurement + version: 1 + - id: waterLeak + version: 1 + - id: thermostatCoolingSetpoint + version: 1 # For low water temp protection setpoint + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: SmartPlug From 50e117f839bf4c9d1001ba6d8bd028a48e392f44 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:21:47 -0500 Subject: [PATCH 25/41] Update deviceProfileName for Sinope Load Controller --- drivers/SmartThings/zigbee-switch/fingerprints.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/SmartThings/zigbee-switch/fingerprints.yml b/drivers/SmartThings/zigbee-switch/fingerprints.yml index 4c91da651e..af25221e26 100644 --- a/drivers/SmartThings/zigbee-switch/fingerprints.yml +++ b/drivers/SmartThings/zigbee-switch/fingerprints.yml @@ -395,7 +395,7 @@ zigbeeManufacturer: deviceLabel: "RM3500ZB Sinope Load Controller" manufacturer: Sinope Technologies model: RM3500ZB - deviceProfileName: switch-power-smartplug + deviceProfileName: sinope-switch-rm3500zb - id: "Sinope Dimmer Switch/DM2500ZB" deviceLabel: "DM2500ZB Sinope Dimmer" manufacturer: Sinope Technologies @@ -2484,4 +2484,4 @@ zigbeeGeneric: - 0x0006 #OnOff - 0x0702 #Simple Metering - 0x0B04 #Electrical Measurment - deviceProfileName: switch-power \ No newline at end of file + deviceProfileName: switch-power From 7a0d4076b54eb4ded3a7fe4b85f051703d65167e Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:37:51 -0500 Subject: [PATCH 26/41] Rename sinope-switch-rm3500zb to sinope-switch-rm3500zb.yml --- .../{sinope-switch-rm3500zb => sinope-switch-rm3500zb.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename drivers/SmartThings/zigbee-switch/profiles/{sinope-switch-rm3500zb => sinope-switch-rm3500zb.yml} (100%) diff --git a/drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm3500zb b/drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm3500zb.yml similarity index 100% rename from drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm3500zb rename to drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm3500zb.yml From fc124f2d642adbd3f5fb18c697bf35bfb9de823c Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 5 Dec 2025 23:22:17 -0500 Subject: [PATCH 27/41] Add temperature measurement handler to init.lua --- .../src/zigbee-switch-power/init.lua | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/SmartThings/zigbee-switch/src/zigbee-switch-power/init.lua b/drivers/SmartThings/zigbee-switch/src/zigbee-switch-power/init.lua index 0ea2224a6f..555ef75425 100644 --- a/drivers/SmartThings/zigbee-switch/src/zigbee-switch-power/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/zigbee-switch-power/init.lua @@ -7,6 +7,7 @@ local constants = require "st.zigbee.constants" local SimpleMetering = clusters.SimpleMetering local ElectricalMeasurement = clusters.ElectricalMeasurement +local TemperatureMeasurement = clusters.TemperatureMeasurement local function active_power_meter_handler(driver, device, value, zb_rx) local raw_value = value.value @@ -43,3 +44,24 @@ local zigbee_switch_power = { } return zigbee_switch_power + + +local function electrical_measurement_handler(driver, device, value, raw) + if value.attr_id == 0x0400 then -- Active Power + device:emit_event(capabilities.powerMeter.power({value = value.value, unit = "W"})) + elseif value.attr_id == 0x0505 then -- RMS Voltage + device:emit_event(capabilities.voltageMeasurement.voltage({value = value.value, unit = "V"})) + elseif value.attr_id == 0x0508 then -- RMS Current + device:emit_event(capabilities.currentMeter.current({value = value.value, unit = "A"})) + end +end + +local function metering_handler(driver, device, value, raw) + if value.attr_id == 0x0000 then -- Cumulative Energy + device:emit_event(capabilities.energyMeter.energy({value = value.value / 1000, unit = "kWh"})) + end +end + +local function temperature_handler(driver, device, value, raw) + device:emit_event(capabilities.temperatureMeasurement.temperature({value = value.value / 100, unit = "C"})) +end From c2d00c88e754c23644d01672107b0cb2f19fec1f Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 5 Dec 2025 23:39:15 -0500 Subject: [PATCH 28/41] Add handlers for RMS voltage, current, and metering --- .../src/zigbee-switch-power/init.lua | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/SmartThings/zigbee-switch/src/zigbee-switch-power/init.lua b/drivers/SmartThings/zigbee-switch/src/zigbee-switch-power/init.lua index 555ef75425..372610774b 100644 --- a/drivers/SmartThings/zigbee-switch/src/zigbee-switch-power/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/zigbee-switch-power/init.lua @@ -8,6 +8,7 @@ local constants = require "st.zigbee.constants" local SimpleMetering = clusters.SimpleMetering local ElectricalMeasurement = clusters.ElectricalMeasurement local TemperatureMeasurement = clusters.TemperatureMeasurement +local Metering = clusters.Metering local function active_power_meter_handler(driver, device, value, zb_rx) local raw_value = value.value @@ -27,15 +28,40 @@ local function instantaneous_demand_handler(driver, device, value, zb_rx) device:emit_event(capabilities.powerMeter.power({value = raw_value, unit = "W"})) end +local function rms_voltage_handler(driver, device, value, zb_rx) + device:emit_event(capabilities.voltageMeasurement.voltage({value = value.value, unit = "V"})) +end + +local function rms_current_handler(driver, device, value, zb_rx) + device:emit_event(capabilities.currentMeter.current({value = value.value, unit = "A"})) +end + +local function metering_handler(driver, device, value, zb_rx) + local raw_value = value.value / 1000 -- Convert Wh to kWh + device:emit_event(capabilities.energyMeter.energy({value = raw_value, unit = "kWh"})) +end + +local function temperature_handler(driver, device, value, zb_rx) + device:emit_event(capabilities.temperatureMeasurement.temperature({value = value.value / 100, unit = "C"})) +end + local zigbee_switch_power = { NAME = "Zigbee Switch Power", zigbee_handlers = { attr = { [ElectricalMeasurement.ID] = { - [ElectricalMeasurement.attributes.ActivePower.ID] = active_power_meter_handler + [ElectricalMeasurement.attributes.ActivePower.ID] = active_power_meter_handler, + [ElectricalMeasurement.attributes.RmsVoltage.ID] = rms_voltage_handler, + [ElectricalMeasurement.attributes.RmsCurrent.ID] = rms_current_handler }, [SimpleMetering.ID] = { [SimpleMetering.attributes.InstantaneousDemand.ID] = instantaneous_demand_handler + }, + [Metering.ID] = { + [Metering.attributes.CumulativeEnergy.ID] = metering_handler + }, + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MeasuredValue.ID] = temperature_handler } } }, @@ -44,24 +70,3 @@ local zigbee_switch_power = { } return zigbee_switch_power - - -local function electrical_measurement_handler(driver, device, value, raw) - if value.attr_id == 0x0400 then -- Active Power - device:emit_event(capabilities.powerMeter.power({value = value.value, unit = "W"})) - elseif value.attr_id == 0x0505 then -- RMS Voltage - device:emit_event(capabilities.voltageMeasurement.voltage({value = value.value, unit = "V"})) - elseif value.attr_id == 0x0508 then -- RMS Current - device:emit_event(capabilities.currentMeter.current({value = value.value, unit = "A"})) - end -end - -local function metering_handler(driver, device, value, raw) - if value.attr_id == 0x0000 then -- Cumulative Energy - device:emit_event(capabilities.energyMeter.energy({value = value.value / 1000, unit = "kWh"})) - end -end - -local function temperature_handler(driver, device, value, raw) - device:emit_event(capabilities.temperatureMeasurement.temperature({value = value.value / 100, unit = "C"})) -end From a27425c748befa622c4b38d220f5bee673ab7138 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 6 Dec 2025 20:59:53 -0500 Subject: [PATCH 29/41] Rename profile to switch-power-waterheater and add capabilities --- .../profiles/switch-power-waterheater.yml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml diff --git a/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml new file mode 100644 index 0000000000..f1090a8ef3 --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml @@ -0,0 +1,22 @@ +name: switch-power-waterheater +components: + - id: main + capabilities: + - id: switch + version: 1 + - id: powerMeter + version: 1 + - id: temperatureMeasurement + version: 1 + - id: waterSensor   + version: 1 + - id: voltageMeasurement  + version: 1 + - id: energyMeter + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: SmartPlug From c36116f26a07de4354ddb7a2153d20e69d0329c0 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:00:40 -0500 Subject: [PATCH 30/41] Update deviceProfileName for RM3500ZB device --- drivers/SmartThings/zigbee-switch/fingerprints.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/SmartThings/zigbee-switch/fingerprints.yml b/drivers/SmartThings/zigbee-switch/fingerprints.yml index af25221e26..7f52fa2b72 100644 --- a/drivers/SmartThings/zigbee-switch/fingerprints.yml +++ b/drivers/SmartThings/zigbee-switch/fingerprints.yml @@ -395,7 +395,7 @@ zigbeeManufacturer: deviceLabel: "RM3500ZB Sinope Load Controller" manufacturer: Sinope Technologies model: RM3500ZB - deviceProfileName: sinope-switch-rm3500zb + deviceProfileName: switch-power-waterheater - id: "Sinope Dimmer Switch/DM2500ZB" deviceLabel: "DM2500ZB Sinope Dimmer" manufacturer: Sinope Technologies From 60f4e02db00e455f63e05d32b70892d06501a62c Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:03:42 -0500 Subject: [PATCH 31/41] Create Sinope-waterheater --- drivers/SmartThings/zigbee-switch/src/Sinope-waterheater | 1 + 1 file changed, 1 insertion(+) create mode 100644 drivers/SmartThings/zigbee-switch/src/Sinope-waterheater diff --git a/drivers/SmartThings/zigbee-switch/src/Sinope-waterheater b/drivers/SmartThings/zigbee-switch/src/Sinope-waterheater new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/src/Sinope-waterheater @@ -0,0 +1 @@ + From 27181215db9a472e86beb6c3e7c58d15c2ab98e8 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:04:01 -0500 Subject: [PATCH 32/41] Delete drivers/SmartThings/zigbee-switch/src/Sinope-waterheater --- drivers/SmartThings/zigbee-switch/src/Sinope-waterheater | 1 - 1 file changed, 1 deletion(-) delete mode 100644 drivers/SmartThings/zigbee-switch/src/Sinope-waterheater diff --git a/drivers/SmartThings/zigbee-switch/src/Sinope-waterheater b/drivers/SmartThings/zigbee-switch/src/Sinope-waterheater deleted file mode 100644 index 8b13789179..0000000000 --- a/drivers/SmartThings/zigbee-switch/src/Sinope-waterheater +++ /dev/null @@ -1 +0,0 @@ - From dc5f98479a63a73839e4b60839215aa9091f0298 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:05:44 -0500 Subject: [PATCH 33/41] Create init.lua --- .../SmartThings/zigbee-switch/src/sinope-waterheater/init.lua | 1 + 1 file changed, 1 insertion(+) create mode 100644 drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua diff --git a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua @@ -0,0 +1 @@ + From b0aa01e7183e9421cd0421a5cebe8a35385c7bbf Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:08:00 -0500 Subject: [PATCH 34/41] Update device model check for Sinope water heater --- .../src/sinope-waterheater/can_handle.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 drivers/SmartThings/zigbee-switch/src/sinope-waterheater/can_handle.lua diff --git a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/can_handle.lua b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/can_handle.lua new file mode 100644 index 0000000000..2d215d1b36 --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/can_handle.lua @@ -0,0 +1,12 @@ +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 + +return function(opts, driver, device, ...) + local can_handle = device:get_manufacturer() == "Sinope Technologies" and device:get_model() == "RM3500ZB" + if can_handle then + local subdriver = require("sinope-waterheater") + return true, subdriver + else + return false + end + end From e4e73d464d761cebb47b4d5e51b1632c7f22786b Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:19:16 -0500 Subject: [PATCH 35/41] Update device capabilities in water heater profile --- .../profiles/switch-power-waterheater.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml index f1090a8ef3..1cf883b081 100644 --- a/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml +++ b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml @@ -6,14 +6,18 @@ components: version: 1 - id: powerMeter version: 1 - - id: temperatureMeasurement - version: 1 - - id: waterSensor   + - id: voltageMeasurement version: 1 - - id: voltageMeasurement  + - id: currentMeter version: 1 - id: energyMeter version: 1 + - id: temperatureMeasurement + version: 1 + - id: waterLeak + version: 1 + - id: thermostatCoolingSetpoint + version: 1 # For low water temp protection setpoint - id: firmwareUpdate version: 1 - id: refresh From 31665dc926c521cc0a7d7257f7d8fa9c1907ed41 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:19:41 -0500 Subject: [PATCH 36/41] Delete drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm3500zb.yml --- .../profiles/sinope-switch-rm3500zb.yml | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm3500zb.yml diff --git a/drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm3500zb.yml b/drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm3500zb.yml deleted file mode 100644 index 882f81440e..0000000000 --- a/drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm3500zb.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: sinope-switch-rm3500zb -components: - - id: main - capabilities: - - id: switch - version: 1 - - id: powerMeter - version: 1 - - id: voltageMeasurement - version: 1 - - id: currentMeter - version: 1 - - id: energyMeter - version: 1 - - id: temperatureMeasurement - version: 1 - - id: waterLeak - version: 1 - - id: thermostatCoolingSetpoint - version: 1 # For low water temp protection setpoint - - id: firmwareUpdate - version: 1 - - id: refresh - version: 1 - categories: - - name: SmartPlug From 5cee9ceaa001e2291818c2fd687c0af48bac735a Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:32:30 -0500 Subject: [PATCH 37/41] Add water and voltage sensor capabilities --- drivers/SmartThings/zigbee-switch/src/init.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/zigbee-switch/src/init.lua b/drivers/SmartThings/zigbee-switch/src/init.lua index 1b694d2a5e..438e623dc4 100644 --- a/drivers/SmartThings/zigbee-switch/src/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/init.lua @@ -68,6 +68,9 @@ local zigbee_switch_driver_template = { capabilities.illuminanceMeasurement, capabilities.relativeHumidityMeasurement, capabilities.temperatureMeasurement, + capabilities.waterSensor, + capabilities.voltageMeasurement, + }, sub_drivers = { lazy_load_if_possible("non_zigbee_devices"), @@ -78,6 +81,7 @@ local zigbee_switch_driver_template = { lazy_load_if_possible("rexense"), lazy_load_if_possible("sinope"), lazy_load_if_possible("sinope-dimmer"), + lazy_load_if_possible("sinope-waterheater"), lazy_load_if_possible("zigbee-dimmer-power-energy"), lazy_load_if_possible("zigbee-metering-plug-power-consumption-report"), lazy_load_if_possible("jasco"), @@ -99,6 +103,7 @@ local zigbee_switch_driver_template = { lazy_load_if_possible("laisiao"), lazy_load_if_possible("tuya-multi"), lazy_load_if_possible("frient") + }, zigbee_handlers = { global = { From c8fc2bed346c76e2a7e4e90d2485cdcf0b465651 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:29:50 -0500 Subject: [PATCH 38/41] Update init.lua --- .../src/sinope-waterheater/init.lua | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua index 8b13789179..7a9a9c9553 100644 --- a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua @@ -1 +1,157 @@ +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 + +local cluster_base = require "st.zigbee.cluster_base" +local data_types = require "st.zigbee.data_types" +local capabilities = require "st.capabilities" +local clusters = require "st.zigbee.zcl.clusters" + +local SINOPE_SWITCH_CLUSTER = 0xFF01 +local SINOPE_MAX_INTENSITY_ON_ATTRIBUTE = 0x0052 +local SINOPE_MAX_INTENSITY_OFF_ATTRIBUTE = 0x0053 + +-- RM3500ZB additional manufacturer attributes (0xFF01)[web:45] +local SINOPE_CONNECTED_LOAD_ATTR = 0x0060 -- ConnectedLoad (W)[web:45] +local SINOPE_CURRENT_LOAD_ATTR = 0x0070 -- CurrentLoad (W-ish bitmap)[web:45] +local SINOPE_DR_MIN_WATER_TEMP_ATTR = 0x0076 -- drConfigWaterTempMin (°C)[web:45] +local SINOPE_DR_MIN_WATER_TEMP_TIME_ATTR = 0x0077 -- drConfigWaterTempTime[web:45] +local SINOPE_TIMER_ATTR = 0x00A0 -- Timer seconds[web:45] +local SINOPE_TIMER_COUNTDOWN_ATTR = 0x00A1 -- Timer_countDown[web:45] +local SINOPE_MIN_MEASURED_TEMP_ATTR = 0x007C -- min_measured_temp (°C×100)[web:45] +local SINOPE_MAX_MEASURED_TEMP_ATTR = 0x007D -- max_measured_temp (°C×100)[web:45] +local SINOPE_ENERGY_INTERNAL_ATTR = 0x0090 -- currentSummationDelivered (internal)[web:45] + +local OnOff = clusters.OnOff -- 0x0006 +local TempMeas = clusters.TemperatureMeasurement -- 0x0402 +local IASZone = clusters.IASZone -- 0x0500 +local ElectricalMeasurement = clusters.ElectricalMeasurement -- 0x0B04 +local Metering = clusters.Metering -- 0x0702 + + + +local function info_changed(driver, device, event, args) + -- handle ledIntensity preference setting + if (args.old_st_store.preferences.ledIntensity ~= device.preferences.ledIntensity) then + local ledIntensity = device.preferences.ledIntensity + + device:send(cluster_base.write_attribute(device, + data_types.ClusterId(SINOPE_SWITCH_CLUSTER), + data_types.AttributeId(SINOPE_MAX_INTENSITY_ON_ATTRIBUTE), + data_types.validate_or_build_type(ledIntensity, data_types.Uint8, "payload"))) + device:send(cluster_base.write_attribute(device, + data_types.ClusterId(SINOPE_SWITCH_CLUSTER), + data_types.AttributeId(SINOPE_MAX_INTENSITY_OFF_ATTRIBUTE), + data_types.validate_or_build_type(ledIntensity, data_types.Uint8, "payload"))) + + end + -- Example: DR minimum water temperature preference + if args.old_st_store.preferences.drMinWaterTemp ~= device.preferences.drMinWaterTemp then + local minTemp = device.preferences.drMinWaterTemp -- in °C + device:send(cluster_base.write_attribute( + device, + data_types.ClusterId(SINOPE_SWITCH_CLUSTER), + data_types.AttributeId(SINOPE_DR_MIN_WATER_TEMP_ATTR), + data_types.validate_or_build_type(minTemp, data_types.Uint8, "payload") + )) + end + +end + +local zigbee_sinope_switch = { + NAME = "Zigbee Sinope switch", + lifecycle_handlers = { + infoChanged = info_changed + }, + + zigbee_handlers = { + attr = { + -- Standard clusters used by RM3500ZB[web:41][web:45] + [OnOff.ID] = { + [OnOff.attributes.OnOff.ID] = onoff_attr_handler + }, + [TempMeas.ID] = { + [TempMeas.attributes.MeasuredValue.ID] = water_temp_attr_handler + }, + [IASZone.ID] = { + [IASZone.attributes.ZoneStatus.ID] = leak_attr_handler + }, + [ElectricalMeasurement.ID] = { + [ElectricalMeasurement.attributes.ActivePower.ID] = active_power_attr_handler + }, + [Metering.ID] = { + [Metering.attributes.CurrentSummationDelivered.ID] = energy_attr_handler + }, + + -- Optional: manufacturer-specific 0xFF01 attributes for RM3500ZB[web:45] + [SINOPE_SWITCH_CLUSTER] = { + [SINOPE_CONNECTED_LOAD_ATTR] = sinope_connected_load_handler, + [SINOPE_MIN_MEASURED_TEMP_ATTR] = sinope_min_temp_handler, + [SINOPE_MAX_MEASURED_TEMP_ATTR] = sinope_max_temp_handler, + -- add more as needed (Timer, DR min temp, etc.) + } + } + }, + + capability_handlers = { + [capabilities.switch.ID] = { + [capabilities.switch.commands.on.NAME] = switch_on_handler, + [capabilities.switch.commands.off.NAME] = switch_off_handler, + -- Add mappings for any custom capabilities you define for DR/timer/load here + } + }, + can_handle = require("sinope.can_handle"), +} + +return zigbee_sinope_switch + +-- Switch on/off from 0x0006/0x0000[web:45] +local function onoff_attr_handler(driver, device, value, zb_rx) + if value.value then + device:emit_event(capabilities.switch.switch.on()) + else + device:emit_event(capabilities.switch.switch.off()) + end +end + +-- Water temperature from 0x0402/0x0000 (°C×100)[web:45] +local function water_temp_attr_handler(driver, device, value, zb_rx) + local temp_c = value.value / 100.0 + device:emit_event(capabilities.temperatureMeasurement.temperature({ value = temp_c, unit = "C" })) +end + +-- Leak state from IAS Zone 0x0500/0x0002[web:45] +local function leak_attr_handler(driver, device, value, zb_rx) + local zone_status = value.value + local wet = (bit32.band(zone_status, 0x0001) ~= 0) -- example mask + if wet then + device:emit_event(capabilities.waterSensor.water.wet()) + else + device:emit_event(capabilities.waterSensor.water.dry()) + end +end + +-- Active power from 0x0B04/0x050B[web:45] +local function active_power_attr_handler(driver, device, value, zb_rx) + local power_w = value.value -- apply multiplier/divisor if needed + device:emit_event(capabilities.powerMeter.power({ value = power_w, unit = "W" })) +end + +-- Energy from 0x0702/0x0000 (Wh or kWh with multiplier/divisor)[web:41][web:45] +local function energy_attr_handler(driver, device, value, zb_rx) + local raw = value.value + -- If you read AC Power Multiplier/Divisor, apply here; otherwise assume Wh and convert + local kwh = raw / 1000.0 + device:emit_event(capabilities.energyMeter.energy({ value = kwh, unit = "kWh" })) +end + +local function sinope_min_temp_handler(driver, device, value, zb_rx) + local temp_c = value.value / 100.0 + -- device:emit_event(capabilities["yourNamespace.minTankTemp"].temperature({ value = temp_c, unit = "C" })) +end + +local function sinope_max_temp_handler(driver, device, value, zb_rx) + local temp_c = value.value / 100.0 + -- device:emit_event(capabilities["yourNamespace.maxTankTemp"].temperature({ value = temp_c, unit = "C" })) +end + From 3b375f5ff4d866be71af902b1ee56579f4a2a774 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 2 Jan 2026 21:07:33 -0500 Subject: [PATCH 39/41] Jan2 --- .../profiles/switch-power-waterheater.yml | 4 +- .../src/sinope-waterheater/init.lua | 232 +++++++++++++----- 2 files changed, 171 insertions(+), 65 deletions(-) diff --git a/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml index 1cf883b081..a9901d0588 100644 --- a/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml +++ b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml @@ -17,10 +17,10 @@ components: - id: waterLeak version: 1 - id: thermostatCoolingSetpoint - version: 1 # For low water temp protection setpoint + version: 1 - id: firmwareUpdate version: 1 - id: refresh version: 1 categories: - - name: SmartPlug + - name: SmartPlug \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua index 7a9a9c9553..d522439f59 100644 --- a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua @@ -4,13 +4,14 @@ local cluster_base = require "st.zigbee.cluster_base" local data_types = require "st.zigbee.data_types" local capabilities = require "st.capabilities" +local ZigbeeDriver = require "st.zigbee" +local defaults = require "st.zigbee.defaults" local clusters = require "st.zigbee.zcl.clusters" +-- Sinopé manufacturer cluster and attributes local SINOPE_SWITCH_CLUSTER = 0xFF01 local SINOPE_MAX_INTENSITY_ON_ATTRIBUTE = 0x0052 local SINOPE_MAX_INTENSITY_OFF_ATTRIBUTE = 0x0053 - --- RM3500ZB additional manufacturer attributes (0xFF01)[web:45] local SINOPE_CONNECTED_LOAD_ATTR = 0x0060 -- ConnectedLoad (W)[web:45] local SINOPE_CURRENT_LOAD_ATTR = 0x0070 -- CurrentLoad (W-ish bitmap)[web:45] local SINOPE_DR_MIN_WATER_TEMP_ATTR = 0x0076 -- drConfigWaterTempMin (°C)[web:45] @@ -21,13 +22,157 @@ local SINOPE_MIN_MEASURED_TEMP_ATTR = 0x007C -- min_measured_temp (°C×1 local SINOPE_MAX_MEASURED_TEMP_ATTR = 0x007D -- max_measured_temp (°C×100)[web:45] local SINOPE_ENERGY_INTERNAL_ATTR = 0x0090 -- currentSummationDelivered (internal)[web:45] +-- Standard Zigbee clusters local OnOff = clusters.OnOff -- 0x0006 local TempMeas = clusters.TemperatureMeasurement -- 0x0402 local IASZone = clusters.IASZone -- 0x0500 local ElectricalMeasurement = clusters.ElectricalMeasurement -- 0x0B04 local Metering = clusters.Metering -- 0x0702 +local Thermostat = clusters.Thermostat + +-- Switch on/off from 0x0006/0x0000 +local function onoff_attr_handler(driver, device, value, zb_rx) + if value.value then + device:emit_event(capabilities.switch.switch.on()) + else + device:emit_event(capabilities.switch.switch.off()) + end +end +-- Water temperature from cluster 0x0402, attribute 0x0000 (°C×100) +local function water_temp_attr_handler(driver, device, value, zb_rx) + local temp_c = value.value / 100.0 + device:emit_event(capabilities.temperatureMeasurement.temperature({ + value = temp_c, + unit = "C" + })) +end + +-- Leak state from IAS Zone 0x0500/0x0002[web:45] +local function leak_attr_handler(driver, device, value, zb_rx) + local zone_status = value.value + local wet = (bit32.band(zone_status, 0x0001) ~= 0) -- example mask + if wet then + device:emit_event(capabilities.waterLeak.water.wet()) + else + device:emit_event(capabilities.waterLeak.water.dry()) + end +end + +-- Active power from 0x0B04/0x050B[web:45] +local function active_power_attr_handler(driver, device, value, zb_rx) + local power_w = value.value -- apply multiplier/divisor if needed + device:emit_event(capabilities.powerMeter.power({ value = power_w, unit = "W" })) +end + +-- Energy from 0x0702/0x0000 (Wh or kWh with multiplier/divisor)[web:41][web:45] +local function energy_attr_handler(driver, device, value, zb_rx) + local raw = value.value + -- If you read AC Power Multiplier/Divisor, apply here; otherwise assume Wh and convert + local kwh = raw / 1000.0 + device:emit_event(capabilities.energyMeter.energy({ value = kwh, unit = "kWh" })) + +end + +-- Voltage from Electrical Measurement cluster 0x0B04, attribute 0x0505 +local function voltage_attr_handler(driver, device, value, zb_rx) + local voltage_raw = value.value + -- Device sends in 0.1V increments + local voltage_v = math.floor((voltage_raw / 10) + 0.5) + device:emit_event(capabilities.voltageMeasurement.voltage({ + value = voltage_v, + unit = "V" + })) +end + +-- Current from Electrical Measurement cluster 0x0B04, attribute 0x0508 +local function current_attr_handler(driver, device, value, zb_rx) + local current_raw = value.value + -- Device sends in 0.001A (1mA) increments + local current_a = math.floor((current_raw / 1000) + 0.5) + device:emit_event(capabilities.currentMeter.current({ + value = current_a, + unit = "A" + })) +end + +-- Cooling setpoint from Thermostat cluster 0x0201, attribute 0x0012 +local function cooling_setpoint_attr_handler(driver, device, value, zb_rx) + local setpoint_raw = value.value or 4600 -- Default 46°C + local setpoint_c = setpoint_raw / 100 + device:emit_event(capabilities.thermostatCoolingSetpoint.coolingSetpoint({ + value = math.floor(setpoint_c + 0.5), + unit = "C" + })) +end + +-- Manufacturer-specific: Connected load +local function sinope_connected_load_handler(driver, device, value, zb_rx) + local load_w = value.value + -- You could store this or emit a custom capability event + device:set_field("connected_load", load_w, {persist = true}) +end + +local function sinope_min_temp_handler(driver, device, value, zb_rx) + local temp_c = value.value / 100.0 + -- device:emit_event(capabilities["yourNamespace.minTankTemp"].temperature({ value = temp_c, unit = "C" })) + -- device:set_field("min_measured_temp", temp_c, {persist = true}) +end + +local function sinope_max_temp_handler(driver, device, value, zb_rx) + local temp_c = value.value / 100.0 + -- device:emit_event(capabilities["yourNamespace.maxTankTemp"].temperature({ value = temp_c, unit = "C" })) + -- device:set_field("max_measured_temp", temp_c, {persist = true}) +end +-- ============================================================================= +-- COMMAND HANDLERS +-- ============================================================================= + +-- Handle switch.on command +local function switch_on_handler(driver, device, command) + device:send(OnOff.server.commands.On(device)) +end + +-- Handle switch.off command +local function switch_off_handler(driver, device, command) + device:send(OnOff.server.commands.Off(device)) +end + +-- Handle thermostatCoolingSetpoint.setCoolingSetpoint command +local function set_cooling_setpoint_handler(driver, device, command) + local setpoint_c = command.args.setpoint or 46 + + -- Validate range (RM3500ZB supports 46-55°C) + if setpoint_c < 46 then setpoint_c = 46 end + if setpoint_c > 55 then setpoint_c = 55 end + + local zigbee_value = setpoint_c * 100 + + -- Get current setpoint to calculate delta + local current_setpoint = device:get_field("current_cooling_setpoint") or (46 * 100) + local delta = zigbee_value - current_setpoint + + device:send(Thermostat.server.commands.SetpointRaiseLower(device, 0x02, delta)) + device:set_field("current_cooling_setpoint", zigbee_value, {persist = true}) +end + +-- Handle refresh command +local function refresh_handler(driver, device, command) + -- Read all important attributes + device:send(OnOff.attributes.OnOff:read(device)) + device:send(TempMeas.attributes.MeasuredValue:read(device)) + device:send(Metering.attributes.InstantaneousDemand:read(device)) + device:send(Metering.attributes.CurrentSummationDelivered:read(device)) + device:send(ElectricalMeasurement.attributes.RMSVoltage:read(device)) + device:send(ElectricalMeasurement.attributes.RMSCurrent:read(device)) + device:send(Thermostat.attributes.CoolingSetpoint:read(device)) + device:send(IASZone.attributes.ZoneStatus:read(device)) +end + +-- ============================================================================= +-- PREFERENCE CHANGE HANDLER +-- ============================================================================= local function info_changed(driver, device, event, args) -- handle ledIntensity preference setting @@ -42,7 +187,6 @@ local function info_changed(driver, device, event, args) data_types.ClusterId(SINOPE_SWITCH_CLUSTER), data_types.AttributeId(SINOPE_MAX_INTENSITY_OFF_ATTRIBUTE), data_types.validate_or_build_type(ledIntensity, data_types.Uint8, "payload"))) - end -- Example: DR minimum water temperature preference if args.old_st_store.preferences.drMinWaterTemp ~= device.preferences.drMinWaterTemp then @@ -54,9 +198,12 @@ local function info_changed(driver, device, event, args) data_types.validate_or_build_type(minTemp, data_types.Uint8, "payload") )) end - end +-- ============================================================================= +-- DRIVER DEFINITION (NOW handlers are defined above and can be referenced) +-- ============================================================================= + local zigbee_sinope_switch = { NAME = "Zigbee Sinope switch", lifecycle_handlers = { @@ -65,7 +212,7 @@ local zigbee_sinope_switch = { zigbee_handlers = { attr = { - -- Standard clusters used by RM3500ZB[web:41][web:45] + -- Standard clusters used by RM3500ZB [OnOff.ID] = { [OnOff.attributes.OnOff.ID] = onoff_attr_handler }, @@ -76,15 +223,20 @@ local zigbee_sinope_switch = { [IASZone.attributes.ZoneStatus.ID] = leak_attr_handler }, [ElectricalMeasurement.ID] = { - [ElectricalMeasurement.attributes.ActivePower.ID] = active_power_attr_handler + [ElectricalMeasurement.attributes.RMSVoltage.ID] = voltage_attr_handler, + [ElectricalMeasurement.attributes.RMSCurrent.ID] = current_attr_handler, }, [Metering.ID] = { - [Metering.attributes.CurrentSummationDelivered.ID] = energy_attr_handler + [Metering.attributes.InstantaneousDemand.ID] = power_attr_handler, + [Metering.attributes.CurrentSummationDelivered.ID] = energy_attr_handler, + }, + [Thermostat.ID] = { + [Thermostat.attributes.CoolingSetpoint.ID] = cooling_setpoint_attr_handler, }, -- Optional: manufacturer-specific 0xFF01 attributes for RM3500ZB[web:45] [SINOPE_SWITCH_CLUSTER] = { - [SINOPE_CONNECTED_LOAD_ATTR] = sinope_connected_load_handler, + [SINOPE_CONNECTED_LOAD_ATTR] = sinope_connected_load_handler, [SINOPE_MIN_MEASURED_TEMP_ATTR] = sinope_min_temp_handler, [SINOPE_MAX_MEASURED_TEMP_ATTR] = sinope_max_temp_handler, -- add more as needed (Timer, DR min temp, etc.) @@ -94,64 +246,18 @@ local zigbee_sinope_switch = { capability_handlers = { [capabilities.switch.ID] = { - [capabilities.switch.commands.on.NAME] = switch_on_handler, + [capabilities.switch.commands.on.NAME] = switch_on_handler, [capabilities.switch.commands.off.NAME] = switch_off_handler, -- Add mappings for any custom capabilities you define for DR/timer/load here - } }, + [capabilities.thermostatCoolingSetpoint.ID] = { + [capabilities.thermostatCoolingSetpoint.commands.setCoolingSetpoint.NAME] = set_cooling_setpoint_handler, + }, + [capabilities.refresh.ID] = { + [capabilities.refresh.commands.refresh.NAME] = refresh_handler, + }, +}, can_handle = require("sinope.can_handle"), } -return zigbee_sinope_switch - --- Switch on/off from 0x0006/0x0000[web:45] -local function onoff_attr_handler(driver, device, value, zb_rx) - if value.value then - device:emit_event(capabilities.switch.switch.on()) - else - device:emit_event(capabilities.switch.switch.off()) - end -end - --- Water temperature from 0x0402/0x0000 (°C×100)[web:45] -local function water_temp_attr_handler(driver, device, value, zb_rx) - local temp_c = value.value / 100.0 - device:emit_event(capabilities.temperatureMeasurement.temperature({ value = temp_c, unit = "C" })) -end - --- Leak state from IAS Zone 0x0500/0x0002[web:45] -local function leak_attr_handler(driver, device, value, zb_rx) - local zone_status = value.value - local wet = (bit32.band(zone_status, 0x0001) ~= 0) -- example mask - if wet then - device:emit_event(capabilities.waterSensor.water.wet()) - else - device:emit_event(capabilities.waterSensor.water.dry()) - end -end - --- Active power from 0x0B04/0x050B[web:45] -local function active_power_attr_handler(driver, device, value, zb_rx) - local power_w = value.value -- apply multiplier/divisor if needed - device:emit_event(capabilities.powerMeter.power({ value = power_w, unit = "W" })) -end - --- Energy from 0x0702/0x0000 (Wh or kWh with multiplier/divisor)[web:41][web:45] -local function energy_attr_handler(driver, device, value, zb_rx) - local raw = value.value - -- If you read AC Power Multiplier/Divisor, apply here; otherwise assume Wh and convert - local kwh = raw / 1000.0 - device:emit_event(capabilities.energyMeter.energy({ value = kwh, unit = "kWh" })) -end - -local function sinope_min_temp_handler(driver, device, value, zb_rx) - local temp_c = value.value / 100.0 - -- device:emit_event(capabilities["yourNamespace.minTankTemp"].temperature({ value = temp_c, unit = "C" })) -end - -local function sinope_max_temp_handler(driver, device, value, zb_rx) - local temp_c = value.value / 100.0 - -- device:emit_event(capabilities["yourNamespace.maxTankTemp"].temperature({ value = temp_c, unit = "C" })) -end - - +return zigbee_sinope_switch \ No newline at end of file From d62e1250046bf796b400a448ed0f5ee0f4a5f5e4 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 3 Jan 2026 13:19:03 -0500 Subject: [PATCH 40/41] Fixed Sub-driver structure --- drivers/SmartThings/zigbee-switch/config.yml | 2 +- .../profiles/switch-power-waterheater.yml | 6 +- .../SmartThings/zigbee-switch/src/init.lua | 2 +- .../src/sinope-waterheater/can_handle.lua | 20 +- .../src/sinope-waterheater/init.lua | 345 ++++++++---------- .../src/zigbee-switch-power/init.lua | 15 +- 6 files changed, 178 insertions(+), 212 deletions(-) diff --git a/drivers/SmartThings/zigbee-switch/config.yml b/drivers/SmartThings/zigbee-switch/config.yml index 32ad44a36e..74e58c52da 100644 --- a/drivers/SmartThings/zigbee-switch/config.yml +++ b/drivers/SmartThings/zigbee-switch/config.yml @@ -1,4 +1,4 @@ -name: 'Zigbee Switch' +name: 'Zigbee Switch Vx' packageKey: 'zigbee-switch' permissions: zigbee: {} diff --git a/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml index a9901d0588..327a3dca2b 100644 --- a/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml +++ b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml @@ -8,13 +8,13 @@ components: version: 1 - id: voltageMeasurement version: 1 - - id: currentMeter - version: 1 + # - id: currentMeter + # version: 1 - id: energyMeter version: 1 - id: temperatureMeasurement version: 1 - - id: waterLeak + - id: waterSensor version: 1 - id: thermostatCoolingSetpoint version: 1 diff --git a/drivers/SmartThings/zigbee-switch/src/init.lua b/drivers/SmartThings/zigbee-switch/src/init.lua index 438e623dc4..cc2c6a45ec 100644 --- a/drivers/SmartThings/zigbee-switch/src/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/init.lua @@ -81,7 +81,7 @@ local zigbee_switch_driver_template = { lazy_load_if_possible("rexense"), lazy_load_if_possible("sinope"), lazy_load_if_possible("sinope-dimmer"), - lazy_load_if_possible("sinope-waterheater"), + require("sinope-waterheater"), lazy_load_if_possible("zigbee-dimmer-power-energy"), lazy_load_if_possible("zigbee-metering-plug-power-consumption-report"), lazy_load_if_possible("jasco"), diff --git a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/can_handle.lua b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/can_handle.lua index 2d215d1b36..4a1b216130 100644 --- a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/can_handle.lua +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/can_handle.lua @@ -1,12 +1,16 @@ -- Copyright 2025 SmartThings, Inc. -- Licensed under the Apache License, Version 2.0 -return function(opts, driver, device, ...) - local can_handle = device:get_manufacturer() == "Sinope Technologies" and device:get_model() == "RM3500ZB" - if can_handle then - local subdriver = require("sinope-waterheater") - return true, subdriver - else - return false - end +local function can_handle_sinope_rm3500zb(opts, driver, device, ...) + if device ~= nil then + local manufacturer = device:get_manufacturer() + local model = device:get_model() + + -- Check if this is an RM3500ZB + return manufacturer == "Sinope Technologies" and model == "RM3500ZB" end + + return false +end + +return can_handle_sinope_rm3500zb \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua index d522439f59..8a23dd3f4b 100644 --- a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua @@ -7,6 +7,7 @@ local capabilities = require "st.capabilities" local ZigbeeDriver = require "st.zigbee" local defaults = require "st.zigbee.defaults" local clusters = require "st.zigbee.zcl.clusters" +local log = require "log" -- Sinopé manufacturer cluster and attributes local SINOPE_SWITCH_CLUSTER = 0xFF01 @@ -23,241 +24,201 @@ local SINOPE_MAX_MEASURED_TEMP_ATTR = 0x007D -- max_measured_temp (°C×1 local SINOPE_ENERGY_INTERNAL_ATTR = 0x0090 -- currentSummationDelivered (internal)[web:45] -- Standard Zigbee clusters +local SimpleMetering = clusters.SimpleMetering -- 0x0702 local OnOff = clusters.OnOff -- 0x0006 -local TempMeas = clusters.TemperatureMeasurement -- 0x0402 +local TemperatureMeasurement = clusters.TemperatureMeasurement -- 0x0402 local IASZone = clusters.IASZone -- 0x0500 local ElectricalMeasurement = clusters.ElectricalMeasurement -- 0x0B04 -local Metering = clusters.Metering -- 0x0702 -local Thermostat = clusters.Thermostat - - --- Switch on/off from 0x0006/0x0000 -local function onoff_attr_handler(driver, device, value, zb_rx) - if value.value then - device:emit_event(capabilities.switch.switch.on()) - else - device:emit_event(capabilities.switch.switch.off()) - end -end - --- Water temperature from cluster 0x0402, attribute 0x0000 (°C×100) -local function water_temp_attr_handler(driver, device, value, zb_rx) - local temp_c = value.value / 100.0 - device:emit_event(capabilities.temperatureMeasurement.temperature({ - value = temp_c, - unit = "C" - })) -end +local Thermostat = clusters.Thermostat -- Leak state from IAS Zone 0x0500/0x0002[web:45] local function leak_attr_handler(driver, device, value, zb_rx) + log.info("========================================") + log.info("RM3500ZB LEAK HANDLER CALLED") local zone_status = value.value local wet = (bit32.band(zone_status, 0x0001) ~= 0) -- example mask if wet then - device:emit_event(capabilities.waterLeak.water.wet()) + device:emit_event(capabilities.waterSensor.water.wet()) else - device:emit_event(capabilities.waterLeak.water.dry()) + device:emit_event(capabilities.waterSensor.water.dry()) end end --- Active power from 0x0B04/0x050B[web:45] -local function active_power_attr_handler(driver, device, value, zb_rx) - local power_w = value.value -- apply multiplier/divisor if needed - device:emit_event(capabilities.powerMeter.power({ value = power_w, unit = "W" })) -end +-- -- Active power from 0x0B04/0x050B[web:45] +-- local function active_power_meter_handler(driver, device, value, zb_rx) +-- log.info("========================================") +-- log.info("RM3500ZB POWERMETER HANDLER CALLED") +-- local raw_value = value.value +-- local divisor = device:get_field(constants.ELECTRICAL_MEASUREMENT_DIVISOR_KEY) or 10 --- Energy from 0x0702/0x0000 (Wh or kWh with multiplier/divisor)[web:41][web:45] -local function energy_attr_handler(driver, device, value, zb_rx) - local raw = value.value - -- If you read AC Power Multiplier/Divisor, apply here; otherwise assume Wh and convert - local kwh = raw / 1000.0 - device:emit_event(capabilities.energyMeter.energy({ value = kwh, unit = "kWh" })) - -end +-- raw_value = raw_value / divisor --- Voltage from Electrical Measurement cluster 0x0B04, attribute 0x0505 -local function voltage_attr_handler(driver, device, value, zb_rx) - local voltage_raw = value.value - -- Device sends in 0.1V increments - local voltage_v = math.floor((voltage_raw / 10) + 0.5) - device:emit_event(capabilities.voltageMeasurement.voltage({ - value = voltage_v, - unit = "V" - })) -end +-- device:emit_event(capabilities.powerMeter.power({value = raw_value, unit = "W"})) +-- end --- Current from Electrical Measurement cluster 0x0B04, attribute 0x0508 -local function current_attr_handler(driver, device, value, zb_rx) - local current_raw = value.value - -- Device sends in 0.001A (1mA) increments - local current_a = math.floor((current_raw / 1000) + 0.5) - device:emit_event(capabilities.currentMeter.current({ - value = current_a, - unit = "A" - })) -end +local function instantaneous_demand_handler(driver, device, value, zb_rx) + log.info("========================================") + log.info("RM3500ZB INSTANTMETER HANDLER CALLED") + local raw_value = value.value + local divisor = device:get_field(constants.SIMPLE_METERING_DIVISOR_KEY) or 10 --- Cooling setpoint from Thermostat cluster 0x0201, attribute 0x0012 -local function cooling_setpoint_attr_handler(driver, device, value, zb_rx) - local setpoint_raw = value.value or 4600 -- Default 46°C - local setpoint_c = setpoint_raw / 100 - device:emit_event(capabilities.thermostatCoolingSetpoint.coolingSetpoint({ - value = math.floor(setpoint_c + 0.5), - unit = "C" - })) -end + raw_value = raw_value / divisor --- Manufacturer-specific: Connected load -local function sinope_connected_load_handler(driver, device, value, zb_rx) - local load_w = value.value - -- You could store this or emit a custom capability event - device:set_field("connected_load", load_w, {persist = true}) + device:emit_event(capabilities.powerMeter.power({value = raw_value, unit = "W"})) end - -local function sinope_min_temp_handler(driver, device, value, zb_rx) - local temp_c = value.value / 100.0 - -- device:emit_event(capabilities["yourNamespace.minTankTemp"].temperature({ value = temp_c, unit = "C" })) - -- device:set_field("min_measured_temp", temp_c, {persist = true}) +local function rms_voltage_handler(driver, device, value, zb_rx) + log.info("========================================") + log.info("RM3500ZB RMSVOLTS HANDLER CALLED") + device:emit_event(capabilities.voltageMeasurement.voltage({value = value.value, unit = "V"})) end -local function sinope_max_temp_handler(driver, device, value, zb_rx) - local temp_c = value.value / 100.0 - -- device:emit_event(capabilities["yourNamespace.maxTankTemp"].temperature({ value = temp_c, unit = "C" })) - -- device:set_field("max_measured_temp", temp_c, {persist = true}) -end --- ============================================================================= --- COMMAND HANDLERS --- ============================================================================= +-- local function rms_current_handler(driver, device, value, zb_rx) +-- log.info("========================================") +-- log.info("RM3500ZB RMS CURRENT HANDLER CALLED") +-- device:emit_event(capabilities.currentMeter.current({value = value.value, unit = "A"})) +-- end --- Handle switch.on command -local function switch_on_handler(driver, device, command) - device:send(OnOff.server.commands.On(device)) +local function metering_handler(driver, device, value, zb_rx) + log.info("========================================") + log.info("RM3500ZB ENERGYMETER HANDLER CALLED") + local raw_value = value.value / 1000 -- Convert Wh to kWh + device:emit_event(capabilities.energyMeter.energy({value = raw_value, unit = "kWh"})) end --- Handle switch.off command -local function switch_off_handler(driver, device, command) - device:send(OnOff.server.commands.Off(device)) +local function temperature_handler(driver, device, value, zb_rx) + log.info("========================================") + log.info("RM3500ZB TEMPERATURE HANDLER CALLED") + log.info("========================================") + local temp_c = value.value /100 + log.warn(string.format("RM3500ZB: Temperature below 0°C (%.2f°C) - ignoring", temp_c)) + if temp_c > -100 then + device:emit_event(capabilities.temperatureMeasurement.temperature({value = value.value / 100, unit = "C"})) + return + end end --- Handle thermostatCoolingSetpoint.setCoolingSetpoint command -local function set_cooling_setpoint_handler(driver, device, command) - local setpoint_c = command.args.setpoint or 46 - - -- Validate range (RM3500ZB supports 46-55°C) - if setpoint_c < 46 then setpoint_c = 46 end - if setpoint_c > 55 then setpoint_c = 55 end - - local zigbee_value = setpoint_c * 100 - - -- Get current setpoint to calculate delta - local current_setpoint = device:get_field("current_cooling_setpoint") or (46 * 100) - local delta = zigbee_value - current_setpoint - - device:send(Thermostat.server.commands.SetpointRaiseLower(device, 0x02, delta)) - device:set_field("current_cooling_setpoint", zigbee_value, {persist = true}) -end +-- ============================================================================ +-- CONFIGURE HANDLER - Set reporting intervals +-- ============================================================================ --- Handle refresh command -local function refresh_handler(driver, device, command) - -- Read all important attributes - device:send(OnOff.attributes.OnOff:read(device)) - device:send(TempMeas.attributes.MeasuredValue:read(device)) - device:send(Metering.attributes.InstantaneousDemand:read(device)) - device:send(Metering.attributes.CurrentSummationDelivered:read(device)) +local function do_configure(driver, device) + log.info("========================================") + log.info("RM3500ZB DOCONFIG HANDLER CALLED") + log.info("========================================") + + -- Configure Temperature reporting (every 30s to 5min, on 0.5°C change) + device:send(TemperatureMeasurement.attributes.MeasuredValue:configure_reporting( + device, + 60, -- min_report_interval (seconds) + 900, -- max_report_interval (seconds) + 50 -- reportable_change (0.5°C, in 0.01°C units) + )) + + -- Configure Power reporting (every 10s to 60s, on 5W change) + device:send(SimpleMetering.attributes.InstantaneousDemand:configure_reporting( + device, + 10, -- min interval: 10 seconds + 900, -- max interval: 15 minute + 50 -- reportable change: 5W (in 0.1W units) + )) + + -- Configure Energy reporting (every 5min to 30min, on 0.01 kWh change) + device:send(SimpleMetering.attributes.CurrentSummationDelivered:configure_reporting( + device, + 300, -- min interval: 5 minutes + 1800, -- max interval: 30 minutes + 10 -- reportable change: 0.01 kWh (in 0.001 kWh units) + )) + + -- Configure Voltage reporting (every 60s to 5min, on 1V change) + device:send(ElectricalMeasurement.attributes.RMSVoltage:configure_reporting( + device, + 60, -- min interval: 1 minute + 1800, -- max interval: 30 minutes + 10 -- reportable change: 1V (in 0.1V units) + )) + + -- Configure Current reporting (every 10s to 60s, on 0.1A change) + device:send(ElectricalMeasurement.attributes.RMSCurrent:configure_reporting( + device, + 10, -- min interval: 10 seconds + 900, -- max interval: 15 minute + 500 -- reportable change: 0.1A (in 0.001A units) + )) + + -- Configure IAS Zone reporting (water leak detection) + device:send(IASZone.attributes.ZoneStatus:configure_reporting( + device, + 0, -- min interval: immediate + 1800, -- max interval: 30 minutes + 1 -- reportable change: any change + )) + + -- Configure On/Off reporting + device:send(OnOff.attributes.OnOff:configure_reporting( + device, + 0, -- min interval: immediate + 1800, -- max interval: 30 minutes + 1 -- reportable change: any change + )) + + -- Refresh all values after configuration + device:send(TemperatureMeasurement.attributes.MeasuredValue:read(device)) + device:send(SimpleMetering.attributes.InstantaneousDemand:read(device)) + device:send(SimpleMetering.attributes.CurrentSummationDelivered:read(device)) device:send(ElectricalMeasurement.attributes.RMSVoltage:read(device)) device:send(ElectricalMeasurement.attributes.RMSCurrent:read(device)) - device:send(Thermostat.attributes.CoolingSetpoint:read(device)) device:send(IASZone.attributes.ZoneStatus:read(device)) + device:send(OnOff.attributes.OnOff:read(device)) end --- ============================================================================= --- PREFERENCE CHANGE HANDLER --- ============================================================================= - -local function info_changed(driver, device, event, args) - -- handle ledIntensity preference setting - if (args.old_st_store.preferences.ledIntensity ~= device.preferences.ledIntensity) then - local ledIntensity = device.preferences.ledIntensity - - device:send(cluster_base.write_attribute(device, - data_types.ClusterId(SINOPE_SWITCH_CLUSTER), - data_types.AttributeId(SINOPE_MAX_INTENSITY_ON_ATTRIBUTE), - data_types.validate_or_build_type(ledIntensity, data_types.Uint8, "payload"))) - device:send(cluster_base.write_attribute(device, - data_types.ClusterId(SINOPE_SWITCH_CLUSTER), - data_types.AttributeId(SINOPE_MAX_INTENSITY_OFF_ATTRIBUTE), - data_types.validate_or_build_type(ledIntensity, data_types.Uint8, "payload"))) - end - -- Example: DR minimum water temperature preference - if args.old_st_store.preferences.drMinWaterTemp ~= device.preferences.drMinWaterTemp then - local minTemp = device.preferences.drMinWaterTemp -- in °C - device:send(cluster_base.write_attribute( - device, - data_types.ClusterId(SINOPE_SWITCH_CLUSTER), - data_types.AttributeId(SINOPE_DR_MIN_WATER_TEMP_ATTR), - data_types.validate_or_build_type(minTemp, data_types.Uint8, "payload") - )) - end +local function do_refresh(driver, device) + log.info("========================================") + log.info("RM3500ZB DOREFRESH HANDLER CALLED") + log.info("========================================") + + -- Refresh all values + device:send(TemperatureMeasurement.attributes.MeasuredValue:read(device)) + device:send(SimpleMetering.attributes.InstantaneousDemand:read(device)) + device:send(SimpleMetering.attributes.CurrentSummationDelivered:read(device)) + device:send(ElectricalMeasurement.attributes.RMSVoltage:read(device)) + device:send(ElectricalMeasurement.attributes.RMSCurrent:read(device)) + device:send(IASZone.attributes.ZoneStatus:read(device)) + device:send(OnOff.attributes.OnOff:read(device)) end --- ============================================================================= --- DRIVER DEFINITION (NOW handlers are defined above and can be referenced) --- ============================================================================= +-- ============================================================================ +-- DRIVER DEFINITION +-- ============================================================================ -local zigbee_sinope_switch = { - NAME = "Zigbee Sinope switch", +local sinope_rm3500zb = { + NAME = "Sinopé RM3500ZB Water Heater", + capability_handlers = { + [capabilities.refresh.ID] = { + [capabilities.refresh.commands.refresh.NAME] = do_refresh, + } + }, lifecycle_handlers = { - infoChanged = info_changed + doConfigure = do_configure, -- Called when device is added/configured }, - zigbee_handlers = { attr = { - -- Standard clusters used by RM3500ZB - [OnOff.ID] = { - [OnOff.attributes.OnOff.ID] = onoff_attr_handler - }, - [TempMeas.ID] = { - [TempMeas.attributes.MeasuredValue.ID] = water_temp_attr_handler - }, - [IASZone.ID] = { - [IASZone.attributes.ZoneStatus.ID] = leak_attr_handler - }, [ElectricalMeasurement.ID] = { - [ElectricalMeasurement.attributes.RMSVoltage.ID] = voltage_attr_handler, - [ElectricalMeasurement.attributes.RMSCurrent.ID] = current_attr_handler, + [ElectricalMeasurement.attributes.ActivePower.ID] = active_power_meter_handler, + [ElectricalMeasurement.attributes.RMSVoltage.ID] = rms_voltage_handler, + [ElectricalMeasurement.attributes.RMSCurrent.ID] = rms_current_handler }, - [Metering.ID] = { - [Metering.attributes.InstantaneousDemand.ID] = power_attr_handler, - [Metering.attributes.CurrentSummationDelivered.ID] = energy_attr_handler, + [SimpleMetering.ID] = { + [SimpleMetering.attributes.InstantaneousDemand.ID] = instantaneous_demand_handler, + [SimpleMetering.attributes.CurrentSummationDelivered.ID] = metering_handler }, - [Thermostat.ID] = { - [Thermostat.attributes.CoolingSetpoint.ID] = cooling_setpoint_attr_handler, + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MeasuredValue.ID] = temperature_handler }, - - -- Optional: manufacturer-specific 0xFF01 attributes for RM3500ZB[web:45] - [SINOPE_SWITCH_CLUSTER] = { - [SINOPE_CONNECTED_LOAD_ATTR] = sinope_connected_load_handler, - [SINOPE_MIN_MEASURED_TEMP_ATTR] = sinope_min_temp_handler, - [SINOPE_MAX_MEASURED_TEMP_ATTR] = sinope_max_temp_handler, - -- add more as needed (Timer, DR min temp, etc.) - } - } + }, }, - - capability_handlers = { - [capabilities.switch.ID] = { - [capabilities.switch.commands.on.NAME] = switch_on_handler, - [capabilities.switch.commands.off.NAME] = switch_off_handler, - -- Add mappings for any custom capabilities you define for DR/timer/load here - }, - [capabilities.thermostatCoolingSetpoint.ID] = { - [capabilities.thermostatCoolingSetpoint.commands.setCoolingSetpoint.NAME] = set_cooling_setpoint_handler, - }, - [capabilities.refresh.ID] = { - [capabilities.refresh.commands.refresh.NAME] = refresh_handler, - }, -}, - can_handle = require("sinope.can_handle"), + can_handle = require("sinope-waterheater.can_handle") } -return zigbee_sinope_switch \ No newline at end of file + +return sinope_rm3500zb \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-switch/src/zigbee-switch-power/init.lua b/drivers/SmartThings/zigbee-switch/src/zigbee-switch-power/init.lua index 372610774b..eb2138b84c 100644 --- a/drivers/SmartThings/zigbee-switch/src/zigbee-switch-power/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/zigbee-switch-power/init.lua @@ -8,7 +8,6 @@ local constants = require "st.zigbee.constants" local SimpleMetering = clusters.SimpleMetering local ElectricalMeasurement = clusters.ElectricalMeasurement local TemperatureMeasurement = clusters.TemperatureMeasurement -local Metering = clusters.Metering local function active_power_meter_handler(driver, device, value, zb_rx) local raw_value = value.value @@ -42,6 +41,9 @@ local function metering_handler(driver, device, value, zb_rx) end local function temperature_handler(driver, device, value, zb_rx) + log.info("========================================") + log.info("ZIGBEE GENERIC SWITCHPOWER TEMPERATURE HANDLER CALLED") + log.info("========================================") device:emit_event(capabilities.temperatureMeasurement.temperature({value = value.value / 100, unit = "C"})) end @@ -51,14 +53,13 @@ local zigbee_switch_power = { attr = { [ElectricalMeasurement.ID] = { [ElectricalMeasurement.attributes.ActivePower.ID] = active_power_meter_handler, - [ElectricalMeasurement.attributes.RmsVoltage.ID] = rms_voltage_handler, - [ElectricalMeasurement.attributes.RmsCurrent.ID] = rms_current_handler + [ElectricalMeasurement.attributes.RMSVoltage.ID] = rms_voltage_handler, + [ElectricalMeasurement.attributes.RMSCurrent.ID] = rms_current_handler }, [SimpleMetering.ID] = { - [SimpleMetering.attributes.InstantaneousDemand.ID] = instantaneous_demand_handler - }, - [Metering.ID] = { - [Metering.attributes.CumulativeEnergy.ID] = metering_handler + [SimpleMetering.attributes.InstantaneousDemand.ID] = instantaneous_demand_handler, + [SimpleMetering.attributes.CurrentSummationDelivered.ID] = metering_handler + }, [TemperatureMeasurement.ID] = { [TemperatureMeasurement.attributes.MeasuredValue.ID] = temperature_handler From eaf4d788e88ce1b60331ad5ce674b02676e6c514 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 3 Jan 2026 13:22:04 -0500 Subject: [PATCH 41/41] Refactor active power meter handler function removed comment for leak sensor --- .../src/sinope-waterheater/init.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua index 8a23dd3f4b..aa50dff907 100644 --- a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua @@ -45,16 +45,16 @@ local function leak_attr_handler(driver, device, value, zb_rx) end -- -- Active power from 0x0B04/0x050B[web:45] --- local function active_power_meter_handler(driver, device, value, zb_rx) --- log.info("========================================") --- log.info("RM3500ZB POWERMETER HANDLER CALLED") --- local raw_value = value.value --- local divisor = device:get_field(constants.ELECTRICAL_MEASUREMENT_DIVISOR_KEY) or 10 + local function active_power_meter_handler(driver, device, value, zb_rx) + log.info("========================================") + log.info("RM3500ZB POWERMETER HANDLER CALLED") + local raw_value = value.value + local divisor = device:get_field(constants.ELECTRICAL_MEASUREMENT_DIVISOR_KEY) or 10 --- raw_value = raw_value / divisor + raw_value = raw_value / divisor --- device:emit_event(capabilities.powerMeter.power({value = raw_value, unit = "W"})) --- end + device:emit_event(capabilities.powerMeter.power({value = raw_value, unit = "W"})) + end local function instantaneous_demand_handler(driver, device, value, zb_rx) log.info("========================================") @@ -221,4 +221,4 @@ local sinope_rm3500zb = { } -return sinope_rm3500zb \ No newline at end of file +return sinope_rm3500zb