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: {} diff --git a/drivers/SmartThings/zigbee-motion-sensor/fingerprints.yml b/drivers/SmartThings/zigbee-motion-sensor/fingerprints.yml index 28aaea8d33..557c296994 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/fingerprints.yml +++ b/drivers/SmartThings/zigbee-motion-sensor/fingerprints.yml @@ -9,6 +9,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 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..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 @@ -6,13 +6,19 @@ 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 - id: refresh version: 1 + - id: voltageMeasurement + version: 1 + - id: signalStrength + version: 1 categories: - name: MotionSensor diff --git a/drivers/SmartThings/zigbee-motion-sensor/src/aqara/init.lua b/drivers/SmartThings/zigbee-motion-sensor/src/aqara/init.lua index e4586d4b0f..a3ac5d96e2 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/src/aqara/init.lua +++ b/drivers/SmartThings/zigbee-motion-sensor/src/aqara/init.lua @@ -19,6 +19,12 @@ local FREQUENCY_ATTRIBUTE_ID = 0x0102 local MOTION_DETECTED_UINT32 = 65536 +local FINGERPRINTS = { + { mfr = "LUMI", model = "lumi.motion.ac02" }, + { mfr = "LUMI", model = "lumi.motion.agl02" }, + { mfr = "LUMI", model = "lumi.motion.agl04" }, + { mfr = "LUMI", model = "lumi.motion.ac02" } +} local CONFIGURATIONS = { { 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/fingerprints.yml b/drivers/SmartThings/zigbee-switch/fingerprints.yml index 3d598372fa..5c0ef589ad 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: switch-power-waterheater - id: "Sinope Dimmer Switch/DM2500ZB" deviceLabel: "DM2500ZB Sinope Dimmer" manufacturer: Sinope Technologies @@ -2495,4 +2495,4 @@ zigbeeGeneric: - 0x0006 #OnOff - 0x0702 #Simple Metering - 0x0B04 #Electrical Measurment - deviceProfileName: switch-power \ No newline at end of file + deviceProfileName: switch-power 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..327a3dca2b --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/profiles/switch-power-waterheater.yml @@ -0,0 +1,26 @@ +name: switch-power-waterheater +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: waterSensor + version: 1 + - id: thermostatCoolingSetpoint + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: SmartPlug \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-switch/src/init.lua b/drivers/SmartThings/zigbee-switch/src/init.lua index 1b694d2a5e..cc2c6a45ec 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"), + 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"), @@ -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 = { 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..4a1b216130 --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/can_handle.lua @@ -0,0 +1,16 @@ +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 + +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 new file mode 100644 index 0000000000..aa50dff907 --- /dev/null +++ b/drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua @@ -0,0 +1,224 @@ +-- 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 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 +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] + +-- 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 + +-- 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.waterSensor.water.wet()) + else + device:emit_event(capabilities.waterSensor.water.dry()) + 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 + + 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 + + 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 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 + +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 + +-- ============================================================================ +-- CONFIGURE HANDLER - Set reporting intervals +-- ============================================================================ + +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(IASZone.attributes.ZoneStatus:read(device)) + device:send(OnOff.attributes.OnOff:read(device)) +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 +-- ============================================================================ + +local sinope_rm3500zb = { + NAME = "Sinopé RM3500ZB Water Heater", + capability_handlers = { + [capabilities.refresh.ID] = { + [capabilities.refresh.commands.refresh.NAME] = do_refresh, + } + }, + lifecycle_handlers = { + doConfigure = do_configure, -- Called when device is added/configured + }, + zigbee_handlers = { + 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 + }, + [SimpleMetering.ID] = { + [SimpleMetering.attributes.InstantaneousDemand.ID] = instantaneous_demand_handler, + [SimpleMetering.attributes.CurrentSummationDelivered.ID] = metering_handler + }, + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MeasuredValue.ID] = temperature_handler + }, + }, + }, + can_handle = require("sinope-waterheater.can_handle") +} + + +return sinope_rm3500zb 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..eb2138b84c 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 @@ -26,15 +27,42 @@ 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) + 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 + 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 + [SimpleMetering.attributes.InstantaneousDemand.ID] = instantaneous_demand_handler, + [SimpleMetering.attributes.CurrentSummationDelivered.ID] = metering_handler + + }, + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MeasuredValue.ID] = temperature_handler } } }, 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: diff --git a/drivers/SmartThings/zigbee-thermostat/fingerprints.yml b/drivers/SmartThings/zigbee-thermostat/fingerprints.yml index d88b3ff89a..d1a8fd031b 100644 --- a/drivers/SmartThings/zigbee-thermostat/fingerprints.yml +++ b/drivers/SmartThings/zigbee-thermostat/fingerprints.yml @@ -79,6 +79,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 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: diff --git a/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua b/drivers/SmartThings/zigbee-thermostat/src/stelpro/init.lua index 063f423517..a6c46fb6a9 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,11 +145,16 @@ 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))) @@ -121,15 +173,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 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 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