Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
aae45d2
Adding Power consumption measurment to stelpro device
xmorand Aug 5, 2023
e590f43
Update init.lua
xmorand Aug 5, 2023
7db7864
Delete stelpro_maestrostat.lua
xmorand Aug 5, 2023
c377860
Delete stelpro_sorb.lua
xmorand Aug 5, 2023
5676927
Update thermostat-stelpro-profile.yml
xmorand Aug 5, 2023
20b1ddc
Adding support for SMT402AD
xmorand Aug 5, 2023
1a90c02
Update init.lua
xmorand Aug 5, 2023
1e176c4
Update fingerprints.yml
xmorand Aug 6, 2023
9da09d4
Update init.lua
xmorand Oct 7, 2023
f3111eb
Merge pull request #2 from xmorand/xmorand-stepropower-2
xmorand Oct 7, 2023
a03d971
Update fingerprints.yml
xmorand Oct 7, 2023
e3f207a
Update init.lua
xmorand Oct 7, 2023
a179607
Merge branch 'main' into xmorand-stelpro2
xmorand Oct 7, 2023
06a6735
Delete drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_maes…
xmorand Oct 7, 2023
623d89b
Delete drivers/SmartThings/zigbee-thermostat/src/stelpro/stelpro_sorb…
xmorand Oct 7, 2023
e19e882
Merge pull request #4 from xmorand/xmorand-stelpro2
xmorand Oct 7, 2023
44ef50e
Merge pull request #5 from xmorand/xmorand-stelpro2
xmorand Oct 7, 2023
def353d
Update fingerprints.yml
xmorand Oct 7, 2023
c1cfa85
Update motion-illuminance-battery-aqara.yml
xmorand Oct 7, 2023
435dbc6
Update motion-illuminance-battery-aqara.yml
xmorand Oct 7, 2023
df228fa
Merge pull request #6 from xmorand/Aqara-P1
xmorand Oct 7, 2023
c12d2cc
Update fingerprints.yml
xmorand Oct 7, 2023
4e1df06
Merge pull request #7 from xmorand/xmorand-patch-1
xmorand Oct 7, 2023
2f93ca1
commit
xmorand Oct 7, 2023
5471edf
commit
xmorand Oct 7, 2023
2058ea2
Merge pull request #8 from xmorand/patch2
xmorand Oct 7, 2023
3d0d0cd
removed bad headers
xmorand Oct 7, 2023
1da2837
Merge pull request #9 from xmorand/Correct-bad-comments
xmorand Oct 7, 2023
882e684
aqara comit
xmorand Oct 7, 2023
cf14817
Merge pull request #10 from xmorand/Aqara-P1--1
xmorand Oct 7, 2023
9cd7026
capabilities
xmorand Oct 7, 2023
1dad3ca
Merge pull request #11 from xmorand/aqara-capabilites
xmorand Oct 7, 2023
5df3399
commit aqara P1
xmorand Oct 7, 2023
fc23d6a
Merge pull request #12 from xmorand/aqara-P1-2
xmorand Oct 7, 2023
5e63a78
Merge branch 'SmartThingsCommunity:main' into main
xmorand Dec 17, 2023
94eb7ea
Merge branch 'SmartThingsCommunity:main' into main
xmorand Dec 6, 2025
5780f0a
Add profile for sinope-switch-rm3500zb
xmorand Dec 6, 2025
50e117f
Update deviceProfileName for Sinope Load Controller
xmorand Dec 6, 2025
7a0d407
Rename sinope-switch-rm3500zb to sinope-switch-rm3500zb.yml
xmorand Dec 6, 2025
fc124f2
Add temperature measurement handler to init.lua
xmorand Dec 6, 2025
c2d00c8
Add handlers for RMS voltage, current, and metering
xmorand Dec 6, 2025
a27425c
Rename profile to switch-power-waterheater and add capabilities
xmorand Dec 7, 2025
c36116f
Update deviceProfileName for RM3500ZB device
xmorand Dec 7, 2025
60f4e02
Create Sinope-waterheater
xmorand Dec 7, 2025
2718121
Delete drivers/SmartThings/zigbee-switch/src/Sinope-waterheater
xmorand Dec 7, 2025
dc5f984
Create init.lua
xmorand Dec 7, 2025
b0aa01e
Update device model check for Sinope water heater
xmorand Dec 7, 2025
e4e73d4
Update device capabilities in water heater profile
xmorand Dec 7, 2025
31665dc
Delete drivers/SmartThings/zigbee-switch/profiles/sinope-switch-rm350…
xmorand Dec 7, 2025
5cee9ce
Add water and voltage sensor capabilities
xmorand Dec 7, 2025
c8fc2be
Update init.lua
xmorand Dec 7, 2025
3b375f5
Jan2
xmorand Jan 3, 2026
77ab1fa
Merge pull request #14 from xmorand/TestRM
xmorand Jan 3, 2026
d62e125
Fixed Sub-driver structure
xmorand Jan 3, 2026
eaf4d78
Refactor active power meter handler function removed comment for leak…
xmorand Jan 3, 2026
63e260c
Merge branch 'main' into RM3500ZB
xmorand Jan 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion drivers/SmartThings/zigbee-motion-sensor/config.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: 'Zigbee Motion Sensor'
name: 'Zigbee Motion Sensor vX'
packageKey: 'zigbee-motion-sensor'
permissions:
zigbee: {}
Expand Down
5 changes: 5 additions & 0 deletions drivers/SmartThings/zigbee-motion-sensor/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 6 additions & 0 deletions drivers/SmartThings/zigbee-motion-sensor/src/aqara/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
{
Expand Down
2 changes: 1 addition & 1 deletion drivers/SmartThings/zigbee-switch/config.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: 'Zigbee Switch'
name: 'Zigbee Switch Vx'
packageKey: 'zigbee-switch'
permissions:
zigbee: {}
Expand Down
4 changes: 2 additions & 2 deletions drivers/SmartThings/zigbee-switch/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -2495,4 +2495,4 @@ zigbeeGeneric:
- 0x0006 #OnOff
- 0x0702 #Simple Metering
- 0x0B04 #Electrical Measurment
deviceProfileName: switch-power
deviceProfileName: switch-power
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions drivers/SmartThings/zigbee-switch/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand All @@ -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"),
Expand All @@ -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 = {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
224 changes: 224 additions & 0 deletions drivers/SmartThings/zigbee-switch/src/sinope-waterheater/init.lua
Original file line number Diff line number Diff line change
@@ -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
Loading
Loading