Skip to content

Commit 426eadd

Browse files
committed
[Thermostat] Add test for deadband handling
1 parent d98845b commit 426eadd

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

src/python_testing/TC_TSTAT_2_3.py

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#
2+
# Copyright (c) 2024 Project CHIP Authors
3+
# All rights reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments
18+
# for details about the block below.
19+
#
20+
# === BEGIN CI TEST ARGUMENTS ===
21+
# test-runner-runs: run1
22+
# test-runner-run/run1/app: ${ALL_CLUSTERS_APP}
23+
# test-runner-run/run1/factoryreset: True
24+
# test-runner-run/run1/quiet: True
25+
# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json
26+
# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
27+
# === END CI TEST ARGUMENTS ===
28+
29+
import copy
30+
import logging
31+
import random
32+
33+
import chip.clusters as Clusters
34+
from chip import ChipDeviceCtrl # Needed before chip.FabricAdmin
35+
from chip.clusters import Globals
36+
from chip.clusters.Types import NullValue
37+
from chip.interaction_model import InteractionModelError, Status
38+
from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main
39+
from mobly import asserts
40+
41+
logger = logging.getLogger(__name__)
42+
43+
cluster = Clusters.Thermostat
44+
45+
46+
class TC_TSTAT_2_2(MatterBaseTest):
47+
def desc_TC_TSTAT_2_2(self) -> str:
48+
"""Returns a description of this test"""
49+
return "42.2.2. [TC-TSTAT-2.2] Setpoint Test Cases with server as DUT"
50+
51+
def pics_TC_TSTAT_2_2(self):
52+
""" This function returns a list of PICS for this test case that must be True for the test to be run"""
53+
return ["TSTAT.S"]
54+
55+
def steps_TC_TSTAT_2_2(self) -> list[TestStep]:
56+
steps = [
57+
TestStep("1", "Commissioning, already done",
58+
is_commissioning=True),
59+
TestStep("2", "Test Harness Client reads AbsMinHeatSetpointLimit, MinHeatSetpointLimit, AbsMaxCoolSetpointLimit, MaxCoolSetpointLimit, DeadBand, OccupiedCoolingSetpoint, OccupiedHeatingSetpoint attributes from Server DUT"),
60+
TestStep("3", "Test Harness Client reads UnoccupiedCoolingSetpoint, UnoccupiedHeatingSetpoint attributes from Server DUT"),
61+
TestStep("4", "If the OccupiedCoolingSetpoint is at least 0.01C less than the minimum of MaxCoolSetpointLimit and AbsMaxCoolSetpointLimit, the Test Harness Client sets the OccupiedHeatingSetpoint to (OccupiedCoolingSetpoint - Deadband) + 0.01C",
62+
"The OccupiedCoolingSetpoint attribute should increase in value by 0.01C"),
63+
TestStep("5", "If the OccupiedHeatingSetpoint is at least 0.01C more than the maximum of MinHeatSetpointLimit and AbsMinHeatSetpointLimit, the Test Harness Client sets the OccupiedCoolingSetpoint to (OccupiedHeatingSetpoint + Deadband) - 0.01C",
64+
"The OccupiedHeatingSetpoint attribute should decrease in value by 0.01C"),
65+
TestStep("6", "If the UnoccupiedCoolingSetpoint is at least 0.01C less than the minimum of MaxCoolSetpointLimit and AbsMaxCoolSetpointLimit, the Test Harness Client sets the UnoccupiedHeatingSetpoint to (UnoccupiedCoolingSetpoint - Deadband) + 0.01C",
66+
"The UnoccupiedCoolingSetpoint attribute should increase in value by 0.01C"),
67+
TestStep("7", "If the UnoccupiedHeatingSetpoint is at least 0.01C more than the maximum of MinHeatSetpointLimit and AbsMinHeatSetpointLimit, the Test Harness Client sets the UnoccupiedCoolingSetpoint to (UnoccupiedHeatingSetpoint + Deadband) - 0.01C",
68+
"The UnoccupiedHeatingSetpoint attribute should decrease in value by 0.01C"),
69+
]
70+
return steps
71+
72+
@async_test_body
73+
async def test_TC_TSTAT_2_2(self):
74+
endpoint = self.user_params.get("endpoint", 1)
75+
76+
self.step("1")
77+
# Commission DUT - already done
78+
79+
if not self.pics_guard(self.check_pics("TSTAT.S.F05")):
80+
# Thermostats that do not support the Auto system mode do not have to maintain a deadband
81+
self.skip_all_remaining_steps("2")
82+
return
83+
84+
self.step("2")
85+
absMinHeatSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.AbsMinHeatSetpointLimit)
86+
minHeatSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MinHeatSetpointLimit)
87+
absMaxCoolSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.AbsMaxCoolSetpointLimit)
88+
maxCoolSetpointLimit = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MaxCoolSetpointLimit)
89+
occupiedCoolingSetpoint = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.OccupiedCoolingSetpoint)
90+
occupiedHeatingSetpoint = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.OccupiedHeatingSetpoint)
91+
deadband = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.MinSetpointDeadBand)
92+
deadband *= 10 # Unlike all the setpoints it affects, deadband is in 0.1C increments, because reasons
93+
unoccupiedCoolingSetpoint = None
94+
unoccupiedHeatingSetpoint = None
95+
96+
self.step("3")
97+
if self.pics_guard(self.check_pics("TSTAT.S.F02")):
98+
unoccupiedCoolingSetpoint = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.UnoccupiedCoolingSetpoint)
99+
unoccupiedHeatingSetpoint = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.UnoccupiedHeatingSetpoint)
100+
101+
maxCool = min(maxCoolSetpointLimit, absMaxCoolSetpointLimit)
102+
minHeat = max(minHeatSetpointLimit, absMinHeatSetpointLimit)
103+
104+
self.step("4")
105+
if occupiedCoolingSetpoint < maxCool:
106+
targetHeatingSetpoint = (occupiedCoolingSetpoint - deadband) + 1
107+
targetCoolingSetpoint = targetHeatingSetpoint + deadband
108+
await self.write_single_attribute(attribute_value=cluster.Attributes.OccupiedHeatingSetpoint(targetHeatingSetpoint), endpoint_id=endpoint)
109+
occupiedCoolingSetpoint = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.OccupiedCoolingSetpoint)
110+
asserts.assert_equal(occupiedCoolingSetpoint, targetCoolingSetpoint, "OccupiedCoolingSetpoint was not adjusted")
111+
112+
self.step("5")
113+
if occupiedHeatingSetpoint > minHeat:
114+
targetCoolingSetpoint = (occupiedHeatingSetpoint + deadband) - 1
115+
targetHeatingSetpoint = targetCoolingSetpoint - deadband
116+
await self.write_single_attribute(attribute_value=cluster.Attributes.OccupiedCoolingSetpoint(targetCoolingSetpoint), endpoint_id=endpoint)
117+
occupiedHeatingSetpoint = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.OccupiedHeatingSetpoint)
118+
asserts.assert_equal(occupiedHeatingSetpoint, targetHeatingSetpoint, "OccupiedHeatingSetpoint was not adjusted")
119+
120+
self.step("6")
121+
if self.pics_guard(self.check_pics("TSTAT.S.F02")) and unoccupiedCoolingSetpoint < maxCool:
122+
targetHeatingSetpoint = (unoccupiedCoolingSetpoint - deadband) + 1
123+
targetCoolingSetpoint = targetHeatingSetpoint + deadband
124+
await self.write_single_attribute(attribute_value=cluster.Attributes.UnoccupiedHeatingSetpoint(targetHeatingSetpoint), endpoint_id=endpoint)
125+
unoccupiedCoolingSetpoint = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.UnoccupiedCoolingSetpoint)
126+
asserts.assert_equal(unoccupiedCoolingSetpoint, targetCoolingSetpoint, "UnoccupiedCoolingSetpoint was not adjusted")
127+
128+
129+
self.step("7")
130+
if self.pics_guard(self.check_pics("TSTAT.S.F02")) and unoccupiedHeatingSetpoint > minHeat:
131+
targetCoolingSetpoint = (unoccupiedHeatingSetpoint + deadband) - 1
132+
targetHeatingSetpoint = targetCoolingSetpoint - deadband
133+
await self.write_single_attribute(attribute_value=cluster.Attributes.UnoccupiedCoolingSetpoint(targetCoolingSetpoint), endpoint_id=endpoint)
134+
unoccupiedHeatingSetpoint = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=cluster.Attributes.UnoccupiedHeatingSetpoint)
135+
asserts.assert_equal(unoccupiedHeatingSetpoint, targetHeatingSetpoint, "UnoccupiedHeatingSetpoint was not adjusted")
136+
137+
if __name__ == "__main__":
138+
default_matter_test_main()

0 commit comments

Comments
 (0)