From 49869aae9d62da86ad5b69358fa50a3b146051b7 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Sat, 3 Jan 2026 13:56:26 -0500 Subject: [PATCH 1/6] First Working version of the RM3500ZB --- .../src/sinope-waterheater/init.lua | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 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..5e1aedc128 100644 --- a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua @@ -32,7 +32,7 @@ local ElectricalMeasurement = clusters.ElectricalMeasurement -- 0x0B04 local Thermostat = clusters.Thermostat -- Leak state from IAS Zone 0x0500/0x0002[web:45] -local function leak_attr_handler(driver, device, value, zb_rx) +local function water_sensor_handler(driver, device, value, zb_rx) log.info("========================================") log.info("RM3500ZB LEAK HANDLER CALLED") local zone_status = value.value @@ -101,11 +101,11 @@ end -- CONFIGURE HANDLER - Set reporting intervals -- ============================================================================ -local function do_configure(driver, device) +local function configure_device(driver, device) log.info("========================================") - log.info("RM3500ZB DOCONFIG HANDLER CALLED") + log.info("RM3500ZB CONFIGURE DEVICE HANDLER CALLED") log.info("========================================") - + -- Configure Temperature reporting (every 30s to 5min, on 0.5°C change) device:send(TemperatureMeasurement.attributes.MeasuredValue:configure_reporting( device, @@ -199,7 +199,7 @@ local sinope_rm3500zb = { } }, lifecycle_handlers = { - doConfigure = do_configure, -- Called when device is added/configured + init = configure_device, -- Called when device is added/configured }, zigbee_handlers = { attr = { @@ -215,10 +215,16 @@ local sinope_rm3500zb = { [TemperatureMeasurement.ID] = { [TemperatureMeasurement.attributes.MeasuredValue.ID] = temperature_handler }, + [IASZone.ID] = { + [IASZone.attributes.ZoneStatus.ID] = water_sensor_handler + }, }, }, can_handle = require("sinope-waterheater.can_handle") } -return sinope_rm3500zb \ No newline at end of file +return sinope_rm3500zb + + + From 5ca40d35764952916de27dd5d43d28471437a6b3 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Tue, 6 Jan 2026 20:32:18 -0500 Subject: [PATCH 2/6] Commit --- .../src/sinope-waterheater/init.lua | 64 +++++++++++-------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua index 5e1aedc128..0c177c1627 100644 --- a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua @@ -10,9 +10,9 @@ local clusters = require "st.zigbee.zcl.clusters" local log = require "log" -- Sinopé manufacturer cluster and attributes -local SINOPE_SWITCH_CLUSTER = 0xFF01 -local SINOPE_MAX_INTENSITY_ON_ATTRIBUTE = 0x0052 -local SINOPE_MAX_INTENSITY_OFF_ATTRIBUTE = 0x0053 +local SINOPE_SWITCH_CLUSTER = 0xFF01 +local SINOPE_MAX_INTENSITY_ON_ATTRIBUTE = 0x0052 +local SINOPE_MAX_INTENSITY_OFF_ATTRIBUTE = 0x0053 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] @@ -24,12 +24,22 @@ 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 TemperatureMeasurement = clusters.TemperatureMeasurement -- 0x0402 -local IASZone = clusters.IASZone -- 0x0500 -local ElectricalMeasurement = clusters.ElectricalMeasurement -- 0x0B04 -local Thermostat = clusters.Thermostat +local SimpleMetering = clusters.SimpleMetering -- 0x0702 +local OnOff = clusters.OnOff -- 0x0006 +local TemperatureMeasurement = clusters.TemperatureMeasurement -- 0x0402 +local IASZone = clusters.IASZone -- 0x0500 +local ElectricalMeasurement = clusters.ElectricalMeasurement -- 0x0B04 +local Thermostat = clusters.Thermostat + +--Water mon temp config +-- Cluster: 0xff01 +-- Attribute: 0x0076 +-- Data type: t.uint8_t +-- Function: drConfigWaterTempMin +-- Values: 45 or 0 + + + -- Leak state from IAS Zone 0x0500/0x0002[web:45] local function water_sensor_handler(driver, device, value, zb_rx) @@ -44,39 +54,36 @@ local function water_sensor_handler(driver, device, value, zb_rx) end 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 - --- raw_value = raw_value / divisor +-- 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 + raw_value = raw_value / 10 --- 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("========================================") log.info("RM3500ZB INSTANTMETER HANDLER CALLED") local raw_value = value.value - local divisor = device:get_field(constants.SIMPLE_METERING_DIVISOR_KEY) or 10 - - raw_value = raw_value / divisor + raw_value = raw_value / 10 device:emit_event(capabilities.powerMeter.power({value = raw_value, unit = "W"})) end + 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 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 +local function rms_current_handler(driver, device, value, zb_rx) + log.info("========================================") + log.info("RM3500ZB RMS CURRENT HANDLER CALLED") + device:emit_event(capabilities.currentMeasurement.current({value = value.value, unit = "A"})) +end local function metering_handler(driver, device, value, zb_rx) log.info("========================================") @@ -90,7 +97,7 @@ local function temperature_handler(driver, device, value, zb_rx) 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)) + -- the RM3500ZB may report 2 types of values with one in the -300 range. This only sends the value if it is over -100 deg C if temp_c > -100 then device:emit_event(capabilities.temperatureMeasurement.temperature({value = value.value / 100, unit = "C"})) return @@ -181,6 +188,7 @@ local function do_refresh(driver, device) 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.ActivePower:read(device)) device:send(ElectricalMeasurement.attributes.RMSVoltage:read(device)) device:send(ElectricalMeasurement.attributes.RMSCurrent:read(device)) device:send(IASZone.attributes.ZoneStatus:read(device)) From 48c23f81215e7235e9bf0763d0443c45502c9f59 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Tue, 6 Jan 2026 20:32:34 -0500 Subject: [PATCH 3/6] current MEter --- .../zigbee-switch/profiles/switch-power-waterheater.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml index 327a3dca2b..650c4a1510 100644 --- a/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml +++ b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml @@ -8,8 +8,8 @@ components: version: 1 - id: voltageMeasurement version: 1 - # - id: currentMeter - # version: 1 + - id: currentMeasurement + version: 1 - id: energyMeter version: 1 - id: temperatureMeasurement From 8659421ae9fc94e4cd73de62d4b511c23d2d8ec8 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 9 Jan 2026 07:24:44 -0500 Subject: [PATCH 4/6] All working excetp settings --- .../profiles/switch-power-waterheater.yml | 70 +++- .../src/sinope-waterheater/init.lua | 300 +++++++++++++++--- 2 files changed, 323 insertions(+), 47 deletions(-) diff --git a/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml index 650c4a1510..5be7899c86 100644 --- a/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml +++ b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml @@ -6,21 +6,77 @@ components: version: 1 - id: powerMeter version: 1 + - id: temperatureMeasurement + version: 1 + - id: waterSensor + version: 1 - id: voltageMeasurement version: 1 - id: currentMeasurement version: 1 - id: energyMeter version: 1 - - id: temperatureMeasurement - version: 1 - - id: waterSensor - version: 1 - - id: thermostatCoolingSetpoint - version: 1 - id: firmwareUpdate version: 1 - id: refresh version: 1 categories: - - name: SmartPlug \ No newline at end of file + - name: SmartPlug + +preferences: + - name: "lowTempProtection" + title: "Low Water Temperature Protection" + description: "Minimum temperature threshold to restart water heater" + required: false + preferenceType: enumeration + definition: + options: + 0: "OFF" + 45: "45 °C" + 46: "46 °C" + 47: "47 °C" + 48: "48 °C" + 49: "49 °C" + 50: "50 °C" + 51: "51 °C" + 52: "52 °C" + 53: "53 °C" + 54: "54 °C" + 55: "55 °C" + default: 45 + + - title: "Min Measured Temperature" + name: minMeasuredTemp + description: "Lowest temperature recorded (°C) - Read Only" + required: false + preferenceType: number + definition: + minimum: -50 + maximum: 100 + default: 0 + + - title: "Max Measured Temperature" + name: maxMeasuredTemp + description: "Highest temperature recorded (°C) - Read Only" + required: false + preferenceType: number + definition: + minimum: -50 + maximum: 100 + default: 0 + + + + # Tank Size not used yet + # - name: "tankSize" + # title: "Tank Size" + # description: "Select the size of the hot water tank" + # required: false + # preferenceType: enumeration + # definition: + # options: + # 40: "40 Gal" + # 50: "50 Gal" + # 60: "60 Gal" + # 80: "80 Gal" + # default: 40 \ 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 0c177c1627..0cc10563f7 100644 --- a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua @@ -8,20 +8,21 @@ local ZigbeeDriver = require "st.zigbee" local defaults = require "st.zigbee.defaults" local clusters = require "st.zigbee.zcl.clusters" local log = require "log" +local zb_utils = require "st.zigbee.utils" -- Sinopé manufacturer cluster and attributes local SINOPE_SWITCH_CLUSTER = 0xFF01 local SINOPE_MAX_INTENSITY_ON_ATTRIBUTE = 0x0052 local SINOPE_MAX_INTENSITY_OFF_ATTRIBUTE = 0x0053 -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 SINOPE_CONNECTED_LOAD_ATTR = 0x0060 -- ConnectedLoad (W) +local SINOPE_CURRENT_LOAD_ATTR = 0x0070 -- CurrentLoad (W-ish bitmap) +local SINOPE_DR_MIN_WATER_TEMP_ATTR = 0x0076 -- drConfigWaterTempMin (°C) +local SINOPE_DR_MIN_WATER_TEMP_TIME_ATTR = 0x0077 -- drConfigWaterTempTime +local SINOPE_TIMER_ATTR = 0x00A0 -- Timer seconds +local SINOPE_TIMER_COUNTDOWN_ATTR = 0x00A1 -- Timer_countDown +local SINOPE_MIN_MEASURED_TEMP_ATTR = 0x007C -- min_measured_temp (°C×100) +local SINOPE_MAX_MEASURED_TEMP_ATTR = 0x007D -- max_measured_temp (°C×100) +local SINOPE_ENERGY_INTERNAL_ATTR = 0x0090 -- currentSummationDelivered (internal) -- Standard Zigbee clusters local SimpleMetering = clusters.SimpleMetering -- 0x0702 @@ -38,10 +39,11 @@ local Thermostat = clusters.Thermostat -- Function: drConfigWaterTempMin -- Values: 45 or 0 +-- ============================================================================ +-- STANDARD ATTRIBUTE HANDLERS +-- ============================================================================ - - --- Leak state from IAS Zone 0x0500/0x0002[web:45] +-- Leak state from IAS Zone 0x0500/0x0002 local function water_sensor_handler(driver, device, value, zb_rx) log.info("========================================") log.info("RM3500ZB LEAK HANDLER CALLED") @@ -54,23 +56,19 @@ local function water_sensor_handler(driver, device, value, zb_rx) end end --- Active power from 0x0B04/0x050B[web:45] +-- Active power from 0x0B04/0x050B local function active_power_meter_handler(driver, device, value, zb_rx) log.info("========================================") log.info("RM3500ZB POWERMETER HANDLER CALLED") - local raw_value = value.value - raw_value = raw_value / 10 - device:emit_event(capabilities.powerMeter.power({value = raw_value, unit = "W"})) + device:emit_event(capabilities.powerMeter.power({value = value.value, unit = "W"})) end local function instantaneous_demand_handler(driver, device, value, zb_rx) log.info("========================================") log.info("RM3500ZB INSTANTMETER HANDLER CALLED") - local raw_value = value.value - raw_value = raw_value / 10 - device:emit_event(capabilities.powerMeter.power({value = raw_value, unit = "W"})) + device:emit_event(capabilities.powerMeter.power({value = value.value, unit = "W"})) end local function rms_voltage_handler(driver, device, value, zb_rx) @@ -82,7 +80,10 @@ end local function rms_current_handler(driver, device, value, zb_rx) log.info("========================================") log.info("RM3500ZB RMS CURRENT HANDLER CALLED") - device:emit_event(capabilities.currentMeasurement.current({value = value.value, unit = "A"})) + local raw_value = value.value + raw_value = raw_value / 1000 + + device:emit_event(capabilities.currentMeasurement.current({value = raw_value, unit = "A"})) end local function metering_handler(driver, device, value, zb_rx) @@ -104,6 +105,143 @@ local function temperature_handler(driver, device, value, zb_rx) end end +-- ============================================================================ +-- SINOPE MANUFACTURER ATTRIBUTE HANDLERS +-- ============================================================================ + +-- Handler for Low Temperature Protection (0xFF01/0x0076) +local function sinope_low_temp_protection_handler(driver, device, value, zb_rx) + log.info("========================================") + log.info("RM3500ZB LOW TEMP PROTECTION HANDLER CALLED") + local temp_value = value.value + log.info(string.format("Low temp protection value from device: %d°C", temp_value)) + + -- Store in field + device:set_field("lowTempProtection", temp_value, {persist = true}) +end + +-- Handler for Tank Size (0xFF01/0x0060) +local function sinope_tank_size_handler(driver, device, value, zb_rx) + log.info("========================================") + log.info("RM3500ZB TANK SIZE HANDLER CALLED") + local tank_size = value.value + log.info(string.format("Tank size from device: %d Gallons", tank_size)) + + -- Store in field + device:set_field("tankSize", tank_size, {persist = true}) +end + +-- Handler for Min Measured Temp (0xFF01/0x007C) - READ ONLY +local function sinope_min_measured_temp_handler(driver, device, value, zb_rx) + log.info("========================================") + log.info("RM3500ZB MIN MEASURED TEMP HANDLER CALLED") + local temp_value = value.value / 100 -- Convert from °C×100 + log.info(string.format("Min measured temp from device: %.2f°C", temp_value)) + + -- Store in field + device:set_field("minMeasuredTemp", temp_value, {persist = true}) + + -- -- Update the preference value (this makes it show in settings) + -- device:try_update_metadata({ + -- preferences = { + -- minMeasuredTemp = temp_value + -- } + -- }) +end + + +local function sinope_max_measured_temp_handler(driver, device, value, zb_rx) + local temp_value = value.value / 100 + log.info(string.format("Max measured temp from device: %.2f°C", temp_value)) + -- Store in field + device:set_field("maxMeasuredTemp", temp_value, {persist = true}) + + -- -- Update the preference value (this makes it show in settings) + -- device:try_update_metadata({ + -- preferences = { + -- maxMeasuredTemp = temp_value + -- } + -- }) +end + + +-- Handler for Max Measured Temp (0xFF01/0x007D) - READ ONLY +local function sinope_max_measured_temp_handler(driver, device, value, zb_rx) + log.info("========================================") + log.info("RM3500ZB MAX MEASURED TEMP HANDLER CALLED") + local temp_value = value.value / 100 -- Convert from °C×100 + log.info(string.format("Max measured temp from device: %.2f°C", temp_value)) + + -- Store in field + device:set_field("maxMeasuredTemp", temp_value, {persist = true}) +end + +-- ============================================================================ +-- REFRESH SETTINGS FUNCTION +-- ============================================================================ + +local function refresh_settings(device) + log.info("========================================") + log.info("RM3500ZB REFRESHING SETTINGS") + log.info("========================================") + + -- Read Low Temperature Protection setting + device:send(cluster_base.read_manufacturer_specific_attribute( + device, + SINOPE_SWITCH_CLUSTER, + SINOPE_DR_MIN_WATER_TEMP_ATTR, + 0x119C + )) + + -- Read Tank Size setting (Connected Load) + device:send(cluster_base.read_manufacturer_specific_attribute( + device, + SINOPE_SWITCH_CLUSTER, + SINOPE_CONNECTED_LOAD_ATTR, + 0x119C + )) + + -- Read Min Measured Temp + device:send(cluster_base.read_manufacturer_specific_attribute( + device, + SINOPE_SWITCH_CLUSTER, + SINOPE_MIN_MEASURED_TEMP_ATTR, + 0x119C + )) + + -- Read Max Measured Temp + device:send(cluster_base.read_manufacturer_specific_attribute( + device, + SINOPE_SWITCH_CLUSTER, + SINOPE_MAX_MEASURED_TEMP_ATTR, + 0x119C + )) +end + +-- ============================================================================ +-- REFRESH ALL VALUES + SETTINGS +-- ============================================================================ + + +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.ActivePower: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)) + + -- Refresh settings values + refresh_settings(device) +end + -- ============================================================================ -- CONFIGURE HANDLER - Set reporting intervals -- ============================================================================ @@ -169,32 +307,106 @@ local function configure_device(driver, device) 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(IASZone.attributes.ZoneStatus:read(device)) - device:send(OnOff.attributes.OnOff:read(device)) + + -- Refresh all values + settings + do_refresh(driver, device) + + end -local function do_refresh(driver, device) + + +local function log_all_unhandled_messages(driver, device, zb_rx) + log.debug("===== INCOMING ZIGBEE MESSAGE =====") + log.debug(zb_rx:pretty_print(zb_utils.MULTI_LINE_FORMAT_CONFIG)) + log.debug("===================================") +end + + +-- ============================================================================ +-- PREFERENCES CHANGE HANDLER +-- ============================================================================ + +local function info_changed_handler(driver, device, event, args) log.info("========================================") - log.info("RM3500ZB DOREFRESH HANDLER CALLED") + log.info("RM3500ZB INFO_CHANGED 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.ActivePower: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)) + -- -- Check if this is a settings page open (no old preferences) + if not args.old_st_store.preferences then + log.info("Settings page opened - refreshing values") + refresh_settings(device) + return + end + + -- Handle Low Temperature Protection change + if args.old_st_store.preferences.lowTempProtection ~= device.preferences.lowTempProtection then + local new_value = tonumber(device.preferences.lowTempProtection) + log.info(string.format("Low temp protection changed to: %d°C", new_value)) + + -- Write to device + device:send(cluster_base.write_manufacturer_specific_attribute( + device, + SINOPE_SWITCH_CLUSTER, + SINOPE_DR_MIN_WATER_TEMP_ATTR, + 0x119C, + data_types.Uint8, + new_value + )) + + -- Read back after 2 seconds to verify + device.thread:call_with_delay(2, function() + log.info("Reading back lowTempProtection after write...") + device:send(cluster_base.read_manufacturer_specific_attribute( + device, + SINOPE_SWITCH_CLUSTER, + SINOPE_DR_MIN_WATER_TEMP_ATTR, + 0x119C + )) + end) + end + + -- Handle Tank Size change + if args.old_st_store.preferences.tankSize ~= device.preferences.tankSize then + local new_value = device.preferences.tankSize + log.info(string.format("Tank size changed to: %d Gallons", new_value)) + + -- Write to device + device:send(cluster_base.write_manufacturer_specific_attribute( + device, + SINOPE_SWITCH_CLUSTER, + SINOPE_CONNECTED_LOAD_ATTR, + 0x119C, + data_types.Uint16, + new_value + )) + + -- Read back after 2 seconds to verify + device.thread:call_with_delay(2, function() + log.info("Reading back tankSize after write...") + device:send(cluster_base.read_manufacturer_specific_attribute( + device, + SINOPE_SWITCH_CLUSTER, + SINOPE_CONNECTED_LOAD_ATTR, + 0x119C + )) + end) + end end + + +-- ============================================================================ +-- THINGS LEFT TO DO +-- Refresh setting Value after setting it +-- Add Min + Max measured values to preferences +-- Add ConnectedLoad to Preferences ? +-- Move +-- ============================================================================ + + + + -- ============================================================================ -- DRIVER DEFINITION -- ============================================================================ @@ -208,8 +420,11 @@ local sinope_rm3500zb = { }, lifecycle_handlers = { init = configure_device, -- Called when device is added/configured + doConfigure = configure_device, + infoChanged = info_changed_handler, }, - zigbee_handlers = { + zigbee_handlers = { + fallback = log_all_unhandled_messages, attr = { [ElectricalMeasurement.ID] = { [ElectricalMeasurement.attributes.ActivePower.ID] = active_power_meter_handler, @@ -226,6 +441,11 @@ local sinope_rm3500zb = { [IASZone.ID] = { [IASZone.attributes.ZoneStatus.ID] = water_sensor_handler }, + [SINOPE_SWITCH_CLUSTER] = { + [SINOPE_DR_MIN_WATER_TEMP_ATTR] = sinope_low_temp_protection_handler, + [SINOPE_MIN_MEASURED_TEMP_ATTR] = sinope_min_measured_temp_handler, + [SINOPE_MAX_MEASURED_TEMP_ATTR] = sinope_max_measured_temp_handler, + }, }, }, can_handle = require("sinope-waterheater.can_handle") From a96db10a476df0fd6c8453433e6d725a83fec932 Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 9 Jan 2026 08:25:00 -0500 Subject: [PATCH 5/6] Final Version --- .../profiles/switch-power-waterheater.yml | 36 +-- .../src/sinope-waterheater/init.lua | 278 ++++++++---------- 2 files changed, 135 insertions(+), 179 deletions(-) diff --git a/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml index 5be7899c86..56acb58b47 100644 --- a/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml +++ b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml @@ -45,25 +45,25 @@ preferences: 55: "55 °C" default: 45 - - title: "Min Measured Temperature" - name: minMeasuredTemp - description: "Lowest temperature recorded (°C) - Read Only" - required: false - preferenceType: number - definition: - minimum: -50 - maximum: 100 - default: 0 + # - title: "Min Measured Temperature" + # name: "minMeasuredTempp" + # description: "Lowest temperature recorded (°C) - Read Only" + # required: false + # preferenceType: number + # definition: + # minimum: -50 + # maximum: 100 + # default: 0 - - title: "Max Measured Temperature" - name: maxMeasuredTemp - description: "Highest temperature recorded (°C) - Read Only" - required: false - preferenceType: number - definition: - minimum: -50 - maximum: 100 - default: 0 + # - title: "Max Measured Temperature" + # name: "maxMeasuredTempp" + # description: "Highest temperature recorded (°C) - Read Only" + # required: false + # preferenceType: number + # definition: + # minimum: -50 + # maximum: 100 + # default: 0 diff --git a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua index 0cc10563f7..850e553c0f 100644 --- a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua @@ -7,7 +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" +-- local log = require "log" local zb_utils = require "st.zigbee.utils" -- Sinopé manufacturer cluster and attributes @@ -32,12 +32,6 @@ local IASZone = clusters.IASZone -- 0x0500 local ElectricalMeasurement = clusters.ElectricalMeasurement -- 0x0B04 local Thermostat = clusters.Thermostat ---Water mon temp config --- Cluster: 0xff01 --- Attribute: 0x0076 --- Data type: t.uint8_t --- Function: drConfigWaterTempMin --- Values: 45 or 0 -- ============================================================================ -- STANDARD ATTRIBUTE HANDLERS @@ -45,8 +39,8 @@ local Thermostat = clusters.Thermostat -- Leak state from IAS Zone 0x0500/0x0002 local function water_sensor_handler(driver, device, value, zb_rx) - log.info("========================================") - log.info("RM3500ZB LEAK HANDLER CALLED") + -- 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 @@ -58,28 +52,28 @@ end -- Active power from 0x0B04/0x050B local function active_power_meter_handler(driver, device, value, zb_rx) - log.info("========================================") - log.info("RM3500ZB POWERMETER HANDLER CALLED") + -- log.info("========================================") + -- log.info("RM3500ZB POWERMETER HANDLER CALLED") device:emit_event(capabilities.powerMeter.power({value = value.value, unit = "W"})) end local function instantaneous_demand_handler(driver, device, value, zb_rx) - log.info("========================================") - log.info("RM3500ZB INSTANTMETER HANDLER CALLED") + -- log.info("========================================") + -- log.info("RM3500ZB INSTANTMETER HANDLER CALLED") device:emit_event(capabilities.powerMeter.power({value = value.value, unit = "W"})) end local function rms_voltage_handler(driver, device, value, zb_rx) - log.info("========================================") - log.info("RM3500ZB RMSVOLTS HANDLER CALLED") + -- log.info("========================================") + -- log.info("RM3500ZB RMSVOLTS HANDLER CALLED") device:emit_event(capabilities.voltageMeasurement.voltage({value = value.value, unit = "V"})) end local function rms_current_handler(driver, device, value, zb_rx) - log.info("========================================") - log.info("RM3500ZB RMS CURRENT HANDLER CALLED") + -- log.info("========================================") + -- log.info("RM3500ZB RMS CURRENT HANDLER CALLED") local raw_value = value.value raw_value = raw_value / 1000 @@ -87,16 +81,16 @@ local function rms_current_handler(driver, device, value, zb_rx) end local function metering_handler(driver, device, value, zb_rx) - log.info("========================================") - log.info("RM3500ZB ENERGYMETER HANDLER CALLED") + -- 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 local function temperature_handler(driver, device, value, zb_rx) - log.info("========================================") - log.info("RM3500ZB TEMPERATURE HANDLER CALLED") - log.info("========================================") + -- log.info("========================================") + -- log.info("RM3500ZB TEMPERATURE HANDLER CALLED") + -- log.info("========================================") local temp_c = value.value /100 -- the RM3500ZB may report 2 types of values with one in the -300 range. This only sends the value if it is over -100 deg C if temp_c > -100 then @@ -111,79 +105,64 @@ end -- Handler for Low Temperature Protection (0xFF01/0x0076) local function sinope_low_temp_protection_handler(driver, device, value, zb_rx) - log.info("========================================") - log.info("RM3500ZB LOW TEMP PROTECTION HANDLER CALLED") + -- log.info("========================================") + -- log.info("RM3500ZB LOW TEMP PROTECTION HANDLER CALLED") local temp_value = value.value - log.info(string.format("Low temp protection value from device: %d°C", temp_value)) + -- log.info(string.format("Low temp protection value from device: %d°C", temp_value)) -- Store in field device:set_field("lowTempProtection", temp_value, {persist = true}) end --- Handler for Tank Size (0xFF01/0x0060) -local function sinope_tank_size_handler(driver, device, value, zb_rx) - log.info("========================================") - log.info("RM3500ZB TANK SIZE HANDLER CALLED") - local tank_size = value.value - log.info(string.format("Tank size from device: %d Gallons", tank_size)) +-- -- Handler for Tank Size (0xFF01/0x0060) +-- local function sinope_tank_size_handler(driver, device, value, zb_rx) +-- log.info("========================================") +-- log.info("RM3500ZB TANK SIZE HANDLER CALLED") +-- local tank_size = value.value +-- log.info(string.format("Tank size from device: %d Gallons", tank_size)) - -- Store in field - device:set_field("tankSize", tank_size, {persist = true}) -end - --- Handler for Min Measured Temp (0xFF01/0x007C) - READ ONLY -local function sinope_min_measured_temp_handler(driver, device, value, zb_rx) - log.info("========================================") - log.info("RM3500ZB MIN MEASURED TEMP HANDLER CALLED") - local temp_value = value.value / 100 -- Convert from °C×100 - log.info(string.format("Min measured temp from device: %.2f°C", temp_value)) +-- -- Store in field +-- device:set_field("tankSize", tank_size, {persist = true}) +-- end + +-- -- Handler for Min Measured Temp (0xFF01/0x007C) - READ ONLY +-- local function sinope_min_measured_temp_handler(driver, device, value, zb_rx) +-- log.info("========================================") +-- log.info("RM3500ZB MIN MEASURED TEMP HANDLER CALLED") +-- local temp_value = value.value / 100 -- Convert from °C×100 +-- log.info(string.format("Min measured temp from device: %.2f°C", temp_value)) - -- Store in field - device:set_field("minMeasuredTemp", temp_value, {persist = true}) - - -- -- Update the preference value (this makes it show in settings) - -- device:try_update_metadata({ - -- preferences = { - -- minMeasuredTemp = temp_value - -- } - -- }) -end - - -local function sinope_max_measured_temp_handler(driver, device, value, zb_rx) - local temp_value = value.value / 100 - log.info(string.format("Max measured temp from device: %.2f°C", temp_value)) - -- Store in field - device:set_field("maxMeasuredTemp", temp_value, {persist = true}) - - -- -- Update the preference value (this makes it show in settings) - -- device:try_update_metadata({ - -- preferences = { - -- maxMeasuredTemp = temp_value - -- } - -- }) -end - - --- Handler for Max Measured Temp (0xFF01/0x007D) - READ ONLY -local function sinope_max_measured_temp_handler(driver, device, value, zb_rx) - log.info("========================================") - log.info("RM3500ZB MAX MEASURED TEMP HANDLER CALLED") - local temp_value = value.value / 100 -- Convert from °C×100 - log.info(string.format("Max measured temp from device: %.2f°C", temp_value)) +-- -- Store in field +-- device:set_field("minMeasuredTemp", temp_value, {persist = true}) + +-- -- -- Update the preference value (this makes it show in settings) +-- -- device:try_update_metadata({ +-- -- preferences = { +-- -- minMeasuredTemp = temp_value +-- -- } +-- -- }) +-- end + +-- -- Handler for Max Measured Temp (0xFF01/0x007D) - READ ONLY +-- local function sinope_max_measured_temp_handler(driver, device, value, zb_rx) +-- log.info("========================================") +-- log.info("RM3500ZB MAX MEASURED TEMP HANDLER CALLED") +-- local temp_value = value.value / 100 -- Convert from °C×100 +-- log.info(string.format("Max measured temp from device updated: %.2f°C", temp_value)) - -- Store in field - device:set_field("maxMeasuredTemp", temp_value, {persist = true}) -end +-- -- Store in field +-- device:set_field("maxMeasuredTemp", temp_value, {persist = true}) +-- local templog = device:get_field("maxMeasuredTemp") +-- log.info(string.format("Max measured temp from device read: %.2f°C", templog))end -- ============================================================================ -- REFRESH SETTINGS FUNCTION -- ============================================================================ local function refresh_settings(device) - log.info("========================================") - log.info("RM3500ZB REFRESHING SETTINGS") - log.info("========================================") + -- log.info("========================================") + -- log.info("RM3500ZB REFRESHING SETTINGS") + -- log.info("========================================") -- Read Low Temperature Protection setting device:send(cluster_base.read_manufacturer_specific_attribute( @@ -193,29 +172,29 @@ local function refresh_settings(device) 0x119C )) - -- Read Tank Size setting (Connected Load) - device:send(cluster_base.read_manufacturer_specific_attribute( - device, - SINOPE_SWITCH_CLUSTER, - SINOPE_CONNECTED_LOAD_ATTR, - 0x119C - )) + -- -- Read Tank Size setting (Connected Load) + -- device:send(cluster_base.read_manufacturer_specific_attribute( + -- device, + -- SINOPE_SWITCH_CLUSTER, + -- SINOPE_CONNECTED_LOAD_ATTR, + -- 0x119C + -- )) - -- Read Min Measured Temp - device:send(cluster_base.read_manufacturer_specific_attribute( - device, - SINOPE_SWITCH_CLUSTER, - SINOPE_MIN_MEASURED_TEMP_ATTR, - 0x119C - )) + -- -- Read Min Measured Temp + -- device:send(cluster_base.read_manufacturer_specific_attribute( + -- device, + -- SINOPE_SWITCH_CLUSTER, + -- SINOPE_MIN_MEASURED_TEMP_ATTR, + -- 0x119C + -- )) - -- Read Max Measured Temp - device:send(cluster_base.read_manufacturer_specific_attribute( - device, - SINOPE_SWITCH_CLUSTER, - SINOPE_MAX_MEASURED_TEMP_ATTR, - 0x119C - )) + -- -- Read Max Measured Temp + -- device:send(cluster_base.read_manufacturer_specific_attribute( + -- device, + -- SINOPE_SWITCH_CLUSTER, + -- SINOPE_MAX_MEASURED_TEMP_ATTR, + -- 0x119C + -- )) end -- ============================================================================ @@ -224,9 +203,9 @@ end local function do_refresh(driver, device) - log.info("========================================") - log.info("RM3500ZB DOREFRESH HANDLER CALLED") - log.info("========================================") + -- log.info("========================================") + -- log.info("RM3500ZB DOREFRESH HANDLER CALLED") + -- log.info("========================================") -- Refresh all values device:send(TemperatureMeasurement.attributes.MeasuredValue:read(device)) @@ -247,9 +226,9 @@ end -- ============================================================================ local function configure_device(driver, device) - log.info("========================================") - log.info("RM3500ZB CONFIGURE DEVICE HANDLER CALLED") - log.info("========================================") + -- log.info("========================================") + -- log.info("RM3500ZB CONFIGURE DEVICE HANDLER CALLED") + -- log.info("========================================") -- Configure Temperature reporting (every 30s to 5min, on 0.5°C change) device:send(TemperatureMeasurement.attributes.MeasuredValue:configure_reporting( @@ -314,27 +293,18 @@ local function configure_device(driver, device) end - - -local function log_all_unhandled_messages(driver, device, zb_rx) - log.debug("===== INCOMING ZIGBEE MESSAGE =====") - log.debug(zb_rx:pretty_print(zb_utils.MULTI_LINE_FORMAT_CONFIG)) - log.debug("===================================") -end - - -- ============================================================================ -- PREFERENCES CHANGE HANDLER -- ============================================================================ local function info_changed_handler(driver, device, event, args) - log.info("========================================") - log.info("RM3500ZB INFO_CHANGED HANDLER CALLED") - log.info("========================================") + -- log.info("========================================") + -- log.info("RM3500ZB INFO_CHANGED HANDLER CALLED") + -- log.info("========================================") -- -- Check if this is a settings page open (no old preferences) if not args.old_st_store.preferences then - log.info("Settings page opened - refreshing values") + -- log.info("Settings page opened - refreshing values") refresh_settings(device) return end @@ -342,7 +312,7 @@ local function info_changed_handler(driver, device, event, args) -- Handle Low Temperature Protection change if args.old_st_store.preferences.lowTempProtection ~= device.preferences.lowTempProtection then local new_value = tonumber(device.preferences.lowTempProtection) - log.info(string.format("Low temp protection changed to: %d°C", new_value)) + -- log.info(string.format("Low temp protection changed to: %d°C", new_value)) -- Write to device device:send(cluster_base.write_manufacturer_specific_attribute( @@ -366,47 +336,34 @@ local function info_changed_handler(driver, device, event, args) end) end - -- Handle Tank Size change - if args.old_st_store.preferences.tankSize ~= device.preferences.tankSize then - local new_value = device.preferences.tankSize - log.info(string.format("Tank size changed to: %d Gallons", new_value)) + -- -- Handle Tank Size change + -- if args.old_st_store.preferences.tankSize ~= device.preferences.tankSize then + -- local new_value = device.preferences.tankSize + -- log.info(string.format("Tank size changed to: %d Gallons", new_value)) - -- Write to device - device:send(cluster_base.write_manufacturer_specific_attribute( - device, - SINOPE_SWITCH_CLUSTER, - SINOPE_CONNECTED_LOAD_ATTR, - 0x119C, - data_types.Uint16, - new_value - )) + -- -- Write to device + -- device:send(cluster_base.write_manufacturer_specific_attribute( + -- device, + -- SINOPE_SWITCH_CLUSTER, + -- SINOPE_CONNECTED_LOAD_ATTR, + -- 0x119C, + -- data_types.Uint16, + -- new_value + -- )) - -- Read back after 2 seconds to verify - device.thread:call_with_delay(2, function() - log.info("Reading back tankSize after write...") - device:send(cluster_base.read_manufacturer_specific_attribute( - device, - SINOPE_SWITCH_CLUSTER, - SINOPE_CONNECTED_LOAD_ATTR, - 0x119C - )) - end) - end + -- -- Read back after 2 seconds to verify + -- device.thread:call_with_delay(2, function() + -- log.info("Reading back tankSize after write...") + -- device:send(cluster_base.read_manufacturer_specific_attribute( + -- device, + -- SINOPE_SWITCH_CLUSTER, + -- SINOPE_CONNECTED_LOAD_ATTR, + -- 0x119C + -- )) + -- end) + -- end end - - --- ============================================================================ --- THINGS LEFT TO DO --- Refresh setting Value after setting it --- Add Min + Max measured values to preferences --- Add ConnectedLoad to Preferences ? --- Move --- ============================================================================ - - - - -- ============================================================================ -- DRIVER DEFINITION -- ============================================================================ @@ -424,7 +381,6 @@ local sinope_rm3500zb = { infoChanged = info_changed_handler, }, zigbee_handlers = { - fallback = log_all_unhandled_messages, attr = { [ElectricalMeasurement.ID] = { [ElectricalMeasurement.attributes.ActivePower.ID] = active_power_meter_handler, @@ -443,8 +399,8 @@ local sinope_rm3500zb = { }, [SINOPE_SWITCH_CLUSTER] = { [SINOPE_DR_MIN_WATER_TEMP_ATTR] = sinope_low_temp_protection_handler, - [SINOPE_MIN_MEASURED_TEMP_ATTR] = sinope_min_measured_temp_handler, - [SINOPE_MAX_MEASURED_TEMP_ATTR] = sinope_max_measured_temp_handler, + -- [SINOPE_MIN_MEASURED_TEMP_ATTR] = sinope_min_measured_temp_handler, + -- [SINOPE_MAX_MEASURED_TEMP_ATTR] = sinope_max_measured_temp_handler, }, }, }, From ec06eb7c779eefaa1211fbc1045ca480553f0b7d Mon Sep 17 00:00:00 2001 From: xmorand <60904575+xmorand@users.noreply.github.com> Date: Fri, 9 Jan 2026 22:30:06 -0500 Subject: [PATCH 6/6] Cleanup --- .../src/sinope-waterheater/init.lua | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua index 850e553c0f..bb7676a050 100644 --- a/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua @@ -1,28 +1,28 @@ -- 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 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 ZigbeeDriver = require "st.zigbee" +-- local defaults = require "st.zigbee.defaults" local clusters = require "st.zigbee.zcl.clusters" -- local log = require "log" local zb_utils = require "st.zigbee.utils" -- Sinopé manufacturer cluster and attributes -local SINOPE_SWITCH_CLUSTER = 0xFF01 -local SINOPE_MAX_INTENSITY_ON_ATTRIBUTE = 0x0052 -local SINOPE_MAX_INTENSITY_OFF_ATTRIBUTE = 0x0053 -local SINOPE_CONNECTED_LOAD_ATTR = 0x0060 -- ConnectedLoad (W) -local SINOPE_CURRENT_LOAD_ATTR = 0x0070 -- CurrentLoad (W-ish bitmap) -local SINOPE_DR_MIN_WATER_TEMP_ATTR = 0x0076 -- drConfigWaterTempMin (°C) -local SINOPE_DR_MIN_WATER_TEMP_TIME_ATTR = 0x0077 -- drConfigWaterTempTime -local SINOPE_TIMER_ATTR = 0x00A0 -- Timer seconds -local SINOPE_TIMER_COUNTDOWN_ATTR = 0x00A1 -- Timer_countDown -local SINOPE_MIN_MEASURED_TEMP_ATTR = 0x007C -- min_measured_temp (°C×100) -local SINOPE_MAX_MEASURED_TEMP_ATTR = 0x007D -- max_measured_temp (°C×100) -local SINOPE_ENERGY_INTERNAL_ATTR = 0x0090 -- currentSummationDelivered (internal) +-- local SINOPE_SWITCH_CLUSTER = 0xFF01 +-- local SINOPE_MAX_INTENSITY_ON_ATTRIBUTE = 0x0052 +-- local SINOPE_MAX_INTENSITY_OFF_ATTRIBUTE = 0x0053 +-- local SINOPE_CONNECTED_LOAD_ATTR = 0x0060 -- ConnectedLoad (W) +-- local SINOPE_CURRENT_LOAD_ATTR = 0x0070 -- CurrentLoad (W-ish bitmap) +-- local SINOPE_DR_MIN_WATER_TEMP_ATTR = 0x0076 -- drConfigWaterTempMin (°C) +-- local SINOPE_DR_MIN_WATER_TEMP_TIME_ATTR = 0x0077 -- drConfigWaterTempTime +-- local SINOPE_TIMER_ATTR = 0x00A0 -- Timer seconds +-- local SINOPE_TIMER_COUNTDOWN_ATTR = 0x00A1 -- Timer_countDown +-- local SINOPE_MIN_MEASURED_TEMP_ATTR = 0x007C -- min_measured_temp (°C×100) +-- local SINOPE_MAX_MEASURED_TEMP_ATTR = 0x007D -- max_measured_temp (°C×100) +-- local SINOPE_ENERGY_INTERNAL_ATTR = 0x0090 -- currentSummationDelivered (internal) -- Standard Zigbee clusters local SimpleMetering = clusters.SimpleMetering -- 0x0702 @@ -30,8 +30,8 @@ local OnOff = clusters.OnOff -- 0x0006 local TemperatureMeasurement = clusters.TemperatureMeasurement -- 0x0402 local IASZone = clusters.IASZone -- 0x0500 local ElectricalMeasurement = clusters.ElectricalMeasurement -- 0x0B04 -local Thermostat = clusters.Thermostat - +-- local Thermostat = clusters.Thermostat + -- ============================================================================ -- STANDARD ATTRIBUTE HANDLERS