From 4e3df75d1fde3f98ff66048ac6856fb8e5e437d6 Mon Sep 17 00:00:00 2001 From: Nick DeBoom Date: Fri, 22 Mar 2024 15:04:00 -0500 Subject: [PATCH] Matter-Thermostat: Use endpoint id in limit fields Add endpoint id to temp limit fields. Rework test cases. --- .../matter-thermostat/src/init.lua | 20 ++- .../test_matter_thermo_setpoint_limits.lua | 117 ++++++++++++------ 2 files changed, 93 insertions(+), 44 deletions(-) diff --git a/drivers/SmartThings/matter-thermostat/src/init.lua b/drivers/SmartThings/matter-thermostat/src/init.lua index d57ba13245..e380572077 100644 --- a/drivers/SmartThings/matter-thermostat/src/init.lua +++ b/drivers/SmartThings/matter-thermostat/src/init.lua @@ -76,6 +76,14 @@ local subscribed_attributes = { } } +local function get_field_for_endpoint(device, field, endpoint) + return device:get_field(string.format("%s_%d", field, endpoint)) +end + +local function set_field_for_endpoint(device, field, endpoint, value, persist) + device:set_field(string.format("%s_%d", field, endpoint), value, {persist = persist}) +end + local function find_default_endpoint(device, cluster) local res = device.MATTER_DEFAULT_ENDPOINT local eps = device:get_endpoints(cluster) @@ -209,14 +217,14 @@ local temp_attr_handler_factory = function(minOrMax) if ib.data.value ~= nil then local temp = ib.data.value / 100.0 local unit = "C" - device:set_field(minOrMax, temp) - local min = device:get_field(setpoint_limit_device_field.MIN_TEMP) - local max = device:get_field(setpoint_limit_device_field.MAX_TEMP) + set_field_for_endpoint(device, minOrMax, ib.endpoint_id, temp, false) + local min = get_field_for_endpoint(device, setpoint_limit_device_field.MIN_TEMP, ib.endpoint_id) + local max = get_field_for_endpoint(device, setpoint_limit_device_field.MAX_TEMP, ib.endpoint_id) if min ~= nil and max ~= nil then if min < max then device:emit_event_for_endpoint(ib.endpoint_id, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = unit })) - device:set_field(setpoint_limit_device_field.MIN_TEMP, nil) - device:set_field(setpoint_limit_device_field.MAX_TEMP, nil) + set_field_for_endpoint(device, setpoint_limit_device_field.MIN_TEMP, ib.endpoint_id, nil, false) + set_field_for_endpoint(device, setpoint_limit_device_field.MAX_TEMP, ib.endpoint_id, nil, false) else device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) end @@ -414,6 +422,7 @@ local heating_setpoint_limit_handler_factory = function(minOrMax) return function(driver, device, ib, response) if ib.data.value ~= nil then local val = ib.data.value / 100.0 + print("setting %s to %d", minOrMax, val) device:set_field(minOrMax, val) local min = device:get_field(setpoint_limit_device_field.MIN_HEAT) local max = device:get_field(setpoint_limit_device_field.MAX_HEAT) @@ -432,6 +441,7 @@ local cooling_setpoint_limit_handler_factory = function(minOrMax) return function(driver, device, ib, response) if ib.data.value ~= nil then local val = ib.data.value / 100.0 + print("setting %s to %d", minOrMax, val) device:set_field(minOrMax, val) local min = device:get_field(setpoint_limit_device_field.MIN_COOL) local max = device:get_field(setpoint_limit_device_field.MAX_COOL) diff --git a/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermo_setpoint_limits.lua b/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermo_setpoint_limits.lua index dac997191b..3c6deaebc1 100644 --- a/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermo_setpoint_limits.lua +++ b/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermo_setpoint_limits.lua @@ -79,45 +79,6 @@ local function test_init() read_limits:merge(clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:read()) test.socket.matter:__expect_send({mock_device.id, read_limits}) - --Populate setpoint limits - test.socket.matter:__queue_receive({ - mock_device.id, - clusters.Thermostat.attributes.AbsMinHeatSetpointLimit:build_test_report_data(mock_device, 1, 1000) - }) - test.socket.matter:__queue_receive({ - mock_device.id, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit:build_test_report_data(mock_device, 1, 3222) - }) - test.socket.matter:__queue_receive({ - mock_device.id, - clusters.Thermostat.attributes.AbsMinCoolSetpointLimit:build_test_report_data(mock_device, 1, 1000) --10.0 celcius - }) - test.socket.matter:__queue_receive({ - mock_device.id, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit:build_test_report_data(mock_device, 1, 3222) --32.22 celcius - }) - test.socket.matter:__queue_receive({ - mock_device.id, - clusters.Thermostat.attributes.MinSetpointDeadBand:build_test_report_data(mock_device, 1, 16) --1.6 celcius - }) - test.socket.matter:__queue_receive({ - mock_device.id, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue:build_test_report_data(mock_device, 1, 500) --5.0 celsius - }) - test.socket.matter:__queue_receive({ - mock_device.id, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_report_data(mock_device, 1, 4000) --40.0 celsius - }) - - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.thermostatHeatingSetpoint.heatingSetpointRange({ value = { minimum = 10.00, maximum = 32.22 }, unit = "C" })) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.thermostatCoolingSetpoint.coolingSetpointRange({ value = { minimum = 10.00, maximum = 32.22 }, unit = "C" })) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 5.00, maximum = 40.00 }, unit = "C" })) - ) test.mock_device.add_test_device(mock_device) end test.set_test_init_function(test_init) @@ -152,6 +113,10 @@ end test.register_coroutine_test( "Heat setpoint lower than min", function() + test.socket.matter:__queue_receive({ + mock_device.id, + clusters.Thermostat.attributes.AbsMinHeatSetpointLimit:build_test_report_data(mock_device, 1, 1000) + }) configure(mock_device) test.socket.capability:__queue_receive({ mock_device.id, @@ -166,6 +131,10 @@ test.register_coroutine_test( test.register_coroutine_test( "Cool setpoint lower than min", function() + test.socket.matter:__queue_receive({ + mock_device.id, + clusters.Thermostat.attributes.AbsMinCoolSetpointLimit:build_test_report_data(mock_device, 1, 1000) + }) configure(mock_device) test.socket.capability:__queue_receive({ mock_device.id, @@ -180,6 +149,10 @@ test.register_coroutine_test( test.register_coroutine_test( "Heat setpoint higher than max", function() + test.socket.matter:__queue_receive({ + mock_device.id, + clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit:build_test_report_data(mock_device, 1, 3222) + }) configure(mock_device) test.socket.capability:__queue_receive({ mock_device.id, @@ -194,6 +167,10 @@ test.register_coroutine_test( test.register_coroutine_test( "Cool setpoint higher than max", function() + test.socket.matter:__queue_receive({ + mock_device.id, + clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit:build_test_report_data(mock_device, 1, 3222) + }) configure(mock_device) test.socket.capability:__queue_receive({ mock_device.id, @@ -208,6 +185,10 @@ test.register_coroutine_test( test.register_coroutine_test( "Heat setpoint inside deadband", function() + test.socket.matter:__queue_receive({ + mock_device.id, + clusters.Thermostat.attributes.MinSetpointDeadBand:build_test_report_data(mock_device, 1, 16) --1.6 celcius + }) configure(mock_device) test.socket.capability:__queue_receive({ mock_device.id, @@ -222,6 +203,10 @@ test.register_coroutine_test( test.register_coroutine_test( "Cool setpoint inside deadband", function() + test.socket.matter:__queue_receive({ + mock_device.id, + clusters.Thermostat.attributes.MinSetpointDeadBand:build_test_report_data(mock_device, 1, 16) --1.6 celcius + }) configure(mock_device) test.socket.capability:__queue_receive({ mock_device.id, @@ -233,6 +218,60 @@ test.register_coroutine_test( end ) +test.register_message_test( + "Min and max heating setpoint attributes set capability constraint", + { + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + clusters.Thermostat.attributes.AbsMinCoolSetpointLimit:build_test_report_data(mock_device, 1, 1000) + } + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit:build_test_report_data(mock_device, 1, 3222) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.thermostatCoolingSetpoint.coolingSetpointRange({ value = { minimum = 10.00, maximum = 32.22 }, unit = "C" })) + } + } +) + +test.register_message_test( + "Min and max cooling setpoint attributes set capability constraint", + { + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + clusters.Thermostat.attributes.AbsMinHeatSetpointLimit:build_test_report_data(mock_device, 1, 1000) + } + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit:build_test_report_data(mock_device, 1, 3222) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.thermostatHeatingSetpoint.heatingSetpointRange({ value = { minimum = 10.00, maximum = 32.22 }, unit = "C" })) + } + } +) + test.register_message_test( "Min and max temperature attributes set capability constraint", {