Skip to content

Commit 29d332c

Browse files
extract commissioning.py from matter_testing.py (#37577)
* extract commissioning.py from matter_testing.py * Restyled by isort * Restyled by autopep8 * format and fix imports * add commissioning.py to BUILD.gn * add docstrings * optional type * fix comments * Restyled by isort * undo formatting * fix ruff checks --------- Co-authored-by: Restyled.io <commits@restyled.io>
1 parent fee6066 commit 29d332c

File tree

3 files changed

+211
-101
lines changed

3 files changed

+211
-101
lines changed

src/python_testing/matter_testing_infrastructure/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pw_python_package("chip-testing-module") {
3838
"chip/testing/apps.py",
3939
"chip/testing/basic_composition.py",
4040
"chip/testing/choice_conformance.py",
41+
"chip/testing/commissioning.py",
4142
"chip/testing/conformance.py",
4243
"chip/testing/conversions.py",
4344
"chip/testing/global_attribute_ids.py",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
#
2+
# Copyright (c) 2022-2025 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+
18+
"""
19+
This module contains classes and functions designed to handle the commissioning process of Matter devices.
20+
"""
21+
22+
import logging
23+
from dataclasses import dataclass
24+
from typing import List, Optional
25+
26+
from chip import ChipDeviceCtrl, discovery
27+
from chip.ChipDeviceCtrl import CommissioningParameters
28+
from chip.clusters import ClusterObjects as ClusterObjects
29+
from chip.exceptions import ChipStackError
30+
31+
logger = logging.getLogger("matter.python_testing")
32+
logger.setLevel(logging.INFO)
33+
34+
DiscoveryFilterType = ChipDeviceCtrl.DiscoveryFilterType
35+
36+
37+
@dataclass
38+
class SetupPayloadInfo:
39+
"""
40+
Represents information required to set up a payload during commissioning.
41+
42+
Attributes:
43+
filter_type (discovery.FilterType): The type of filter used for discrimination. Default is `FilterType.LONG_DISCRIMINATOR`.
44+
filter_value (int): The value associated with the filter type. Default is `0`.
45+
passcode (int): A unique code or password required for setup. Default is `0`.
46+
"""
47+
filter_type: discovery.FilterType = discovery.FilterType.LONG_DISCRIMINATOR
48+
filter_value: int = 0
49+
passcode: int = 0
50+
51+
52+
@dataclass
53+
class CommissioningInfo:
54+
"""
55+
Represents the information required for commissioning a device.
56+
57+
Attributes:
58+
commissionee_ip_address_just_for_testing (Optional[str]):
59+
The IP address of the commissionee used only for testing purposes.
60+
61+
commissioning_method (Optional[str]):
62+
The method by which the device is being commissioned.
63+
64+
thread_operational_dataset (Optional[str]):
65+
The Thread operational dataset if applicable during commissioning.
66+
67+
wifi_passphrase (Optional[str]):
68+
The passphrase to connect to a Wi-Fi network, if required.
69+
70+
wifi_ssid (Optional[str]):
71+
The name of the Wi-Fi network to which the device should connect.
72+
73+
tc_version_to_simulate (Optional[int]):
74+
The version of the Terms and Conditions to simulate during testing.
75+
This is used when accepting terms and conditions in a simulated environment.
76+
77+
tc_user_response_to_simulate (Optional[int]):
78+
The user response to simulate for the Terms and Conditions, if applicable.
79+
"""
80+
commissionee_ip_address_just_for_testing: Optional[str] = None
81+
commissioning_method: Optional[str] = None
82+
thread_operational_dataset: Optional[str] = None
83+
wifi_passphrase: Optional[str] = None
84+
wifi_ssid: Optional[str] = None
85+
tc_version_to_simulate: Optional[int] = None
86+
tc_user_response_to_simulate: Optional[int] = None
87+
88+
89+
@dataclass
90+
class CustomCommissioningParameters:
91+
"""
92+
A custom data class that encapsulates commissioning parameters with an additional random discriminator.
93+
94+
Attributes:
95+
commissioningParameters (CommissioningParameters): The underlying commissioning parameters.
96+
randomDiscriminator (int): A randomly generated value used to uniquely identify or distinguish instances during commissioning processes.
97+
"""
98+
commissioningParameters: CommissioningParameters
99+
randomDiscriminator: int
100+
101+
102+
async def commission_device(
103+
dev_ctrl: ChipDeviceCtrl.ChipDeviceController, node_id: int, info: SetupPayloadInfo, commissioning_info: CommissioningInfo
104+
) -> bool:
105+
"""
106+
Starts the commissioning process of a chip device.
107+
108+
This function handles different commissioning methods based on the specified method.
109+
It supports various commissioning techniques such as "on-network", "ble-wifi", and "ble-thread".
110+
111+
Parameters:
112+
dev_ctrl: The chip device controller instance.
113+
node_id: Unique identifier for the chip node.
114+
info: Contains setup information including passcode, filter_type, and filter_value.
115+
commissioning_info: Specifies the type of commissioning method to use.
116+
117+
Returns:
118+
True if the commissioning process completes successfully. False otherwise,
119+
except in case of an error which logs the exception details.
120+
121+
Note:
122+
The "on-network-ip" method is deprecated as it's not supported in long-term
123+
environments.
124+
"""
125+
126+
if commissioning_info.tc_version_to_simulate is not None and commissioning_info.tc_user_response_to_simulate is not None:
127+
logging.debug(
128+
f"Setting TC Acknowledgements to version {commissioning_info.tc_version_to_simulate} with user response {commissioning_info.tc_user_response_to_simulate}."
129+
)
130+
dev_ctrl.SetTCAcknowledgements(commissioning_info.tc_version_to_simulate, commissioning_info.tc_user_response_to_simulate)
131+
132+
if commissioning_info.commissioning_method == "on-network":
133+
try:
134+
await dev_ctrl.CommissionOnNetwork(
135+
nodeId=node_id, setupPinCode=info.passcode, filterType=info.filter_type, filter=info.filter_value
136+
)
137+
return True
138+
except ChipStackError as e:
139+
logging.error("Commissioning failed: %s" % e)
140+
return False
141+
elif commissioning_info.commissioning_method == "ble-wifi":
142+
try:
143+
await dev_ctrl.CommissionWiFi(
144+
info.filter_value,
145+
info.passcode,
146+
node_id,
147+
commissioning_info.wifi_ssid,
148+
commissioning_info.wifi_passphrase,
149+
isShortDiscriminator=(info.filter_type == DiscoveryFilterType.SHORT_DISCRIMINATOR),
150+
)
151+
return True
152+
except ChipStackError as e:
153+
logging.error("Commissioning failed: %s" % e)
154+
return False
155+
elif commissioning_info.commissioning_method == "ble-thread":
156+
try:
157+
await dev_ctrl.CommissionThread(
158+
info.filter_value,
159+
info.passcode,
160+
node_id,
161+
commissioning_info.thread_operational_dataset,
162+
isShortDiscriminator=(info.filter_type == DiscoveryFilterType.SHORT_DISCRIMINATOR),
163+
)
164+
return True
165+
except ChipStackError as e:
166+
logging.error("Commissioning failed: %s" % e)
167+
return False
168+
elif commissioning_info.commissioning_method == "on-network-ip":
169+
try:
170+
logging.warning("==== USING A DIRECT IP COMMISSIONING METHOD NOT SUPPORTED IN THE LONG TERM ====")
171+
await dev_ctrl.CommissionIP(
172+
ipaddr=commissioning_info.commissionee_ip_address_just_for_testing,
173+
setupPinCode=info.passcode,
174+
nodeid=node_id,
175+
)
176+
return True
177+
except ChipStackError as e:
178+
logging.error("Commissioning failed: %s" % e)
179+
return False
180+
else:
181+
raise ValueError("Invalid commissioning method %s!" % commissioning_info.commissioning_method)
182+
183+
184+
async def commission_devices(
185+
dev_ctrl: ChipDeviceCtrl.ChipDeviceController,
186+
dut_node_ids: List[int],
187+
setup_payloads: List[SetupPayloadInfo],
188+
commissioning_info: CommissioningInfo,
189+
) -> bool:
190+
"""
191+
Attempt to commission all specified device nodes with their respective setup payloads.
192+
193+
Args:
194+
dev_ctrl: The chip device controller being used.
195+
dut_node_ids: List of node IDs that need to be commissioned.
196+
setup_payloads: List of SetupPayloadInfo objects containing configuration data
197+
for each node to be set up and commissioned.
198+
commissioning_info: Information about the commissioning process, including method,
199+
parameters, etc.
200+
201+
Returns:
202+
bool: True if all devices were successfully commissioned; False otherwise.
203+
"""
204+
commissioned = []
205+
for node_id, setup_payload in zip(dut_node_ids, setup_payloads):
206+
logging.info(f"Commissioning method: {commissioning_info.commissioning_method}")
207+
commissioned.append(await commission_device(dev_ctrl, node_id, setup_payload, commissioning_info))
208+
209+
return all(commissioned)

src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py

+1-101
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
from chip import ChipDeviceCtrl # Needed before chip.FabricAdmin
5252
import chip.FabricAdmin # Needed before chip.CertificateAuthority
5353
import chip.CertificateAuthority
54-
from chip.ChipDeviceCtrl import CommissioningParameters
5554

5655
# isort: on
5756
from time import sleep
@@ -68,6 +67,7 @@
6867
from chip.interaction_model import InteractionModelError, Status
6968
from chip.setup_payload import SetupPayload
7069
from chip.storage import PersistentStorage
70+
from chip.testing.commissioning import CommissioningInfo, CustomCommissioningParameters, SetupPayloadInfo, commission_devices
7171
from chip.testing.global_attribute_ids import GlobalAttributeIds
7272
from chip.testing.pics import read_pics_from_file
7373
from chip.tracing import TracingContext
@@ -152,100 +152,6 @@ def get_default_paa_trust_store(root_path: pathlib.Path) -> pathlib.Path:
152152
return pathlib.Path.cwd()
153153

154154

155-
@dataclass
156-
class SetupPayloadInfo:
157-
filter_type: discovery.FilterType = discovery.FilterType.LONG_DISCRIMINATOR
158-
filter_value: int = 0
159-
passcode: int = 0
160-
161-
162-
@dataclass
163-
class CommissioningInfo:
164-
commissionee_ip_address_just_for_testing: Optional[str] = None
165-
commissioning_method: Optional[str] = None
166-
thread_operational_dataset: Optional[str] = None
167-
wifi_passphrase: Optional[str] = None
168-
wifi_ssid: Optional[str] = None
169-
# Accepted Terms and Conditions if used
170-
tc_version_to_simulate: int = None
171-
tc_user_response_to_simulate: int = None
172-
173-
174-
async def commission_device(
175-
dev_ctrl: ChipDeviceCtrl.ChipDeviceController, node_id: int, info: SetupPayloadInfo, commissioning_info: CommissioningInfo
176-
) -> bool:
177-
if commissioning_info.tc_version_to_simulate is not None and commissioning_info.tc_user_response_to_simulate is not None:
178-
logging.debug(
179-
f"Setting TC Acknowledgements to version {commissioning_info.tc_version_to_simulate} with user response {commissioning_info.tc_user_response_to_simulate}."
180-
)
181-
dev_ctrl.SetTCAcknowledgements(commissioning_info.tc_version_to_simulate, commissioning_info.tc_user_response_to_simulate)
182-
183-
if commissioning_info.commissioning_method == "on-network":
184-
try:
185-
await dev_ctrl.CommissionOnNetwork(
186-
nodeId=node_id, setupPinCode=info.passcode, filterType=info.filter_type, filter=info.filter_value
187-
)
188-
return True
189-
except ChipStackError as e:
190-
logging.error("Commissioning failed: %s" % e)
191-
return False
192-
elif commissioning_info.commissioning_method == "ble-wifi":
193-
try:
194-
await dev_ctrl.CommissionWiFi(
195-
info.filter_value,
196-
info.passcode,
197-
node_id,
198-
commissioning_info.wifi_ssid,
199-
commissioning_info.wifi_passphrase,
200-
isShortDiscriminator=(info.filter_type == DiscoveryFilterType.SHORT_DISCRIMINATOR),
201-
)
202-
return True
203-
except ChipStackError as e:
204-
logging.error("Commissioning failed: %s" % e)
205-
return False
206-
elif commissioning_info.commissioning_method == "ble-thread":
207-
try:
208-
await dev_ctrl.CommissionThread(
209-
info.filter_value,
210-
info.passcode,
211-
node_id,
212-
commissioning_info.thread_operational_dataset,
213-
isShortDiscriminator=(info.filter_type == DiscoveryFilterType.SHORT_DISCRIMINATOR),
214-
)
215-
return True
216-
except ChipStackError as e:
217-
logging.error("Commissioning failed: %s" % e)
218-
return False
219-
elif commissioning_info.commissioning_method == "on-network-ip":
220-
try:
221-
logging.warning("==== USING A DIRECT IP COMMISSIONING METHOD NOT SUPPORTED IN THE LONG TERM ====")
222-
await dev_ctrl.CommissionIP(
223-
ipaddr=commissioning_info.commissionee_ip_address_just_for_testing,
224-
setupPinCode=info.passcode,
225-
nodeid=node_id,
226-
)
227-
return True
228-
except ChipStackError as e:
229-
logging.error("Commissioning failed: %s" % e)
230-
return False
231-
else:
232-
raise ValueError("Invalid commissioning method %s!" % commissioning_info.commissioning_method)
233-
234-
235-
async def commission_devices(
236-
dev_ctrl: ChipDeviceCtrl.ChipDeviceController,
237-
dut_node_ids: List[int],
238-
setup_payloads: List[SetupPayloadInfo],
239-
commissioning_info: CommissioningInfo,
240-
) -> bool:
241-
commissioned = []
242-
for node_id, setup_payload in zip(dut_node_ids, setup_payloads):
243-
logging.info(f"Commissioning method: {commissioning_info.commissioning_method}")
244-
commissioned.append(await commission_device(dev_ctrl, node_id, setup_payload, commissioning_info))
245-
246-
return all(commissioned)
247-
248-
249155
class SimpleEventCallback:
250156
def __init__(self, name: str, expected_cluster_id: int, expected_event_id: int, output_queue: queue.SimpleQueue):
251157
self._name = name
@@ -735,12 +641,6 @@ def get_attribute_string(self, cluster_id: int, attribute_id) -> str:
735641
return f"Attribute {attribute_name} ({attribute_id}, 0x{attribute_id:04X})"
736642

737643

738-
@dataclass
739-
class CustomCommissioningParameters:
740-
commissioningParameters: CommissioningParameters
741-
randomDiscriminator: int
742-
743-
744644
@dataclass
745645
class ClusterPathLocation:
746646
endpoint_id: int

0 commit comments

Comments
 (0)