From 85913473f219dec81fddcda8a8a9bb22bb8dfc14 Mon Sep 17 00:00:00 2001 From: HunsupJung <59987061+HunsupJung@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:12:23 +0900 Subject: [PATCH 1/2] Set state_change to true when receive lockAlarm event (#1519) Signed-off-by: Hunsup Jung --- .../matter-lock/src/aqara-lock/init.lua | 12 ++++---- .../src/test/test_aqara_matter_lock.lua | 30 +++++++++++++++---- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/drivers/SmartThings/matter-lock/src/aqara-lock/init.lua b/drivers/SmartThings/matter-lock/src/aqara-lock/init.lua index 4b0fe8762e..fc83bc9483 100644 --- a/drivers/SmartThings/matter-lock/src/aqara-lock/init.lua +++ b/drivers/SmartThings/matter-lock/src/aqara-lock/init.lua @@ -52,7 +52,7 @@ local function device_init(driver, device) end local function device_added(driver, device) - device:emit_event(capabilities.lockAlarm.alarm.clear()) + device:emit_event(capabilities.lockAlarm.alarm.clear({state_change = true})) end local function lock_state_handler(driver, device, ib, response) @@ -75,15 +75,15 @@ local function alarm_event_handler(driver, device, ib, response) local DlAlarmCode = DoorLock.types.DlAlarmCode local alarm_code = ib.data.elements.alarm_code if alarm_code.value == DlAlarmCode.LOCK_JAMMED then - device:emit_event(capabilities.lockAlarm.alarm.unableToLockTheDoor()) + device:emit_event(capabilities.lockAlarm.alarm.unableToLockTheDoor({state_change = true})) elseif alarm_code.value == DlAlarmCode.LOCK_FACTORY_RESET then - device:emit_event(capabilities.lockAlarm.alarm.lockFactoryReset()) + device:emit_event(capabilities.lockAlarm.alarm.lockFactoryReset({state_change = true})) elseif alarm_code.value == DlAlarmCode.WRONG_CODE_ENTRY_LIMIT then - device:emit_event(capabilities.lockAlarm.alarm.attemptsExceeded()) + device:emit_event(capabilities.lockAlarm.alarm.attemptsExceeded({state_change = true})) elseif alarm_code.value == DlAlarmCode.FRONT_ESCEUTCHEON_REMOVED then - device:emit_event(capabilities.lockAlarm.alarm.damaged()) + device:emit_event(capabilities.lockAlarm.alarm.damaged({state_change = true})) elseif alarm_code.value == DlAlarmCode.DOOR_FORCED_OPEN then - device:emit_event(capabilities.lockAlarm.alarm.forcedOpeningAttempt()) + device:emit_event(capabilities.lockAlarm.alarm.forcedOpeningAttempt({state_change = true})) end end diff --git a/drivers/SmartThings/matter-lock/src/test/test_aqara_matter_lock.lua b/drivers/SmartThings/matter-lock/src/test/test_aqara_matter_lock.lua index a1dae329e4..a9ec6dd950 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_aqara_matter_lock.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_aqara_matter_lock.lua @@ -158,7 +158,10 @@ test.register_message_test( { channel = "capability", direction = "send", - message = mock_device:generate_test_message("main", capabilities.lockAlarm.alarm.unableToLockTheDoor()), + message = mock_device:generate_test_message( + "main", + capabilities.lockAlarm.alarm.unableToLockTheDoor({state_change = true}) + ), }, { channel = "matter", @@ -173,7 +176,10 @@ test.register_message_test( { channel = "capability", direction = "send", - message = mock_device:generate_test_message("main", capabilities.lockAlarm.alarm.lockFactoryReset()), + message = mock_device:generate_test_message( + "main", + capabilities.lockAlarm.alarm.lockFactoryReset({state_change = true}) + ), }, { channel = "matter", @@ -188,7 +194,10 @@ test.register_message_test( { channel = "capability", direction = "send", - message = mock_device:generate_test_message("main", capabilities.lockAlarm.alarm.attemptsExceeded()), + message = mock_device:generate_test_message( + "main", + capabilities.lockAlarm.alarm.attemptsExceeded({state_change = true}) + ), }, { channel = "matter", @@ -203,7 +212,10 @@ test.register_message_test( { channel = "capability", direction = "send", - message = mock_device:generate_test_message("main", capabilities.lockAlarm.alarm.damaged()), + message = mock_device:generate_test_message( + "main", + capabilities.lockAlarm.alarm.damaged({state_change = true}) + ), }, { channel = "matter", @@ -218,7 +230,10 @@ test.register_message_test( { channel = "capability", direction = "send", - message = mock_device:generate_test_message("main", capabilities.lockAlarm.alarm.forcedOpeningAttempt()), + message = mock_device:generate_test_message( + "main", + capabilities.lockAlarm.alarm.forcedOpeningAttempt({state_change = true}) + ), }, } ) @@ -229,7 +244,10 @@ test.register_coroutine_test( test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.lockAlarm.alarm.clear()) + mock_device:generate_test_message( + "main", + capabilities.lockAlarm.alarm.clear({state_change = true}) + ) ) end ) From d5ec70c46335c0195449d65a675b322845fe8729 Mon Sep 17 00:00:00 2001 From: nickolas-deboom <158304111+nickolas-deboom@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:17:40 -0500 Subject: [PATCH 2/2] Revert dynamic constraint updates for matter-thermostat and matter-sensor (#1455) A bug exists in the hub firmware that needs to be corrected before temperature conversions for the setpoint limits will work. Therefore, this PR will revert the dynamic constraint updates originally made in PR 1223 until the bug is fixed in the next firmware release. --- .../SmartThings/matter-sensor/src/init.lua | 43 +---- .../test/test_matter_air_quality_sensor.lua | 14 +- .../src/test/test_matter_sensor.lua | 32 ---- .../test/test_matter_sensor_featuremap.lua | 4 +- .../src/test/test_matter_sensor_rpc.lua | 85 --------- .../src/test/test_matter_smoke_co_alarm.lua | 2 - .../matter-thermostat/src/init.lua | 140 ++++---------- .../src/test/test_matter_air_purifier.lua | 7 +- .../src/test/test_matter_room_ac.lua | 10 +- .../test/test_matter_thermo_featuremap.lua | 32 +--- .../test_matter_thermo_setpoint_limits.lua | 178 +++--------------- ...test_matter_thermo_setpoint_limits_rpc.lua | 152 --------------- .../src/test/test_matter_thermostat.lua | 12 -- ...est_matter_thermostat_composed_bridged.lua | 12 -- 14 files changed, 82 insertions(+), 641 deletions(-) delete mode 100644 drivers/SmartThings/matter-sensor/src/test/test_matter_sensor_rpc.lua delete mode 100644 drivers/SmartThings/matter-thermostat/src/test/test_matter_thermo_setpoint_limits_rpc.lua diff --git a/drivers/SmartThings/matter-sensor/src/init.lua b/drivers/SmartThings/matter-sensor/src/init.lua index 9ec2f269d7..2b91805958 100644 --- a/drivers/SmartThings/matter-sensor/src/init.lua +++ b/drivers/SmartThings/matter-sensor/src/init.lua @@ -42,20 +42,9 @@ if version.api < 10 then end local BATTERY_CHECKED = "__battery_checked" -local TEMP_BOUND_RECEIVED = "__temp_bound_received" -local TEMP_MIN = "__temp_min" -local TEMP_MAX = "__temp_max" local HUE_MANUFACTURER_ID = 0x100B -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, additional_params) - device:set_field(string.format("%s_%d", field, endpoint), value, additional_params) -end - local function supports_battery_percentage_remaining(device) local battery_eps = device:get_endpoints(clusters.PowerSource.ID, {feature_bitmap = clusters.PowerSource.types.PowerSourceFeature.BATTERY}) @@ -132,30 +121,6 @@ local function temperature_attr_handler(driver, device, ib, response) end end -local temp_attr_handler_factory = function(minOrMax) - return function(driver, device, ib, response) - -- Return if no data or RPC version < 4 (unit conversion for temperature - -- range capability is only supported for RPC >= 4) - if ib.data.value == nil or version.rpc < 4 then - return - end - local temp = ib.data.value / 100.0 - local unit = "C" - set_field_for_endpoint(device, TEMP_BOUND_RECEIVED..minOrMax, ib.endpoint_id, temp) - local min = get_field_for_endpoint(device, TEMP_BOUND_RECEIVED..TEMP_MIN, ib.endpoint_id) - local max = get_field_for_endpoint(device, TEMP_BOUND_RECEIVED..TEMP_MAX, 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 })) - set_field_for_endpoint(device, TEMP_BOUND_RECEIVED..TEMP_MIN, ib.endpoint_id, nil) - set_field_for_endpoint(device, TEMP_BOUND_RECEIVED..TEMP_MAX, ib.endpoint_id, nil) - 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 - end - end -end - local function humidity_attr_handler(driver, device, ib, response) local measured_value = ib.data.value if measured_value ~= nil then @@ -202,9 +167,7 @@ local matter_driver_template = { [clusters.RelativeHumidityMeasurement.attributes.MeasuredValue.ID] = humidity_attr_handler }, [clusters.TemperatureMeasurement.ID] = { - [clusters.TemperatureMeasurement.attributes.MeasuredValue.ID] = temperature_attr_handler, - [clusters.TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temp_attr_handler_factory(TEMP_MIN), - [clusters.TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temp_attr_handler_factory(TEMP_MAX), + [clusters.TemperatureMeasurement.attributes.MeasuredValue.ID] = temperature_attr_handler }, [clusters.IlluminanceMeasurement.ID] = { [clusters.IlluminanceMeasurement.attributes.MeasuredValue.ID] = illuminance_attr_handler @@ -230,9 +193,7 @@ local matter_driver_template = { clusters.RelativeHumidityMeasurement.attributes.MeasuredValue }, [capabilities.temperatureMeasurement.ID] = { - clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue + clusters.TemperatureMeasurement.attributes.MeasuredValue }, [capabilities.illuminanceMeasurement.ID] = { clusters.IlluminanceMeasurement.attributes.MeasuredValue diff --git a/drivers/SmartThings/matter-sensor/src/test/test_matter_air_quality_sensor.lua b/drivers/SmartThings/matter-sensor/src/test/test_matter_air_quality_sensor.lua index 77a7dc8493..ada7a0f20a 100644 --- a/drivers/SmartThings/matter-sensor/src/test/test_matter_air_quality_sensor.lua +++ b/drivers/SmartThings/matter-sensor/src/test/test_matter_air_quality_sensor.lua @@ -150,9 +150,7 @@ local function test_init() clusters.RelativeHumidityMeasurement.attributes.MeasuredValue }, [capabilities.temperatureMeasurement.ID] = { - clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue + clusters.TemperatureMeasurement.attributes.MeasuredValue }, [capabilities.airQualityHealthConcern.ID] = { clusters.AirQuality.attributes.AirQuality @@ -248,9 +246,7 @@ local function test_init_common() clusters.RelativeHumidityMeasurement.attributes.MeasuredValue }, [capabilities.temperatureMeasurement.ID] = { - clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue + clusters.TemperatureMeasurement.attributes.MeasuredValue }, [capabilities.airQualityHealthConcern.ID] = { clusters.AirQuality.attributes.AirQuality @@ -289,9 +285,7 @@ local function test_init_level() clusters.AirQuality.attributes.AirQuality }, [capabilities.temperatureMeasurement.ID] = { - clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue + clusters.TemperatureMeasurement.attributes.MeasuredValue }, [capabilities.relativeHumidityMeasurement.ID] = { clusters.RelativeHumidityMeasurement.attributes.MeasuredValue @@ -650,4 +644,4 @@ test.register_coroutine_test( { test_init = test_init_level } ) -test.run_registered_tests() \ No newline at end of file +test.run_registered_tests() diff --git a/drivers/SmartThings/matter-sensor/src/test/test_matter_sensor.lua b/drivers/SmartThings/matter-sensor/src/test/test_matter_sensor.lua index 14104a8867..6ebcb1a8a5 100644 --- a/drivers/SmartThings/matter-sensor/src/test/test_matter_sensor.lua +++ b/drivers/SmartThings/matter-sensor/src/test/test_matter_sensor.lua @@ -66,8 +66,6 @@ local mock_device = test.mock_device.build_test_matter_device({ local function subscribe_on_init(dev) local subscribe_request = clusters.RelativeHumidityMeasurement.attributes.MeasuredValue:subscribe(mock_device) subscribe_request:merge(clusters.TemperatureMeasurement.attributes.MeasuredValue:subscribe(mock_device)) - subscribe_request:merge(clusters.TemperatureMeasurement.attributes.MinMeasuredValue:subscribe(mock_device)) - subscribe_request:merge(clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:subscribe(mock_device)) subscribe_request:merge(clusters.IlluminanceMeasurement.attributes.MeasuredValue:subscribe(mock_device)) subscribe_request:merge(clusters.BooleanState.attributes.StateValue:subscribe(mock_device)) subscribe_request:merge(clusters.OccupancySensing.attributes.Occupancy:subscribe(mock_device)) @@ -80,7 +78,6 @@ local function test_init() test.mock_device.add_test_device(mock_device) -- don't check the battery for this device because we are using the catch-all "sensor.yml" profile just for testing mock_device:set_field("__battery_checked", 1, {persist = true}) - test.set_rpc_version(4) end test.set_test_init_function(test_init) @@ -240,8 +237,6 @@ test.register_message_test( local function refresh_commands(dev) local req = clusters.RelativeHumidityMeasurement.attributes.MeasuredValue:read(dev) req:merge(clusters.TemperatureMeasurement.attributes.MeasuredValue:read(dev)) - req:merge(clusters.TemperatureMeasurement.attributes.MinMeasuredValue:read(dev)) - req:merge(clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:read(dev)) req:merge(clusters.IlluminanceMeasurement.attributes.MeasuredValue:read(dev)) req:merge(clusters.BooleanState.attributes.StateValue:read(dev)) req:merge(clusters.OccupancySensing.attributes.Occupancy:read(dev)) @@ -271,31 +266,4 @@ test.register_message_test( } ) -test.register_message_test( - "Min and max temperature attributes set capability constraint", - { - { - channel = "matter", - direction = "receive", - message = { - mock_device.id, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue:build_test_report_data(mock_device, 1, 500) - } - }, - { - channel = "matter", - direction = "receive", - message = { - mock_device.id, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_report_data(mock_device, 1, 4000) - } - }, - { - channel = "capability", - direction = "send", - message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 5.00, maximum = 40.00 }, unit = "C" })) - } - } -) - test.run_registered_tests() diff --git a/drivers/SmartThings/matter-sensor/src/test/test_matter_sensor_featuremap.lua b/drivers/SmartThings/matter-sensor/src/test/test_matter_sensor_featuremap.lua index 18fa4573e6..a7fb80d277 100644 --- a/drivers/SmartThings/matter-sensor/src/test/test_matter_sensor_featuremap.lua +++ b/drivers/SmartThings/matter-sensor/src/test/test_matter_sensor_featuremap.lua @@ -119,9 +119,7 @@ local cluster_subscribe_list_humidity_no_battery = { local cluster_subscribe_list_temp_humidity = { clusters.RelativeHumidityMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue + clusters.TemperatureMeasurement.attributes.MeasuredValue } local function test_init_humidity_battery() diff --git a/drivers/SmartThings/matter-sensor/src/test/test_matter_sensor_rpc.lua b/drivers/SmartThings/matter-sensor/src/test/test_matter_sensor_rpc.lua deleted file mode 100644 index b595b5ac1d..0000000000 --- a/drivers/SmartThings/matter-sensor/src/test/test_matter_sensor_rpc.lua +++ /dev/null @@ -1,85 +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 test = require "integration_test" - -local t_utils = require "integration_test.utils" -local clusters = require "st.matter.clusters" - ---Note all endpoints are being mapped to the main component --- in the matter-sensor driver. If any devices require invoke/write --- requests to support the capabilities/preferences, custom mappings --- will need to be setup. -local matter_endpoints = { - { - endpoint_id = 0, - clusters = { - {cluster_id = clusters.Basic.ID, cluster_type = "SERVER"}, - }, - device_types = { - device_type_id = 0x0016, device_type_revision = 1, -- RootNode - } - }, - { - endpoint_id = 1, - clusters = { - {cluster_id = clusters.TemperatureMeasurement.ID, cluster_type = "BOTH"}, - } - } -} - -local mock_device = test.mock_device.build_test_matter_device({ - profile = t_utils.get_profile_definition("sensor.yml"), - endpoints = matter_endpoints -}) - -local function subscribe_on_init(dev) - local subscribe_request = clusters.TemperatureMeasurement.attributes.MeasuredValue:subscribe(mock_device) - subscribe_request:merge(clusters.TemperatureMeasurement.attributes.MinMeasuredValue:subscribe(mock_device)) - subscribe_request:merge(clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:subscribe(mock_device)) - return subscribe_request -end - -local function test_init() - test.socket.matter:__expect_send({mock_device.id, subscribe_on_init(mock_device)}) - test.mock_device.add_test_device(mock_device) - -- don't check the battery for this device because we are using the catch-all "sensor.yml" profile just for testing - mock_device:set_field("__battery_checked", 1, {persist = true}) - test.set_rpc_version(3) -end -test.set_test_init_function(test_init) - -test.register_message_test( - "Min and max temperature attributes do not set capability constraint when RPC version is less than 4", - { - { - channel = "matter", - direction = "receive", - message = { - mock_device.id, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue:build_test_report_data(mock_device, 1, 500) - } - }, - { - channel = "matter", - direction = "receive", - message = { - mock_device.id, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_report_data(mock_device, 1, 4000) - } - } - } -) - -test.run_registered_tests() diff --git a/drivers/SmartThings/matter-sensor/src/test/test_matter_smoke_co_alarm.lua b/drivers/SmartThings/matter-sensor/src/test/test_matter_smoke_co_alarm.lua index 97b4ae5f48..dc417abe5e 100644 --- a/drivers/SmartThings/matter-sensor/src/test/test_matter_smoke_co_alarm.lua +++ b/drivers/SmartThings/matter-sensor/src/test/test_matter_smoke_co_alarm.lua @@ -64,8 +64,6 @@ local cluster_subscribe_list = { clusters.SmokeCoAlarm.attributes.HardwareFaultAlert, clusters.SmokeCoAlarm.attributes.BatteryAlert, clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue, clusters.RelativeHumidityMeasurement.attributes.MeasuredValue, clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasuredValue, clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasurementUnit, diff --git a/drivers/SmartThings/matter-thermostat/src/init.lua b/drivers/SmartThings/matter-thermostat/src/init.lua index d2baf107f5..d12bf1eee2 100644 --- a/drivers/SmartThings/matter-thermostat/src/init.lua +++ b/drivers/SmartThings/matter-thermostat/src/init.lua @@ -76,14 +76,11 @@ local FAN_DEVICE_TYPE_ID = 0x002B local MGM3_PPM_CONVERSION_FACTOR = 24.45 local setpoint_limit_device_field = { - MIN_SETPOINT_DEADBAND_CHECKED = "MIN_SETPOINT_DEADBAND_CHECKED", MIN_HEAT = "MIN_HEAT", MAX_HEAT = "MAX_HEAT", MIN_COOL = "MIN_COOL", MAX_COOL = "MAX_COOL", MIN_DEADBAND = "MIN_DEADBAND", - MIN_TEMP = "MIN_TEMP", - MAX_TEMP = "MAX_TEMP" } local subscribed_attributes = { @@ -92,9 +89,7 @@ local subscribed_attributes = { }, [capabilities.temperatureMeasurement.ID] = { clusters.Thermostat.attributes.LocalTemperature, - clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue + clusters.TemperatureMeasurement.attributes.MeasuredValue }, [capabilities.relativeHumidityMeasurement.ID] = { clusters.RelativeHumidityMeasurement.attributes.MeasuredValue @@ -111,14 +106,10 @@ local subscribed_attributes = { clusters.FanControl.attributes.FanMode }, [capabilities.thermostatCoolingSetpoint.ID] = { - clusters.Thermostat.attributes.OccupiedCoolingSetpoint, - clusters.Thermostat.attributes.AbsMinCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit + clusters.Thermostat.attributes.OccupiedCoolingSetpoint }, [capabilities.thermostatHeatingSetpoint.ID] = { - clusters.Thermostat.attributes.OccupiedHeatingSetpoint, - clusters.Thermostat.attributes.AbsMinHeatSetpointLimit, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit + clusters.Thermostat.attributes.OccupiedHeatingSetpoint }, [capabilities.airConditionerFanMode.ID] = { clusters.FanControl.attributes.FanMode @@ -218,14 +209,6 @@ 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, additional_params) - device:set_field(string.format("%s_%d", field, endpoint), value, additional_params) -end - local function find_default_endpoint(device, cluster) local res = device.MATTER_DEFAULT_ENDPOINT local eps = embedded_cluster_utils.get_endpoints(device, cluster) @@ -254,17 +237,6 @@ end local function device_init(driver, device) device:subscribe() device:set_component_to_endpoint_fn(component_to_endpoint) - - if not device:get_field(setpoint_limit_device_field.MIN_SETPOINT_DEADBAND_CHECKED) then - local auto_eps = device:get_endpoints(clusters.Thermostat.ID, {feature_bitmap = clusters.Thermostat.types.ThermostatFeature.AUTOMODE}) - --Query min setpoint deadband if needed - if #auto_eps ~= 0 and device:get_field(setpoint_limit_device_field.MIN_DEADBAND) == nil then - local setpoint_limit_read = im.InteractionRequest(im.InteractionRequest.RequestType.READ, {}) - setpoint_limit_read:merge(clusters.Thermostat.attributes.MinSetpointDeadBand:read()) - device:send(setpoint_limit_read) - end - device:set_field(setpoint_limit_device_field.MIN_SETPOINT_DEADBAND_CHECKED, true) - end end local function info_changed(driver, device, event, args) @@ -343,6 +315,7 @@ end local function do_configure(driver, device) local heat_eps = device:get_endpoints(clusters.Thermostat.ID, {feature_bitmap = clusters.Thermostat.types.ThermostatFeature.HEATING}) local cool_eps = device:get_endpoints(clusters.Thermostat.ID, {feature_bitmap = clusters.Thermostat.types.ThermostatFeature.COOLING}) + local auto_eps = device:get_endpoints(clusters.Thermostat.ID, {feature_bitmap = clusters.Thermostat.types.ThermostatFeature.AUTOMODE}) local thermo_eps = device:get_endpoints(clusters.Thermostat.ID) local fan_eps = device:get_endpoints(clusters.FanControl.ID) local wind_eps = device:get_endpoints(clusters.FanControl.ID, {feature_bitmap = clusters.FanControl.types.FanControlFeature.WIND}) @@ -452,6 +425,27 @@ local function do_configure(driver, device) else device.log.warn_with({hub_logs=true}, "Device does not support thermostat cluster") end + + --Query setpoint limits if needed + local setpoint_limit_read = im.InteractionRequest(im.InteractionRequest.RequestType.READ, {}) + if #heat_eps ~= 0 and device:get_field(setpoint_limit_device_field.MIN_HEAT) == nil then + setpoint_limit_read:merge(clusters.Thermostat.attributes.AbsMinHeatSetpointLimit:read()) + end + if #heat_eps ~= 0 and device:get_field(setpoint_limit_device_field.MAX_HEAT) == nil then + setpoint_limit_read:merge(clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit:read()) + end + if #cool_eps ~= 0 and device:get_field(setpoint_limit_device_field.MIN_COOL) == nil then + setpoint_limit_read:merge(clusters.Thermostat.attributes.AbsMinCoolSetpointLimit:read()) + end + if #cool_eps ~= 0 and device:get_field(setpoint_limit_device_field.MAX_COOL) == nil then + setpoint_limit_read:merge(clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit:read()) + end + if #auto_eps ~= 0 and device:get_field(setpoint_limit_device_field.MIN_DEADBAND) == nil then + setpoint_limit_read:merge(clusters.Thermostat.attributes.MinSetpointDeadBand:read()) + end + if #setpoint_limit_read.info_blocks ~= 0 then + device:send(setpoint_limit_read) + end end local function device_added(driver, device) @@ -635,30 +629,6 @@ local function temp_event_handler(attribute) end end -local temp_attr_handler_factory = function(minOrMax) - return function(driver, device, ib, response) - -- Return if no data or RPC version < 4 (unit conversion for temperature - -- range capability is only supported for RPC >= 4) - if ib.data.value == nil or version.rpc < 4 then - return - end - local temp = ib.data.value / 100.0 - local unit = "C" - set_field_for_endpoint(device, minOrMax, ib.endpoint_id, temp) - 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 })) - set_field_for_endpoint(device, setpoint_limit_device_field.MIN_TEMP, ib.endpoint_id, nil) - set_field_for_endpoint(device, setpoint_limit_device_field.MAX_TEMP, ib.endpoint_id, nil) - 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 - end - end -end - local function humidity_attr_handler(driver, device, ib, response) local humidity = math.floor(ib.data.value / 100.0) device:emit_event_for_endpoint(ib.endpoint_id, capabilities.relativeHumidityMeasurement.humidity(humidity)) @@ -1041,55 +1011,11 @@ local function set_setpoint(setpoint) end end -local heating_setpoint_limit_handler_factory = function(minOrMax) +local function setpoint_limit_handler(limit_field) return function(driver, device, ib, response) - -- Return if no data or RPC version < 4 (unit conversion for heating setpoint - -- range capability is only supported for RPC >= 4) - if ib.data.value == nil or version.rpc < 4 then - return - end local val = ib.data.value / 100.0 - if val >= 40 then -- assume this is a fahrenheit value - val = utils.f_to_c(val) - end - 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) - if min ~= nil and max ~= nil then - if min < max then - device:emit_event_for_endpoint(ib.endpoint_id, capabilities.thermostatHeatingSetpoint.heatingSetpointRange({ value = { minimum = min, maximum = max }, unit = "C" })) - set_field_for_endpoint(device, setpoint_limit_device_field.MIN_HEAT, ib.endpoint_id, nil) - set_field_for_endpoint(device, setpoint_limit_device_field.MAX_HEAT, ib.endpoint_id, nil) - else - device.log.warn_with({hub_logs = true}, string.format("Device reported a min heating setpoint %d that is not lower than the reported max %d", min, max)) - end - end - end -end - -local cooling_setpoint_limit_handler_factory = function(minOrMax) - return function(driver, device, ib, response) - -- Return if no data or RPC version < 4 (unit conversion for cooling setpoint - -- range capability is only supported for RPC >= 4) - if ib.data.value == nil or version.rpc < 4 then - return - end - local val = ib.data.value / 100.0 - if val >= 40 then -- assume this is a fahrenheit value - val = utils.f_to_c(val) - end - 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) - if min ~= nil and max ~= nil then - if min < max then - device:emit_event_for_endpoint(ib.endpoint_id, capabilities.thermostatCoolingSetpoint.coolingSetpointRange({ value = { minimum = min, maximum = max }, unit = "C" })) - set_field_for_endpoint(device, setpoint_limit_device_field.MIN_COOL, ib.endpoint_id, nil) - set_field_for_endpoint(device, setpoint_limit_device_field.MAX_COOL, ib.endpoint_id, nil) - else - device.log.warn_with({hub_logs = true}, string.format("Device reported a min cooling setpoint %d that is not lower than the reported max %d", min, max)) - end - end + log.info("Setting " .. limit_field .. " to " .. string.format("%s", val)) + device:set_field(limit_field, val, { persist = true }) end end @@ -1195,10 +1121,10 @@ local matter_driver_template = { [clusters.Thermostat.attributes.SystemMode.ID] = system_mode_handler, [clusters.Thermostat.attributes.ThermostatRunningState.ID] = running_state_handler, [clusters.Thermostat.attributes.ControlSequenceOfOperation.ID] = sequence_of_operation_handler, - [clusters.Thermostat.attributes.AbsMinHeatSetpointLimit.ID] = heating_setpoint_limit_handler_factory(setpoint_limit_device_field.MIN_HEAT), - [clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit.ID] = heating_setpoint_limit_handler_factory(setpoint_limit_device_field.MAX_HEAT), - [clusters.Thermostat.attributes.AbsMinCoolSetpointLimit.ID] = cooling_setpoint_limit_handler_factory(setpoint_limit_device_field.MIN_COOL), - [clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit.ID] = cooling_setpoint_limit_handler_factory(setpoint_limit_device_field.MAX_COOL), + [clusters.Thermostat.attributes.AbsMinHeatSetpointLimit.ID] = setpoint_limit_handler(setpoint_limit_device_field.MIN_HEAT), + [clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit.ID] = setpoint_limit_handler(setpoint_limit_device_field.MAX_HEAT), + [clusters.Thermostat.attributes.AbsMinCoolSetpointLimit.ID] = setpoint_limit_handler(setpoint_limit_device_field.MIN_COOL), + [clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit.ID] = setpoint_limit_handler(setpoint_limit_device_field.MAX_COOL), [clusters.Thermostat.attributes.MinSetpointDeadBand.ID] = min_deadband_limit_handler, }, [clusters.FanControl.ID] = { @@ -1210,8 +1136,6 @@ local matter_driver_template = { }, [clusters.TemperatureMeasurement.ID] = { [clusters.TemperatureMeasurement.attributes.MeasuredValue.ID] = temp_event_handler(capabilities.temperatureMeasurement.temperature), - [clusters.TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temp_attr_handler_factory(setpoint_limit_device_field.MIN_TEMP), - [clusters.TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temp_attr_handler_factory(setpoint_limit_device_field.MAX_TEMP), }, [clusters.RelativeHumidityMeasurement.ID] = { [clusters.RelativeHumidityMeasurement.attributes.MeasuredValue.ID] = humidity_attr_handler diff --git a/drivers/SmartThings/matter-thermostat/src/test/test_matter_air_purifier.lua b/drivers/SmartThings/matter-thermostat/src/test/test_matter_air_purifier.lua index 9536cb28fe..7fb5873214 100644 --- a/drivers/SmartThings/matter-thermostat/src/test/test_matter_air_purifier.lua +++ b/drivers/SmartThings/matter-thermostat/src/test/test_matter_air_purifier.lua @@ -259,8 +259,6 @@ local cluster_subscribe_list_configured = { [capabilities.temperatureMeasurement.ID] = { clusters.Thermostat.attributes.LocalTemperature, clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue }, [capabilities.relativeHumidityMeasurement.ID] = { clusters.RelativeHumidityMeasurement.attributes.MeasuredValue @@ -278,8 +276,6 @@ local cluster_subscribe_list_configured = { }, [capabilities.thermostatHeatingSetpoint.ID] = { clusters.Thermostat.attributes.OccupiedHeatingSetpoint, - clusters.Thermostat.attributes.AbsMinHeatSetpointLimit, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit }, [capabilities.airPurifierFanMode.ID] = { clusters.FanControl.attributes.FanModeSequence, @@ -393,6 +389,9 @@ test.register_coroutine_test( "Test profile change on init for AP and Thermo and AQS combined device type", function() test.socket.device_lifecycle:__queue_receive({ mock_device_ap_thermo_aqs.id, "doConfigure" }) + local read_limits = clusters.Thermostat.attributes.AbsMinHeatSetpointLimit:read() + read_limits:merge(clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit:read()) + test.socket.matter:__expect_send({mock_device_ap_thermo_aqs.id, read_limits}) mock_device_ap_thermo_aqs:expect_metadata_update({ profile = "air-purifier-hepa-ac-wind-thermostat-humidity-fan-heating-only-nostate-nobattery-aqs-pm10-pm25-ch2o-meas-pm10-pm25-ch2o-no2-tvoc-level" }) mock_device_ap_thermo_aqs:expect_metadata_update({ provisioning_state = "PROVISIONED" }) print(mock_device_ap_thermo_aqs.profile) diff --git a/drivers/SmartThings/matter-thermostat/src/test/test_matter_room_ac.lua b/drivers/SmartThings/matter-thermostat/src/test/test_matter_room_ac.lua index d613a91fad..e13dcb993d 100644 --- a/drivers/SmartThings/matter-thermostat/src/test/test_matter_room_ac.lua +++ b/drivers/SmartThings/matter-thermostat/src/test/test_matter_room_ac.lua @@ -54,8 +54,6 @@ local function test_init() [capabilities.temperatureMeasurement.ID] = { clusters.Thermostat.attributes.LocalTemperature, clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue }, [capabilities.relativeHumidityMeasurement.ID] = { clusters.RelativeHumidityMeasurement.attributes.MeasuredValue @@ -68,14 +66,10 @@ local function test_init() clusters.Thermostat.attributes.ThermostatRunningState }, [capabilities.thermostatCoolingSetpoint.ID] = { - clusters.Thermostat.attributes.OccupiedCoolingSetpoint, - clusters.Thermostat.attributes.AbsMinCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit + clusters.Thermostat.attributes.OccupiedCoolingSetpoint }, [capabilities.thermostatHeatingSetpoint.ID] = { - clusters.Thermostat.attributes.OccupiedHeatingSetpoint, - clusters.Thermostat.attributes.AbsMinHeatSetpointLimit, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit + clusters.Thermostat.attributes.OccupiedHeatingSetpoint }, [capabilities.airConditionerFanMode.ID] = { clusters.FanControl.attributes.FanMode diff --git a/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermo_featuremap.lua b/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermo_featuremap.lua index e1b04e61a0..5e0825d4bf 100644 --- a/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermo_featuremap.lua +++ b/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermo_featuremap.lua @@ -127,16 +127,10 @@ local cluster_subscribe_list = { clusters.Thermostat.attributes.LocalTemperature, clusters.Thermostat.attributes.OccupiedCoolingSetpoint, clusters.Thermostat.attributes.OccupiedHeatingSetpoint, - clusters.Thermostat.attributes.AbsMinCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMinHeatSetpointLimit, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit, clusters.Thermostat.attributes.SystemMode, clusters.Thermostat.attributes.ThermostatRunningState, clusters.Thermostat.attributes.ControlSequenceOfOperation, clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue, clusters.RelativeHumidityMeasurement.attributes.MeasuredValue, clusters.FanControl.attributes.FanMode, clusters.FanControl.attributes.FanModeSequence, @@ -146,40 +140,23 @@ local cluster_subscribe_list_simple = { clusters.Thermostat.attributes.LocalTemperature, clusters.Thermostat.attributes.OccupiedCoolingSetpoint, clusters.Thermostat.attributes.OccupiedHeatingSetpoint, - clusters.Thermostat.attributes.AbsMinCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMinHeatSetpointLimit, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit, clusters.Thermostat.attributes.SystemMode, clusters.Thermostat.attributes.ThermostatRunningState, clusters.Thermostat.attributes.ControlSequenceOfOperation, clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue, clusters.PowerSource.attributes.BatPercentRemaining, } local cluster_subscribe_list_no_battery = { clusters.Thermostat.attributes.LocalTemperature, clusters.Thermostat.attributes.OccupiedCoolingSetpoint, clusters.Thermostat.attributes.OccupiedHeatingSetpoint, - clusters.Thermostat.attributes.AbsMinCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMinHeatSetpointLimit, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit, clusters.Thermostat.attributes.SystemMode, clusters.Thermostat.attributes.ThermostatRunningState, clusters.Thermostat.attributes.ControlSequenceOfOperation, clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue, } local function test_init() - -- Set MIN_SETPOINT_DEADBAND_CHECKED bypass the setpoint limit read so it does not need - -- to be checked in the init function. - mock_device:set_field("MIN_SETPOINT_DEADBAND_CHECKED", 1, {persist = true}) - mock_device_simple:set_field("MIN_SETPOINT_DEADBAND_CHECKED", 1, {persist = true}) - mock_device_no_battery:set_field("MIN_SETPOINT_DEADBAND_CHECKED", 1, {persist = true}) test.socket.matter:__set_channel_ordering("relaxed") local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device) for i, cluster in ipairs(cluster_subscribe_list) do @@ -212,6 +189,9 @@ test.register_coroutine_test( "Profile change on doConfigure lifecycle event due to cluster feature map", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) + local read_limits = clusters.Thermostat.attributes.AbsMinHeatSetpointLimit:read() + read_limits:merge(clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit:read()) + test.socket.matter:__expect_send({mock_device.id, read_limits}) --TODO why does provisiong state get added in the do configure event handle, but not the refres? mock_device:expect_metadata_update({ profile = "thermostat-humidity-fan-heating-only-nostate" }) mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) @@ -237,6 +217,9 @@ test.register_coroutine_test( "Profile change on doConfigure lifecycle event due to cluster feature map", function() test.socket.device_lifecycle:__queue_receive({ mock_device_simple.id, "doConfigure" }) + local read_limits = clusters.Thermostat.attributes.AbsMinCoolSetpointLimit:read() + read_limits:merge(clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit:read()) + test.socket.matter:__expect_send({mock_device_simple.id, read_limits}) mock_device_simple:expect_metadata_update({ profile = "thermostat-cooling-only-nostate" }) mock_device_simple:expect_metadata_update({ provisioning_state = "PROVISIONED" }) end @@ -246,6 +229,9 @@ test.register_coroutine_test( "Profile change on doConfigure lifecycle event no battery support", function() test.socket.device_lifecycle:__queue_receive({ mock_device_no_battery.id, "doConfigure" }) + local read_limits = clusters.Thermostat.attributes.AbsMinCoolSetpointLimit:read() + read_limits:merge(clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit:read()) + test.socket.matter:__expect_send({mock_device_no_battery.id, read_limits}) mock_device_no_battery:expect_metadata_update({ profile = "thermostat-cooling-only-nostate-nobattery" }) mock_device_no_battery:expect_metadata_update({ provisioning_state = "PROVISIONED" }) end 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 877432e294..974d09c039 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 @@ -43,7 +43,6 @@ local mock_device = test.mock_device.build_test_matter_device({ feature_map=35, -- Heat, Cool, and Auto features. }, {cluster_id = clusters.PowerSource.ID, cluster_type = "SERVER", feature_map = clusters.PowerSource.types.PowerSourceFeature.BATTERY}, - {cluster_id = clusters.TemperatureMeasurement.ID, cluster_type = "BOTH"}, }, device_types = { {device_type_id = 0x0301, device_type_revision = 1} -- Thermostat @@ -57,17 +56,10 @@ local function test_init() clusters.Thermostat.attributes.LocalTemperature, clusters.Thermostat.attributes.OccupiedCoolingSetpoint, clusters.Thermostat.attributes.OccupiedHeatingSetpoint, - clusters.Thermostat.attributes.AbsMinCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMinHeatSetpointLimit, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit, clusters.Thermostat.attributes.SystemMode, clusters.Thermostat.attributes.ThermostatRunningState, clusters.Thermostat.attributes.ControlSequenceOfOperation, clusters.PowerSource.attributes.BatPercentRemaining, - clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue, } test.socket.matter:__set_channel_ordering("relaxed") local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device) @@ -77,13 +69,7 @@ local function test_init() end end test.socket.matter:__expect_send({mock_device.id, subscribe_request}) - - local read_setpoint_deadband = clusters.Thermostat.attributes.MinSetpointDeadBand:read() - test.socket.matter:__expect_send({mock_device.id, read_setpoint_deadband}) - test.mock_device.add_test_device(mock_device) - - test.set_rpc_version(4) end test.set_test_init_function(test_init) @@ -92,18 +78,45 @@ local cached_cooling_setpoint = capabilities.thermostatCoolingSetpoint.coolingSe local function configure(device) test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) + local read_limits = clusters.Thermostat.attributes.AbsMinHeatSetpointLimit:read() + read_limits:merge(clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit:read()) + read_limits:merge(clusters.Thermostat.attributes.AbsMinCoolSetpointLimit:read()) + read_limits:merge(clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit:read()) + read_limits:merge(clusters.Thermostat.attributes.MinSetpointDeadBand:read()) + test.socket.matter:__expect_send({device.id, read_limits}) mock_device:expect_metadata_update({ profile = "thermostat-nostate" }) mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) test.wait_for_events() + --Populate setpoint limits + test.socket.matter:__queue_receive({ + device.id, + clusters.Thermostat.attributes.AbsMinHeatSetpointLimit:build_test_report_data(device, 1, 1000) + }) + test.socket.matter:__queue_receive({ + device.id, + clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit:build_test_report_data(device, 1, 3222) + }) + test.socket.matter:__queue_receive({ + device.id, + clusters.Thermostat.attributes.AbsMinCoolSetpointLimit:build_test_report_data(device, 1, 1000) --10.0 celcius + }) + test.socket.matter:__queue_receive({ + device.id, + clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit:build_test_report_data(device, 1, 3222) --32.22 celcius + }) + test.socket.matter:__queue_receive({ + device.id, + clusters.Thermostat.attributes.MinSetpointDeadBand:build_test_report_data(device, 1, 16) --1.6 celcius + }) --populate cached setpoint values. This would normally happen due to subscription setup. test.socket.matter:__queue_receive({ device.id, - clusters.Thermostat.attributes.OccupiedHeatingSetpoint:build_test_report_data(device, 1, 2444) --24.44 celcius + clusters.Thermostat.attributes.OccupiedHeatingSetpoint:build_test_report_data(mock_device, 1, 2444) --24.44 celcius }) test.socket.matter:__queue_receive({ device.id, - clusters.Thermostat.attributes.OccupiedCoolingSetpoint:build_test_report_data(device, 1, 2667) --26.67 celcius + clusters.Thermostat.attributes.OccupiedCoolingSetpoint:build_test_report_data(mock_device, 1, 2667) --26.67 celcius }) test.socket.capability:__expect_send( device:generate_test_message("main", cached_heating_setpoint) @@ -117,17 +130,6 @@ 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) - }) - test.socket.matter:__queue_receive({ - mock_device.id, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit:build_test_report_data(mock_device, 1, 3222) - }) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.thermostatHeatingSetpoint.heatingSetpointRange({ value = { minimum = 10.00, maximum = 32.22 }, unit = "C" })) - ) configure(mock_device) test.socket.capability:__queue_receive({ mock_device.id, @@ -142,17 +144,6 @@ 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) - }) - test.socket.matter:__queue_receive({ - mock_device.id, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit:build_test_report_data(mock_device, 1, 3222) - }) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.thermostatCoolingSetpoint.coolingSetpointRange({ value = { minimum = 10.00, maximum = 32.22 }, unit = "C" })) - ) configure(mock_device) test.socket.capability:__queue_receive({ mock_device.id, @@ -167,17 +158,6 @@ 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.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.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.thermostatHeatingSetpoint.heatingSetpointRange({ value = { minimum = 10.00, maximum = 32.22 }, unit = "C" })) - ) configure(mock_device) test.socket.capability:__queue_receive({ mock_device.id, @@ -192,17 +172,6 @@ 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.AbsMinCoolSetpointLimit:build_test_report_data(mock_device, 1, 1000) - }) - test.socket.matter:__queue_receive({ - mock_device.id, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit:build_test_report_data(mock_device, 1, 3222) - }) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.thermostatCoolingSetpoint.coolingSetpointRange({ value = { minimum = 10.00, maximum = 32.22 }, unit = "C" })) - ) configure(mock_device) test.socket.capability:__queue_receive({ mock_device.id, @@ -217,10 +186,6 @@ 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, @@ -235,10 +200,6 @@ 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, @@ -250,85 +211,4 @@ 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", - { - { - channel = "matter", - direction = "receive", - message = { - mock_device.id, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue:build_test_report_data(mock_device, 1, 500) - } - }, - { - channel = "matter", - direction = "receive", - message = { - mock_device.id, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_report_data(mock_device, 1, 4000) - } - }, - { - channel = "capability", - direction = "send", - message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 5.00, maximum = 40.00 }, unit = "C" })) - } - } -) - test.run_registered_tests() diff --git a/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermo_setpoint_limits_rpc.lua b/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermo_setpoint_limits_rpc.lua deleted file mode 100644 index e10b652f17..0000000000 --- a/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermo_setpoint_limits_rpc.lua +++ /dev/null @@ -1,152 +0,0 @@ --- --- 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 test = require "integration_test" -local t_utils = require "integration_test.utils" - -local clusters = require "st.matter.clusters" - -local mock_device = test.mock_device.build_test_matter_device({ - profile = t_utils.get_profile_definition("thermostat-humidity-fan.yml"), - manufacturer_info = { - vendor_id = 0x0000, - product_id = 0x0000, - }, - endpoints = { - { - endpoint_id = 0, - clusters = { - {cluster_id = clusters.Basic.ID, cluster_type = "SERVER"}, - }, - device_types = { - device_type_id = 0x0016, device_type_revision = 1, -- RootNode - } - }, - { - endpoint_id = 1, - clusters = { - { - cluster_id = clusters.Thermostat.ID, - cluster_revision=5, - cluster_type="SERVER", - feature_map=35, -- Heat, Cool, and Auto features. - }, - {cluster_id = clusters.PowerSource.ID, cluster_type = "SERVER", feature_map = clusters.PowerSource.types.PowerSourceFeature.BATTERY}, - {cluster_id = clusters.TemperatureMeasurement.ID, cluster_type = "BOTH"}, - } - } - } -}) - -local function test_init() - local cluster_subscribe_list = { - clusters.Thermostat.attributes.LocalTemperature, - clusters.Thermostat.attributes.OccupiedCoolingSetpoint, - clusters.Thermostat.attributes.OccupiedHeatingSetpoint, - clusters.Thermostat.attributes.AbsMinCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMinHeatSetpointLimit, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit, - clusters.Thermostat.attributes.SystemMode, - clusters.Thermostat.attributes.ThermostatRunningState, - clusters.Thermostat.attributes.ControlSequenceOfOperation, - clusters.PowerSource.attributes.BatPercentRemaining, - clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue, - } - test.socket.matter:__set_channel_ordering("relaxed") - local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device) - for i, cluster in ipairs(cluster_subscribe_list) do - if i > 1 then - subscribe_request:merge(cluster:subscribe(mock_device)) - end - end - test.socket.matter:__expect_send({mock_device.id, subscribe_request}) - - local read_setpoint_deadband = clusters.Thermostat.attributes.MinSetpointDeadBand:read() - test.socket.matter:__expect_send({mock_device.id, read_setpoint_deadband}) - - test.mock_device.add_test_device(mock_device) - - test.set_rpc_version(3) -end -test.set_test_init_function(test_init) - -test.register_message_test( - "Min and max heating setpoint attributes do not set capability constraint for RPC version less than 4", - { - { - 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) - } - } - } -) - -test.register_message_test( - "Min and max cooling setpoint attributes do not set capability constraint for RPC version less than 4", - { - { - 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) - } - } - } -) - -test.register_message_test( - "Min and max temperature attributes do not set capability constraint for RPC version less than 4", - { - { - channel = "matter", - direction = "receive", - message = { - mock_device.id, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue:build_test_report_data(mock_device, 1, 500) - } - }, - { - channel = "matter", - direction = "receive", - message = { - mock_device.id, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_report_data(mock_device, 1, 4000) - } - } - } -) - -test.run_registered_tests() diff --git a/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermostat.lua b/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermostat.lua index 96835c2f38..5e0e35c664 100644 --- a/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermostat.lua +++ b/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermostat.lua @@ -58,16 +58,10 @@ local function test_init() clusters.Thermostat.attributes.LocalTemperature, clusters.Thermostat.attributes.OccupiedCoolingSetpoint, clusters.Thermostat.attributes.OccupiedHeatingSetpoint, - clusters.Thermostat.attributes.AbsMinCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMinHeatSetpointLimit, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit, clusters.Thermostat.attributes.SystemMode, clusters.Thermostat.attributes.ThermostatRunningState, clusters.Thermostat.attributes.ControlSequenceOfOperation, clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue, clusters.RelativeHumidityMeasurement.attributes.MeasuredValue, clusters.FanControl.attributes.FanMode, clusters.FanControl.attributes.FanModeSequence, @@ -613,16 +607,10 @@ local attribute_refresh_list = { clusters.Thermostat.attributes.LocalTemperature, clusters.Thermostat.attributes.OccupiedCoolingSetpoint, clusters.Thermostat.attributes.OccupiedHeatingSetpoint, - clusters.Thermostat.attributes.AbsMinCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMinHeatSetpointLimit, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit, clusters.Thermostat.attributes.SystemMode, clusters.Thermostat.attributes.ThermostatRunningState, clusters.Thermostat.attributes.ControlSequenceOfOperation, clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue, clusters.RelativeHumidityMeasurement.attributes.MeasuredValue, clusters.FanControl.attributes.FanMode, clusters.FanControl.attributes.FanModeSequence, diff --git a/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermostat_composed_bridged.lua b/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermostat_composed_bridged.lua index f0d4744ce3..1e9da1a5e5 100644 --- a/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermostat_composed_bridged.lua +++ b/drivers/SmartThings/matter-thermostat/src/test/test_matter_thermostat_composed_bridged.lua @@ -58,16 +58,10 @@ local function test_init() clusters.Thermostat.attributes.LocalTemperature, clusters.Thermostat.attributes.OccupiedCoolingSetpoint, clusters.Thermostat.attributes.OccupiedHeatingSetpoint, - clusters.Thermostat.attributes.AbsMinCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMinHeatSetpointLimit, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit, clusters.Thermostat.attributes.SystemMode, clusters.Thermostat.attributes.ThermostatRunningState, clusters.Thermostat.attributes.ControlSequenceOfOperation, clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue, clusters.RelativeHumidityMeasurement.attributes.MeasuredValue, clusters.FanControl.attributes.FanMode, clusters.FanControl.attributes.FanModeSequence, @@ -633,16 +627,10 @@ local attribute_refresh_list = { clusters.Thermostat.attributes.LocalTemperature, clusters.Thermostat.attributes.OccupiedCoolingSetpoint, clusters.Thermostat.attributes.OccupiedHeatingSetpoint, - clusters.Thermostat.attributes.AbsMinCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit, - clusters.Thermostat.attributes.AbsMinHeatSetpointLimit, - clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit, clusters.Thermostat.attributes.SystemMode, clusters.Thermostat.attributes.ThermostatRunningState, clusters.Thermostat.attributes.ControlSequenceOfOperation, clusters.TemperatureMeasurement.attributes.MeasuredValue, - clusters.TemperatureMeasurement.attributes.MinMeasuredValue, - clusters.TemperatureMeasurement.attributes.MaxMeasuredValue, clusters.RelativeHumidityMeasurement.attributes.MeasuredValue, clusters.FanControl.attributes.FanMode, clusters.FanControl.attributes.FanModeSequence,