From e9d7b2fffc59f191c2d71f5da4653801bc9e17ca Mon Sep 17 00:00:00 2001 From: Hasty Granbery Date: Wed, 25 Sep 2024 00:59:44 -0700 Subject: [PATCH] Update TC_TSTAT_4_2 to work with thermostats that are already on a fabric or don't have min/max (#35754) * Don't hard-code the fabric index when removing the secondary fabric * Fall back on Absolute setpoints, and then defaults, when user-configured setpoints are unimplemented --- src/python_testing/TC_TSTAT_4_2.py | 46 ++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/src/python_testing/TC_TSTAT_4_2.py b/src/python_testing/TC_TSTAT_4_2.py index b2916c5914e38a..8ebd2ece70521f 100644 --- a/src/python_testing/TC_TSTAT_4_2.py +++ b/src/python_testing/TC_TSTAT_4_2.py @@ -261,6 +261,8 @@ async def test_TC_TSTAT_4_2(self): nodeId=self.dut_node_id, setupPinCode=params.setupPinCode, filterType=ChipDeviceCtrl.DiscoveryFilterType.LONG_DISCRIMINATOR, filter=1234) + secondary_fabric_index = await self.read_single_attribute_check_success(dev_ctrl=secondary_controller, endpoint=0, cluster=Clusters.Objects.OperationalCredentials, attribute=Clusters.OperationalCredentials.Attributes.CurrentFabricIndex) + current_presets = [] presetTypes = [] presetScenarioCounts = {} @@ -272,26 +274,54 @@ async def test_TC_TSTAT_4_2(self): supportsHeat = self.check_pics("TSTAT.S.F00") supportsCool = self.check_pics("TSTAT.S.F01") - supportsOccupancy = self.check_pics("TSTAT.S.F02") - - occupied = True if supportsHeat: - minHeatSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MinHeatSetpointLimit) - maxHeatSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MaxHeatSetpointLimit) + # If the server supports MinHeatSetpointLimit & MaxHeatSetpointLimit, use those + if self.check_pics("TSTAT.S.A0015") and self.check_pics("TSTAT.S.A0016"): + minHeatSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MinHeatSetpointLimit) + maxHeatSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MaxHeatSetpointLimit) + elif self.check_pics("TSTAT.S.A0003") and self.check_pics("TSTAT.S.A0004"): + # Otherwise, if the server supports AbsMinHeatSetpointLimit & AbsMaxHeatSetpointLimit, use those + minHeatSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.AbsMinHeatSetpointLimit) + maxHeatSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.AbsMaxHeatSetpointLimit) + asserts.assert_true(minHeatSetpointLimit < maxHeatSetpointLimit, "Heat setpoint range invalid") if supportsCool: - minCoolSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MinCoolSetpointLimit) - maxCoolSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MaxCoolSetpointLimit) + # If the server supports MinCoolSetpointLimit & MaxCoolSetpointLimit, use those + if self.check_pics("TSTAT.S.A0017") and self.check_pics("TSTAT.S.A0018"): + minCoolSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MinCoolSetpointLimit) + maxCoolSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MaxCoolSetpointLimit) + elif self.check_pics("TSTAT.S.A0005") and self.check_pics("TSTAT.S.A0006"): + # Otherwise, if the server supports AbsMinCoolSetpointLimit & AbsMaxCoolSetpointLimit, use those + minCoolSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.AbsMinCoolSetpointLimit) + maxCoolSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.AbsMaxCoolSetpointLimit) + asserts.assert_true(minCoolSetpointLimit < maxCoolSetpointLimit, "Cool setpoint range invalid") + # Servers that do not support occupancy are always "occupied" + occupied = True + + supportsOccupancy = self.check_pics("TSTAT.S.F02") if supportsOccupancy: occupied = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.Occupancy) & 1 + # Target setpoints heatSetpoint = minHeatSetpointLimit + ((maxHeatSetpointLimit - minHeatSetpointLimit) / 2) coolSetpoint = minCoolSetpointLimit + ((maxCoolSetpointLimit - minCoolSetpointLimit) / 2) + # Set the heating and cooling setpoints to something other than the target setpoints + if occupied: + if supportsHeat: + await self.write_single_attribute(attribute_value=cluster.Attributes.OccupiedHeatingSetpoint(heatSetpoint-1), endpoint_id=endpoint) + if supportsCool: + await self.write_single_attribute(attribute_value=cluster.Attributes.OccupiedCoolingSetpoint(coolSetpoint-1), endpoint_id=endpoint) + else: + if supportsHeat: + await self.write_single_attribute(attribute_value=cluster.Attributes.UnoccupiedHeatingSetpoint(heatSetpoint-1), endpoint_id=endpoint) + if supportsCool: + await self.write_single_attribute(attribute_value=cluster.Attributes.UnoccupiedCoolingSetpoint(coolSetpoint-1), endpoint_id=endpoint) + self.step("2") if self.pics_guard(self.check_pics("TSTAT.S.F08") and self.check_pics("TSTAT.S.A0050")): @@ -643,7 +673,7 @@ async def test_TC_TSTAT_4_2(self): await self.send_atomic_request_begin_command(dev_ctrl=secondary_controller) # Primary controller removes the second fabric - await self.send_single_cmd(Clusters.OperationalCredentials.Commands.RemoveFabric(fabricIndex=2), endpoint=0) + await self.send_single_cmd(Clusters.OperationalCredentials.Commands.RemoveFabric(fabricIndex=secondary_fabric_index), endpoint=0) # Send the AtomicRequest begin command from primary controller, which should succeed, as the secondary controller's atomic write state has been cleared status = await self.send_atomic_request_begin_command()