Skip to content

Commit 8f63c49

Browse files
committed
First versionof DEM 1-1
1 parent 1e0db09 commit 8f63c49

File tree

1 file changed

+216
-0
lines changed

1 file changed

+216
-0
lines changed

src/python_testing/TC_DEM_1_1.py

+216
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
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+
# pylint: disable=invalid-name
17+
18+
# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments
19+
# for details about the block below.
20+
#
21+
# === BEGIN CI TEST ARGUMENTS ===
22+
# test-runner-runs: run1
23+
# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
24+
# test-runner-run/run1/factoryreset: True
25+
# test-runner-run/run1/quiet: True
26+
# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x23
27+
# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
28+
# === END CI TEST ARGUMENTS ===
29+
30+
"""Define Matter test case TC_DEM_1_1."""
31+
32+
33+
import logging
34+
35+
import chip.clusters as Clusters
36+
from chip.interaction_model import Status
37+
from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main
38+
from mobly import asserts
39+
from TC_DEMTestBase import DEMTestBase
40+
41+
logger = logging.getLogger(__name__)
42+
43+
44+
class TC_DEM_1_1(MatterBaseTest, DEMTestBase):
45+
"""Implementation of test case TC_DEM_1_1."""
46+
47+
def desc_TC_DEM_1_1(self) -> str:
48+
"""Return a description of this test."""
49+
return "4.1.3. [TC-DEM-2.5] Forecast Adjustment with Power Forecast Reporting feature functionality with DUT as Server"
50+
51+
def pics_TC_DEM_1_1(self):
52+
"""Return the PICS definitions associated with this test."""
53+
pics = [
54+
# Depends on Feature 05 (ForecastAdjustment) & Feature 01 (PowerForecastReporting)
55+
"DEM.S.F05", "DEM.S.F01"
56+
]
57+
return pics
58+
59+
def steps_TC_DEM_1_1(self) -> list[TestStep]:
60+
"""Execute the test steps."""
61+
steps = [
62+
TestStep("1", "Commission DUT to TH (can be skipped if done in a preceding test)."),
63+
TestStep("2", "TH reads from the DUT the ClusterRevision attribute.",
64+
"Verify that the DUT response contains the ClusterRevision attribute and has the value 3."),
65+
TestStep("3", "TH reads from the DUT the FeatureMap attribute.",
66+
"Verify that the DUT response contains the FeatureMap attribute and have the following bit set:\n- bit 0: SHALL be 1 if and only if DEM.S.F00(PowerAdjustment).\n- bit 1: SHALL be 1 if and only if DEM.S.F01(PowerForecastReporting).\n- bit 2: SHALL be 1 if and only if DEM.S.F02(StateForecastReporting).\n- bit 3: SHALL be 1 if and only if DEM.S.F03(StartTimeAdjustment).\n- bit 4: SHALL be 1 if and only if DEM.S.F04(Pausable).\nAll remaining bits SHALL be 0. Provisional features DEM.S.F05(ForecastAdjustment) and DEM.S.F06(ConstraintBasedAdjustment) must not be supported."),
67+
TestStep("4", "TH reads from the DUT the AttributeList attribute.",
68+
"Verify that the DUT response contains the AttributeList attribute and have the list of supported attributes:\nThe list SHALL include all the mandatory entries: +\n0x0000, 0x0001, 0x0002, 0x0003, 0x0004\n0xfff8, 0xfff9, 0xfffb, 0xfffc and 0xfffd.\nThe list includes entries based on feature support: +\n- 0x0005: SHALL be included if and only if DEM.S.F00(PowerAdjustment).\nDEM.S.F02(StateForecastReporting).\n- 0x0007: SHALL be included if and only if DEM.S.F00(PowerAdjustment)"),
69+
TestStep("5", "TH reads from the DUT the EventList attribute.",
70+
"Verify that the DUT response contains the EventList attribute and have the list of supported events:\nThe list includes entries based on feature support: +\n- 0x00, 0x01: SHALL be included if and only if DEM.S.F00(PowerAdjustment).\n- 0x02, 0x03: SHALL be included if and only if DEM.S.F04(Pausable)."),
71+
TestStep("6", "TH reads from the DUT the AcceptedCommandList attribute.",
72+
"Verify that the DUT response contains the AcceptedCommandList attribute and have the list of Accepted Command:\nThe list includes entries based on feature support: +\n- 0x00, 0x01: SHALL be included if and only if DEM.S.F00(PowerAdjustment).\n- 0x02: SHALL be included if and only if DEM.S.F03(StartTimeAdjustment).\n- 0x03, 0x04: SHALL be included if and only if DEM.S.F04(Pausable).\n- 0x05: SHALL be included if and only if DEM.S.F05(ForecastAdjustment).\n- 0x06: SHALL be included if and only if DEM.S.F06(ConstraintBasedAdjustment).\n- 0x07: SHALL be included if and only if DEM.S.F03(StartTimeAdjustment)"),
73+
TestStep("7", "TH reads from the DUT the GeneratedCommandList attribute.",
74+
"Verify that the DUT response contains the GeneratedCommandList attribute and have the list of Generated Command:\nThis cluster has no entries in the standard or scoped range. +"),
75+
]
76+
77+
return steps
78+
79+
@async_test_body
80+
async def test_TC_DEM_1_1(self):
81+
# pylint: disable=too-many-locals, too-many-statements
82+
"""Run the test steps."""
83+
self.step("1")
84+
# Commission DUT - already done
85+
86+
self.step("2")
87+
await self.check_dem_attribute("ClusterRevision", 4)
88+
89+
90+
self.step("3")
91+
#await self.validate_feature_map([Clusters.DeviceEnergyManagement.Bitmaps.Feature.kForecastAdjustment,
92+
# Clusters.DeviceEnergyManagement.Bitmaps.Feature.kPowerForecastReporting],
93+
# [Clusters.DeviceEnergyManagement.Bitmaps.Feature.kPowerAdjustment,
94+
# Clusters.DeviceEnergyManagement.Bitmaps.Feature.kStateForecastReporting,
95+
# Clusters.DeviceEnergyManagement.Bitmaps.Feature.kStartTimeAdjustment,
96+
# Clusters.DeviceEnergyManagement.Bitmaps.Feature.kPausable,
97+
# Clusters.DeviceEnergyManagement.Bitmaps.Feature.kConstraintBasedAdjustment])
98+
99+
self.step("4")
100+
attribute_list = await self.read_dem_attribute_expect_success(attribute="AttributeList")
101+
logging.info(attribute_list)
102+
103+
mandatory_attributes = [Clusters.DeviceEnergyManagement.Attributes.ESAType.attribute_id,
104+
Clusters.DeviceEnergyManagement.Attributes.ESACanGenerate.attribute_id,
105+
Clusters.DeviceEnergyManagement.Attributes.ESAState.attribute_id,
106+
Clusters.DeviceEnergyManagement.Attributes.AbsMinPower.attribute_id,
107+
Clusters.DeviceEnergyManagement.Attributes.AbsMaxPower.attribute_id]
108+
109+
for mandatory_attribute in mandatory_attributes:
110+
asserts.assert_true(mandatory_attribute in attribute_list,
111+
f"Expected to find mandatory attribute {mandatory_attribute} in attribute_list {attribute_list}")
112+
113+
# Remove the enrty from the list
114+
attribute_list.remove(mandatory_attribute)
115+
116+
# Now check feature dependant attributes
117+
feature_map = await self.read_dem_attribute_expect_success(attribute="FeatureMap")
118+
119+
attribute_id = Clusters.DeviceEnergyManagement.Attributes.PowerAdjustmentCapability.attribute_id
120+
required_features = Clusters.DeviceEnergyManagement.Bitmaps.Feature.kPowerAdjustment
121+
self.check_attribute_valid_and_remove_from_list(attribute_id, feature_map, attribute_list, required_features)
122+
123+
attribute_id = Clusters.DeviceEnergyManagement.Attributes.Forecast.attribute_id
124+
required_features = (Clusters.DeviceEnergyManagement.Bitmaps.Feature.kPowerForecastReporting |
125+
Clusters.DeviceEnergyManagement.Bitmaps.Feature.kStateForecastReporting)
126+
self.check_attribute_valid_and_remove_from_list(attribute_id, feature_map, attribute_list, required_features)
127+
128+
attribute_id = Clusters.DeviceEnergyManagement.Attributes.OptOutState.attribute_id
129+
required_features = (Clusters.DeviceEnergyManagement.Bitmaps.Feature.kPowerAdjustment |
130+
Clusters.DeviceEnergyManagement.Bitmaps.Feature.kStartTimeAdjustment |
131+
Clusters.DeviceEnergyManagement.Bitmaps.Feature.kPausable |
132+
Clusters.DeviceEnergyManagement.Bitmaps.Feature.kForecastAdjustment |
133+
Clusters.DeviceEnergyManagement.Bitmaps.Feature.kConstraintBasedAdjustment)
134+
135+
self.check_attribute_valid_and_remove_from_list(attribute_id, feature_map, attribute_list, required_features)
136+
137+
global_attributes = [Clusters.DeviceEnergyManagement.Attributes.GeneratedCommandList.attribute_id,
138+
Clusters.DeviceEnergyManagement.Attributes.AcceptedCommandList.attribute_id,
139+
Clusters.DeviceEnergyManagement.Attributes.AttributeList.attribute_id,
140+
Clusters.DeviceEnergyManagement.Attributes.FeatureMap.attribute_id,
141+
Clusters.DeviceEnergyManagement.Attributes.ClusterRevision.attribute_id]
142+
143+
for global_attribute in global_attributes:
144+
logging.info(f"global_attribute {global_attribute} global_attributes {global_attributes}")
145+
asserts.assert_true(global_attribute in attribute_list,
146+
f"Expected to find global attribute {global_attribute} in attribute_list {attribute_list}")
147+
148+
# Remove the enrty from the list
149+
attribute_list.remove(global_attribute)
150+
151+
# Check there are no unknown attributes left in the list
152+
asserts.assert_equal(len(attribute_list), 0)
153+
154+
self.step("5")
155+
#event_list = await self.read_dem_attribute_expect_success(attribute="EventList")
156+
#logging.info(f"event_list {event_list}")
157+
158+
#n- 0x00, 0x01: SHALL be included if and only if DEM.S.F00(PowerAdjustment).\n- 0x02, 0x03: SHALL be included if and only if DEM.S.F04(Pausable)."),
159+
self.step("6")
160+
accepted_command_list = await self.read_dem_attribute_expect_success(attribute="AcceptedCommandList")
161+
logging.info(f"accepted_command_list {accepted_command_list}")
162+
163+
required_features = Clusters.DeviceEnergyManagement.Bitmaps.Feature.kPowerAdjustment
164+
expected_commands = [Clusters.DeviceEnergyManagement.Commands.PowerAdjustRequest.command_id,
165+
Clusters.DeviceEnergyManagement.Commands.CancelPowerAdjustRequest.command_id]
166+
self.check_expected_commands_in_list(expected_commands, feature_map, accepted_command_list, required_features)
167+
168+
required_features = Clusters.DeviceEnergyManagement.Bitmaps.Feature.kStartTimeAdjustment
169+
expected_commands = [Clusters.DeviceEnergyManagement.Commands.StartTimeAdjustRequest.command_id]
170+
self.check_expected_commands_in_list(expected_commands, feature_map, accepted_command_list, required_features)
171+
172+
required_features = Clusters.DeviceEnergyManagement.Bitmaps.Feature.kPausable
173+
expected_commands = [Clusters.DeviceEnergyManagement.Commands.PauseRequest.command_id,
174+
Clusters.DeviceEnergyManagement.Commands.ResumeRequest.command_id]
175+
self.check_expected_commands_in_list(expected_commands, feature_map, accepted_command_list, required_features)
176+
177+
required_features = Clusters.DeviceEnergyManagement.Bitmaps.Feature.kForecastAdjustment
178+
expected_commands = [Clusters.DeviceEnergyManagement.Commands.ModifyForecastRequest.command_id]
179+
self.check_expected_commands_in_list(expected_commands, feature_map, accepted_command_list, required_features)
180+
181+
required_features = Clusters.DeviceEnergyManagement.Bitmaps.Feature.kConstraintBasedAdjustment
182+
expected_commands = [Clusters.DeviceEnergyManagement.Commands.RequestConstraintBasedForecast.command_id]
183+
self.check_expected_commands_in_list(expected_commands, feature_map, accepted_command_list, required_features)
184+
185+
required_features = (Clusters.DeviceEnergyManagement.Bitmaps.Feature.kStartTimeAdjustment |
186+
Clusters.DeviceEnergyManagement.Bitmaps.Feature.kForecastAdjustment |
187+
Clusters.DeviceEnergyManagement.Bitmaps.Feature.kConstraintBasedAdjustment)
188+
expected_commands = [Clusters.DeviceEnergyManagement.Commands.CancelRequest.command_id]
189+
self.check_expected_commands_in_list(expected_commands, feature_map, accepted_command_list, required_features)
190+
191+
self.step("7")
192+
generated_command_list = await self.read_dem_attribute_expect_success(attribute="GeneratedCommandList")
193+
asserts.assert_equal(len(generated_command_list), 0)
194+
195+
def check_attribute_valid_and_remove_from_list(self, attribute_id, feature_map, attribute_list, required_features):
196+
if feature_map & required_features:
197+
asserts.assert_true(attribute_id in attribute_list,
198+
f"Expected to find attribute {attribute_id} in attribute_list {attribute_list} given feature_map 0x{feature_map:x}")
199+
attribute_list.remove(attribute_id)
200+
201+
else:
202+
asserts.assert_false(attribute_id in attribute_list,
203+
f"Did not expect to find attribute {attribute_id} in attribute_list {attribute_list} given feature_map 0x{feature_map:x}")
204+
205+
def check_expected_commands_in_list(self, expected_commands, feature_map, accepted_command_list, required_features):
206+
if (feature_map & required_features) != 0:
207+
for command in expected_commands:
208+
asserts.assert_true(command in accepted_command_list,
209+
f"Expected command {command} to be in accepted_command_list {accepted_command_list} given required_features {required_features} in feature_map 0x{feature_map:x}")
210+
211+
else:
212+
for command in expected_commands:
213+
asserts.assert_false(command in accepted_command_list,
214+
f"Did not expect command {command} to be in accepted_command_list {accepted_command_list} given required_features {required_features} in feature_map 0x{feature_map:x}")
215+
if __name__ == "__main__":
216+
default_matter_test_main()

0 commit comments

Comments
 (0)