From 2474fc3840ee2aaea703996889b8cf7caeb2cbdc Mon Sep 17 00:00:00 2001 From: C Freeman Date: Fri, 29 Nov 2024 12:04:49 -0500 Subject: [PATCH 01/74] Bridge: Remove ACL client (#36677) --- .../bridge-common/bridge-app.matter | 126 ------------------ .../bridge-app/bridge-common/bridge-app.zap | 28 ++-- 2 files changed, 13 insertions(+), 141 deletions(-) diff --git a/examples/bridge-app/bridge-common/bridge-app.matter b/examples/bridge-app/bridge-common/bridge-app.matter index 6241e8c635bba9..5979751c01b3b7 100644 --- a/examples/bridge-app/bridge-common/bridge-app.matter +++ b/examples/bridge-app/bridge-common/bridge-app.matter @@ -667,131 +667,6 @@ cluster AccessControl = 31 { fabric command access(invoke: administer) ReviewFabricRestrictions(ReviewFabricRestrictionsRequest): ReviewFabricRestrictionsResponse = 0; } -/** The Access Control Cluster exposes a data model view of a - Node's Access Control List (ACL), which codifies the rules used to manage - and enforce Access Control for the Node's endpoints and their associated - cluster instances. */ -cluster AccessControl = 31 { - revision 2; - - enum AccessControlEntryAuthModeEnum : enum8 { - kPASE = 1; - kCASE = 2; - kGroup = 3; - } - - enum AccessControlEntryPrivilegeEnum : enum8 { - kView = 1; - kProxyView = 2; - kOperate = 3; - kManage = 4; - kAdminister = 5; - } - - enum AccessRestrictionTypeEnum : enum8 { - kAttributeAccessForbidden = 0; - kAttributeWriteForbidden = 1; - kCommandForbidden = 2; - kEventForbidden = 3; - } - - enum ChangeTypeEnum : enum8 { - kChanged = 0; - kAdded = 1; - kRemoved = 2; - } - - bitmap Feature : bitmap32 { - kExtension = 0x1; - kManagedDevice = 0x2; - } - - struct AccessRestrictionStruct { - AccessRestrictionTypeEnum type = 0; - nullable int32u id = 1; - } - - struct CommissioningAccessRestrictionEntryStruct { - endpoint_no endpoint = 0; - cluster_id cluster = 1; - AccessRestrictionStruct restrictions[] = 2; - } - - fabric_scoped struct AccessRestrictionEntryStruct { - fabric_sensitive endpoint_no endpoint = 0; - fabric_sensitive cluster_id cluster = 1; - fabric_sensitive AccessRestrictionStruct restrictions[] = 2; - fabric_idx fabricIndex = 254; - } - - struct AccessControlTargetStruct { - nullable cluster_id cluster = 0; - nullable endpoint_no endpoint = 1; - nullable devtype_id deviceType = 2; - } - - fabric_scoped struct AccessControlEntryStruct { - fabric_sensitive AccessControlEntryPrivilegeEnum privilege = 1; - fabric_sensitive AccessControlEntryAuthModeEnum authMode = 2; - nullable fabric_sensitive int64u subjects[] = 3; - nullable fabric_sensitive AccessControlTargetStruct targets[] = 4; - fabric_idx fabricIndex = 254; - } - - fabric_scoped struct AccessControlExtensionStruct { - fabric_sensitive octet_string<128> data = 1; - fabric_idx fabricIndex = 254; - } - - fabric_sensitive info event access(read: administer) AccessControlEntryChanged = 0 { - nullable node_id adminNodeID = 1; - nullable int16u adminPasscodeID = 2; - ChangeTypeEnum changeType = 3; - nullable AccessControlEntryStruct latestValue = 4; - fabric_idx fabricIndex = 254; - } - - fabric_sensitive info event access(read: administer) AccessControlExtensionChanged = 1 { - nullable node_id adminNodeID = 1; - nullable int16u adminPasscodeID = 2; - ChangeTypeEnum changeType = 3; - nullable AccessControlExtensionStruct latestValue = 4; - fabric_idx fabricIndex = 254; - } - - fabric_sensitive info event access(read: administer) FabricRestrictionReviewUpdate = 2 { - int64u token = 0; - optional long_char_string instruction = 1; - optional long_char_string ARLRequestFlowUrl = 2; - fabric_idx fabricIndex = 254; - } - - attribute access(read: administer, write: administer) AccessControlEntryStruct acl[] = 0; - attribute access(read: administer, write: administer) optional AccessControlExtensionStruct extension[] = 1; - readonly attribute int16u subjectsPerAccessControlEntry = 2; - readonly attribute int16u targetsPerAccessControlEntry = 3; - readonly attribute int16u accessControlEntriesPerFabric = 4; - readonly attribute optional CommissioningAccessRestrictionEntryStruct commissioningARL[] = 5; - readonly attribute optional AccessRestrictionEntryStruct arl[] = 6; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute event_id eventList[] = 65530; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; - - request struct ReviewFabricRestrictionsRequest { - CommissioningAccessRestrictionEntryStruct arl[] = 0; - } - - response struct ReviewFabricRestrictionsResponse = 1 { - int64u token = 0; - } - - /** This command signals to the service associated with the device vendor that the fabric administrator would like a review of the current restrictions on the accessing fabric. */ - fabric command access(invoke: administer) ReviewFabricRestrictions(ReviewFabricRestrictionsRequest): ReviewFabricRestrictionsResponse = 0; -} - /** This cluster provides a standardized way for a Node (typically a Bridge, but could be any Node) to expose action information. */ cluster Actions = 37 { revision 1; // NOTE: Default/not specifically set @@ -2272,7 +2147,6 @@ cluster TemperatureMeasurement = 1026 { endpoint 0 { device type ma_rootdevice = 22, version 1; - binding cluster AccessControl; server cluster Descriptor { callback attribute deviceTypeList; diff --git a/examples/bridge-app/bridge-common/bridge-app.zap b/examples/bridge-app/bridge-common/bridge-app.zap index bf78875444add5..8c5882fbd4dbd3 100644 --- a/examples/bridge-app/bridge-common/bridge-app.zap +++ b/examples/bridge-app/bridge-common/bridge-app.zap @@ -1,6 +1,6 @@ { "fileFormat": 2, - "featureLevel": 103, + "featureLevel": 104, "creator": "zap", "keyValuePairs": [ { @@ -41,14 +41,16 @@ "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 } ], "deviceVersions": [ @@ -215,14 +217,6 @@ } ] }, - { - "name": "Access Control", - "code": 31, - "mfgCode": null, - "define": "ACCESS_CONTROL_CLUSTER", - "side": "client", - "enabled": 1 - }, { "name": "Access Control", "code": 31, @@ -4403,14 +4397,16 @@ "code": 14, "profileId": 259, "label": "MA-aggregator", - "name": "MA-aggregator" + "name": "MA-aggregator", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 14, "profileId": 259, "label": "MA-aggregator", - "name": "MA-aggregator" + "name": "MA-aggregator", + "deviceTypeOrder": 0 } ], "deviceVersions": [ @@ -4891,14 +4887,16 @@ "code": 257, "profileId": 259, "label": "MA-dimmablelight", - "name": "MA-dimmablelight" + "name": "MA-dimmablelight", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 257, "profileId": 259, "label": "MA-dimmablelight", - "name": "MA-dimmablelight" + "name": "MA-dimmablelight", + "deviceTypeOrder": 0 } ], "deviceVersions": [ From e402b96fff27361cb46e581d5e84f1971302a35b Mon Sep 17 00:00:00 2001 From: achaulk-goog <107196446+achaulk-goog@users.noreply.github.com> Date: Fri, 29 Nov 2024 17:07:04 -0500 Subject: [PATCH 02/74] Fix JniReferences::GetOptionalValue (#36682) * Fix JniReferences::GetOptionalValue It's possible the optional is not of class java/util/Optional so just use the object provided * fix formatting --- src/lib/support/JniReferences.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/support/JniReferences.cpp b/src/lib/support/JniReferences.cpp index 021f13c2fb0fb2..3e1c8bd79b4d94 100644 --- a/src/lib/support/JniReferences.cpp +++ b/src/lib/support/JniReferences.cpp @@ -310,8 +310,8 @@ CHIP_ERROR JniReferences::GetOptionalValue(jobject optionalObj, jobject & option { JNIEnv * env = GetEnvForCurrentThread(); VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NULL_OBJECT); - jclass optionalCls = nullptr; - ReturnErrorOnFailure(chip::JniReferences::GetInstance().GetLocalClassRef(env, "java/util/Optional", optionalCls)); + VerifyOrReturnError(optionalObj != nullptr, CHIP_JNI_ERROR_NULL_OBJECT); + jclass optionalCls = env->GetObjectClass(optionalObj); jmethodID isPresentMethod = env->GetMethodID(optionalCls, "isPresent", "()Z"); VerifyOrReturnError(isPresentMethod != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND); jboolean isPresent = optionalObj && env->CallBooleanMethod(optionalObj, isPresentMethod); From f488ad44fda5d0fdcefb27894bab9fb58179d8e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Mon, 2 Dec 2024 14:55:22 +0100 Subject: [PATCH 03/74] Update host.py to fix water-leak-detector-app gen (#36683) --- scripts/build/builders/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py index 43b95b763278b8..7fe5823f37b7a8 100644 --- a/scripts/build/builders/host.py +++ b/scripts/build/builders/host.py @@ -159,7 +159,7 @@ def ExamplePath(self): elif self == HostApp.ENERGY_MANAGEMENT: return 'energy-management-app/linux' elif self == HostApp.WATER_LEAK_DETECTOR: - return 'water-leak-detector/linux' + return 'water-leak-detector-app/linux' else: raise Exception('Unknown app type: %r' % self) From 5ca422b0c8f00c2d385b38e0ad68745bd9b171a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Mon, 2 Dec 2024 15:34:16 +0100 Subject: [PATCH 04/74] Formatting code extracts (#36670) * Formatting code extracts Formatting code extracts * Update python.md WARNING: Could not lex literal_block as "python" --- docs/testing/python.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/testing/python.md b/docs/testing/python.md index 1db6ff779b8461..a7bec6d07e17c3 100644 --- a/docs/testing/python.md +++ b/docs/testing/python.md @@ -217,7 +217,7 @@ Each `Clusters..Structs.` has: Example: -``` +```python Clusters.BasicInformation.Structs.ProductAppearanceStruct( finish=Clusters.BasicInformation.Enums.ProductFinishEnum.kFabric, primaryColor=Clusters.BasicInformation.Enums.ColorEnum.kBlack) @@ -293,7 +293,7 @@ Multi-path Example: -``` +```python urgent = 1 await dev_ctrl ReadEvent(node_id, [(1, @@ -359,7 +359,7 @@ asserts.assert_equal(ret[0].status, Status.Success, “write failed”) Example: -``` +```python pai = await dev_ctrl.SendCommand(nodeid, 0, Clusters.OperationalCredentials.Commands.CertificateChainRequest(2)) ``` @@ -387,7 +387,7 @@ class provides some helpers for Mobly integration. use as: -``` +```python if __name__ == "__main__": default_matter_test_main() ``` @@ -479,7 +479,7 @@ See To create a controller on a new fabric: -``` +```python new_CA = self.certificate_authority_manager.NewCertificateAuthority() new_fabric_admin = new_certificate_authority.NewFabricAdmin(vendorId=0xFFF1, @@ -490,7 +490,7 @@ TH2 = new_fabric_admin.NewController(nodeId=112233) Open a commissioning window (ECW): -``` +```python params = self.OpenCommissioningWindow(dev_ctrl=self.default_controller, node_id=self.dut_node_id) ``` @@ -499,7 +499,7 @@ the fabric admin. Fabric admin for default controller: -``` +```python fa = self.certificate_authority_manager.activeCaList[0].adminList[0] second_ctrl = fa.new_fabric_admin.NewController(nodeId=node_id) ``` @@ -577,13 +577,13 @@ running. To compile and install the wheel, do the following: First activate the matter environment using either -``` +```shell . ./scripts/bootstrap.sh ``` or -``` +```shell . ./scripts/activate.sh ``` @@ -592,7 +592,7 @@ subsequent setups as it is faster. Next build the python wheels and create / activate a venv -``` +```shell ./scripts/build_python.sh -i out/python_env source out/python_env/bin/activate ``` @@ -609,7 +609,7 @@ that will be commissioned either over BLE or WiFi. For example, to run the TC-ACE-1.2 tests against an un-commissioned DUT: -``` +```shell python3 src/python_testing/TC_ACE_1_2.py --commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 ``` @@ -617,7 +617,7 @@ Some tests require additional arguments (ex. PIXITs or configuration variables for the CI). These arguments can be passed as sets of key/value pairs using the `---arg:` command line arguments. For example: -``` +```shell --int-arg PIXIT.ACE.APPENDPOINT:1 --int-arg PIXIT.ACE.APPDEVTYPEID:0x0100 --string-arg PIXIT.ACE.APPCLUSTER:OnOff --string-arg PIXIT.ACE.APPATTRIBUTE:OnOff ``` From 511997770172f01067288d16625daa506af2ea2a Mon Sep 17 00:00:00 2001 From: BoB13-Matter Date: Mon, 2 Dec 2024 23:58:25 +0900 Subject: [PATCH 05/74] Documentation: Fix incorrect paths in fuzz_testing.md and yaml.md (#36689) * Documentation: Fix incorrect paths in fuzz_testing.md and yaml.md * Update fuzz_testing.md --- docs/testing/fuzz_testing.md | 4 ++-- docs/testing/yaml.md | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/testing/fuzz_testing.md b/docs/testing/fuzz_testing.md index 68f08f4885c48e..7b5fd5683f612f 100644 --- a/docs/testing/fuzz_testing.md +++ b/docs/testing/fuzz_testing.md @@ -79,10 +79,10 @@ for an example of a simple fuzz test. - Another example: [src/setup_payload/tests/BUILD.gn](https://github.com/project-chip/connectedhomeip/blob/b367512f519e5e109346e81a0d84fd85cd9192f7/src/setup_payload/tests/BUILD.gn#L43) -- Add to `src/BUILD.gn` +- Add to `${chip_root}/BUILD.gn` - Add the Fuzzing Target in this part of the code : - [src/BUILD.gn](https://github.com/project-chip/connectedhomeip/blob/b367512f519e5e109346e81a0d84fd85cd9192f7/BUILD.gn#L52) + [\${chip_root}/BUILD.gn](https://github.com/project-chip/connectedhomeip/blob/b367512f519e5e109346e81a0d84fd85cd9192f7/BUILD.gn#L52) - Add Fuzzing Target like that diff --git a/docs/testing/yaml.md b/docs/testing/yaml.md index e3736d6272f1ab..0adeca43e55c1d 100644 --- a/docs/testing/yaml.md +++ b/docs/testing/yaml.md @@ -330,12 +330,11 @@ or bootstrap.sh should be used for for the first setup, activate.sh may be used for subsequent setups as it is faster. -Next build the python wheels and create a venv (called `py` here, but any name -may be used) +Next build the python wheels and create a venv ``` ./scripts/build_python.sh -i out/python_env -source py/bin/activate +source out/python_env/bin/activate ``` Compile chip-tool: From e7b0989a96e7c9d93fab6cad93d658754aaafc02 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Mon, 2 Dec 2024 16:03:41 +0100 Subject: [PATCH 06/74] Stop shell read loop if the input stream was closed (#36675) --- src/lib/shell/MainLoopDefault.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lib/shell/MainLoopDefault.cpp b/src/lib/shell/MainLoopDefault.cpp index 6a3a6b300b53f3..30e748836b473c 100644 --- a/src/lib/shell/MainLoopDefault.cpp +++ b/src/lib/shell/MainLoopDefault.cpp @@ -57,6 +57,15 @@ size_t ReadLine(char * buffer, size_t max) break; } + // Stop the loop if the input stream is closed. + if (ret == 0) + { + if (line_sz > 0) + // Return current buffer if it is not empty. + buffer[line_sz++] = '\0'; + break; + } + if (ret != 1) continue; From 4c69001a0acef9a77c5963708ecc67262c2b26bd Mon Sep 17 00:00:00 2001 From: BoB13-Matter Date: Tue, 3 Dec 2024 00:26:18 +0900 Subject: [PATCH 07/74] Ensure SYSTEM_STATS_INCREMENT only on successful Timer allocation in SystemTimer.h (#36690) * Fix: Ensure SYSTEM_STATS_INCREMENT only on successful Timer allocation * Update SystemTimer.h --- src/system/SystemTimer.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/system/SystemTimer.h b/src/system/SystemTimer.h index 698be028ce029a..99c3d8620f194f 100644 --- a/src/system/SystemTimer.h +++ b/src/system/SystemTimer.h @@ -204,7 +204,11 @@ class TimerPool Timer * Create(Layer & systemLayer, System::Clock::Timestamp awakenTime, TimerCompleteCallback onComplete, void * appState) { Timer * timer = mTimerPool.CreateObject(systemLayer, awakenTime, onComplete, appState); - SYSTEM_STATS_INCREMENT(Stats::kSystemLayer_NumTimers); + if (timer != nullptr) + { + SYSTEM_STATS_INCREMENT(Stats::kSystemLayer_NumTimers); + } + return timer; } From a3a443a7d15552d133f8ddb7b1ffd6d10496b081 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Mon, 2 Dec 2024 13:58:35 -0500 Subject: [PATCH 08/74] Disable chef build of tempcontrol cabinet. (#36694) --- .../temperature-control/static-supported-temperature-levels.cpp | 1 + integrations/cloudbuild/chef.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/chef/common/clusters/temperature-control/static-supported-temperature-levels.cpp b/examples/chef/common/clusters/temperature-control/static-supported-temperature-levels.cpp index 045825d8faf312..7ebbd0f8132487 100644 --- a/examples/chef/common/clusters/temperature-control/static-supported-temperature-levels.cpp +++ b/examples/chef/common/clusters/temperature-control/static-supported-temperature-levels.cpp @@ -21,6 +21,7 @@ #ifdef MATTER_DM_PLUGIN_TEMPERATURE_CONTROL_SERVER #include "static-supported-temperature-levels.h" #include +#include using namespace chip; using namespace chip::app::Clusters; diff --git a/integrations/cloudbuild/chef.yaml b/integrations/cloudbuild/chef.yaml index 238b47b0fc5fb2..fd8543ee2d4280 100644 --- a/integrations/cloudbuild/chef.yaml +++ b/integrations/cloudbuild/chef.yaml @@ -29,7 +29,7 @@ steps: args: - >- perl -i -pe 's/^gdbgui==/# gdbgui==/' /opt/espressif/esp-idf/requirements.txt && - ./examples/chef/chef.py --build_all --build_exclude noip + ./examples/chef/chef.py --build_all --build_exclude "noip|temperaturecontrolledcabinet" id: CompileAll waitFor: - Bootstrap From 2bc325178516defcf6706e5df793af1b55645fe1 Mon Sep 17 00:00:00 2001 From: C Freeman Date: Tue, 3 Dec 2024 02:49:58 -0500 Subject: [PATCH 09/74] Bridge app: remove binding client (#36697) A binding client means that this device would be reaching out and writing to the binding cluster on another endpoint, which is likely NOT what was intended here since it doesn't do that. The current app now shows no clusters listed in the client list on any cluster (from device dump). --- .../bridge-common/bridge-app.matter | 22 ------------------- .../bridge-app/bridge-common/bridge-app.zap | 8 ------- 2 files changed, 30 deletions(-) diff --git a/examples/bridge-app/bridge-common/bridge-app.matter b/examples/bridge-app/bridge-common/bridge-app.matter index 5979751c01b3b7..26a16622741c6c 100644 --- a/examples/bridge-app/bridge-common/bridge-app.matter +++ b/examples/bridge-app/bridge-common/bridge-app.matter @@ -521,27 +521,6 @@ cluster Descriptor = 29 { readonly attribute int16u clusterRevision = 65533; } -/** The Binding Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for supporting the binding table. */ -cluster Binding = 30 { - revision 1; // NOTE: Default/not specifically set - - fabric_scoped struct TargetStruct { - optional node_id node = 1; - optional group_id group = 2; - optional endpoint_no endpoint = 3; - optional cluster_id cluster = 4; - fabric_idx fabricIndex = 254; - } - - attribute access(write: manage) TargetStruct binding[] = 0; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute event_id eventList[] = 65530; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; -} - /** The Access Control Cluster exposes a data model view of a Node's Access Control List (ACL), which codifies the rules used to manage and enforce Access Control for the Node's endpoints and their associated @@ -2496,7 +2475,6 @@ endpoint 0 { endpoint 1 { device type ma_aggregator = 14, version 1; - binding cluster Binding; server cluster Identify { ram attribute identifyTime default = 0x0; diff --git a/examples/bridge-app/bridge-common/bridge-app.zap b/examples/bridge-app/bridge-common/bridge-app.zap index 8c5882fbd4dbd3..3dc8efff76af5a 100644 --- a/examples/bridge-app/bridge-common/bridge-app.zap +++ b/examples/bridge-app/bridge-common/bridge-app.zap @@ -4713,14 +4713,6 @@ } ] }, - { - "name": "Binding", - "code": 30, - "mfgCode": null, - "define": "BINDING_CLUSTER", - "side": "client", - "enabled": 1 - }, { "name": "Actions", "code": 37, From c4632a6363b7174f0fdd6219cf97309b4c35aac3 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Tue, 3 Dec 2024 10:38:17 -0500 Subject: [PATCH 10/74] Some code updates on composition logic after #36493 (#36681) * Remove some stutterning from endpoint composition (pattern repeated) * Remove some explitic bits, add comments about what endpoint composition patterns are * Restyle * Restyled by clang-format * Fix typo --------- Co-authored-by: Restyled.io --- src/app/clusters/descriptor/descriptor.cpp | 5 ++-- .../CodegenDataModelProvider.cpp | 4 +-- .../tests/TestCodegenModelViaMocks.cpp | 28 +++++++++---------- src/app/data-model-provider/MetadataTypes.h | 19 +++++++++---- 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/app/clusters/descriptor/descriptor.cpp b/src/app/clusters/descriptor/descriptor.cpp index 409240e66a8b9e..7d8854bca1fb5f 100644 --- a/src/app/clusters/descriptor/descriptor.cpp +++ b/src/app/clusters/descriptor/descriptor.cpp @@ -105,8 +105,7 @@ CHIP_ERROR DescriptorAttrAccess::ReadPartsAttribute(EndpointId endpoint, Attribu return CHIP_NO_ERROR; }); } - else if (endpointInfo.has_value() && - endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kFullFamilyPattern) + else if (endpointInfo.has_value() && endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kFullFamily) { err = aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR { auto endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstEndpoint(); @@ -134,7 +133,7 @@ CHIP_ERROR DescriptorAttrAccess::ReadPartsAttribute(EndpointId endpoint, Attribu return CHIP_NO_ERROR; }); } - else if (endpointInfo.has_value() && endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kTreePattern) + else if (endpointInfo.has_value() && endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kTree) { err = aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR { auto endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstEndpoint(); diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp index 4eae3de1e247db..f4e1190d614b45 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp @@ -321,11 +321,11 @@ std::optional GetEndpointInfoAtIndex(uint16_t endpointI EndpointId parent = emberAfParentEndpointFromIndex(endpointIndex); if (GetCompositionForEndpointIndex(endpointIndex) == EndpointComposition::kFullFamily) { - return DataModel::EndpointInfo(parent, DataModel::EndpointCompositionPattern::kFullFamilyPattern); + return DataModel::EndpointInfo(parent, DataModel::EndpointCompositionPattern::kFullFamily); } if (GetCompositionForEndpointIndex(endpointIndex) == EndpointComposition::kTree) { - return DataModel::EndpointInfo(parent, DataModel::EndpointCompositionPattern::kTreePattern); + return DataModel::EndpointInfo(parent, DataModel::EndpointCompositionPattern::kTree); } return std::nullopt; } diff --git a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp index 50d8ec67df3deb..5f47f1abda0498 100644 --- a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp +++ b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp @@ -898,15 +898,15 @@ TEST(TestCodegenModelViaMocks, IterateOverEndpoints) EndpointEntry ep = model.FirstEndpoint(); EXPECT_EQ(ep.id, kMockEndpoint1); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); ep = model.NextEndpoint(kMockEndpoint1); EXPECT_EQ(ep.id, kMockEndpoint2); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTree); ep = model.NextEndpoint(kMockEndpoint2); EXPECT_EQ(ep.id, kMockEndpoint3); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); ep = model.NextEndpoint(kMockEndpoint3); EXPECT_EQ(ep.id, kInvalidEndpointId); @@ -914,27 +914,27 @@ TEST(TestCodegenModelViaMocks, IterateOverEndpoints) ep = model.NextEndpoint(kMockEndpoint2); EXPECT_EQ(ep.id, kMockEndpoint3); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); ep = model.NextEndpoint(kMockEndpoint2); EXPECT_EQ(ep.id, kMockEndpoint3); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); ep = model.NextEndpoint(kMockEndpoint1); EXPECT_EQ(ep.id, kMockEndpoint2); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTree); ep = model.NextEndpoint(kMockEndpoint1); EXPECT_EQ(ep.id, kMockEndpoint2); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTree); ep = model.NextEndpoint(kMockEndpoint2); EXPECT_EQ(ep.id, kMockEndpoint3); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); ep = model.NextEndpoint(kMockEndpoint1); EXPECT_EQ(ep.id, kMockEndpoint2); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTree); ep = model.NextEndpoint(kMockEndpoint3); EXPECT_EQ(ep.id, kInvalidEndpointId); ep = model.NextEndpoint(kMockEndpoint3); @@ -942,11 +942,11 @@ TEST(TestCodegenModelViaMocks, IterateOverEndpoints) ep = model.FirstEndpoint(); EXPECT_EQ(ep.id, kMockEndpoint1); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); ep = model.FirstEndpoint(); EXPECT_EQ(ep.id, kMockEndpoint1); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); // invalid endpoiunts ep = model.NextEndpoint(kInvalidEndpointId); @@ -964,17 +964,17 @@ TEST(TestCodegenModelViaMocks, GetEndpointInfo) ASSERT_TRUE(info.has_value()); EXPECT_EQ(info->parentId, kInvalidEndpointId); // NOLINT(bugprone-unchecked-optional-access) EXPECT_EQ(info->compositionPattern, // NOLINT(bugprone-unchecked-optional-access) - EndpointCompositionPattern::kFullFamilyPattern); + EndpointCompositionPattern::kFullFamily); info = model.GetEndpointInfo(kMockEndpoint2); ASSERT_TRUE(info.has_value()); EXPECT_EQ(info->parentId, kInvalidEndpointId); // NOLINT(bugprone-unchecked-optional-access) EXPECT_EQ(info->compositionPattern, // NOLINT(bugprone-unchecked-optional-access) - EndpointCompositionPattern::kTreePattern); + EndpointCompositionPattern::kTree); info = model.GetEndpointInfo(kMockEndpoint3); ASSERT_TRUE(info.has_value()); EXPECT_EQ(info->parentId, kInvalidEndpointId); // NOLINT(bugprone-unchecked-optional-access) EXPECT_EQ(info->compositionPattern, // NOLINT(bugprone-unchecked-optional-access) - EndpointCompositionPattern::kFullFamilyPattern); + EndpointCompositionPattern::kFullFamily); // invalid endpoiunts info = model.GetEndpointInfo(kInvalidEndpointId); diff --git a/src/app/data-model-provider/MetadataTypes.h b/src/app/data-model-provider/MetadataTypes.h index ab9005412e5261..8f5a6cbf5a5af7 100644 --- a/src/app/data-model-provider/MetadataTypes.h +++ b/src/app/data-model-provider/MetadataTypes.h @@ -33,10 +33,20 @@ namespace chip { namespace app { namespace DataModel { +/// Represents various endpoint composition patters as defined in the spec +/// as `9.2.1. Endpoint Composition patterns` enum class EndpointCompositionPattern : uint8_t { - kTreePattern = 0x1, - kFullFamilyPattern = 0x2, + // Tree pattern supports a general tree of endpoints. Commonly used for + // device types that support physical device composition (e.g. Refrigerator) + kTree = 0x1, + + // A full-family pattern is a list fo all descendant endpoints, with no + // imposed hierarchy. + // + // For example the Root Node and Aggregator device types use the full-familiy + // pattern, as defined in their device type specification + kFullFamily = 0x2, }; struct EndpointInfo @@ -46,9 +56,8 @@ struct EndpointInfo EndpointId parentId; EndpointCompositionPattern compositionPattern; - explicit EndpointInfo(EndpointId parent) : parentId(parent), compositionPattern(EndpointCompositionPattern::kFullFamilyPattern) - {} - explicit EndpointInfo(EndpointId parent, EndpointCompositionPattern pattern) : parentId(parent), compositionPattern(pattern) {} + explicit EndpointInfo(EndpointId parent) : parentId(parent), compositionPattern(EndpointCompositionPattern::kFullFamily) {} + EndpointInfo(EndpointId parent, EndpointCompositionPattern pattern) : parentId(parent), compositionPattern(pattern) {} }; struct EndpointEntry From 9a1d48c3e0471b84297ca6f83a15cf07d3863a0a Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Tue, 3 Dec 2024 18:38:01 +0100 Subject: [PATCH 11/74] [Fabric-Sync] Fix deadlock when removing device (#36706) * [Fabric-Sync] Fix deadlock when removing device * Add assertChipStackLockedByCurrentThread just in case --- .../fabric-sync/bridge/src/BridgedDeviceManager.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp b/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp index 0ead453572aa4f..5057f5f68f80ef 100644 --- a/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp +++ b/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp @@ -245,12 +245,13 @@ std::optional BridgedDeviceManager::AddDeviceEndpoint(std::unique_ptr< int BridgedDeviceManager::RemoveDeviceEndpoint(BridgedDevice * dev) { + assertChipStackLockedByCurrentThread(); + uint8_t index = 0; while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) { if (mDevices[index].get() == dev) { - DeviceLayer::StackLock lock; // Silence complaints about unused ep when progress logging // disabled. [[maybe_unused]] EndpointId ep = emberAfClearDynamicEndpoint(index); @@ -266,6 +267,8 @@ int BridgedDeviceManager::RemoveDeviceEndpoint(BridgedDevice * dev) BridgedDevice * BridgedDeviceManager::GetDevice(chip::EndpointId endpointId) const { + assertChipStackLockedByCurrentThread(); + for (uint8_t index = 0; index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; ++index) { if (mDevices[index] && mDevices[index]->GetEndpointId() == endpointId) @@ -304,6 +307,8 @@ std::string BridgedDeviceManager::GenerateUniqueId() BridgedDevice * BridgedDeviceManager::GetDeviceByUniqueId(const std::string & id) { + assertChipStackLockedByCurrentThread(); + for (uint8_t index = 0; index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; ++index) { if (mDevices[index] && mDevices[index]->GetBridgedAttributes().uniqueId == id) @@ -316,6 +321,8 @@ BridgedDevice * BridgedDeviceManager::GetDeviceByUniqueId(const std::string & id BridgedDevice * BridgedDeviceManager::GetDeviceByScopedNodeId(chip::ScopedNodeId scopedNodeId) const { + assertChipStackLockedByCurrentThread(); + for (uint8_t index = 0; index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; ++index) { if (mDevices[index] && mDevices[index]->GetScopedNodeId() == scopedNodeId) @@ -328,11 +335,12 @@ BridgedDevice * BridgedDeviceManager::GetDeviceByScopedNodeId(chip::ScopedNodeId std::optional BridgedDeviceManager::RemoveDeviceByScopedNodeId(chip::ScopedNodeId scopedNodeId) { + assertChipStackLockedByCurrentThread(); + for (uint16_t index = 0; index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; ++index) { if (mDevices[index] && mDevices[index]->GetScopedNodeId() == scopedNodeId) { - DeviceLayer::StackLock lock; EndpointId ep = emberAfClearDynamicEndpoint(index); mDevices[index] = nullptr; ChipLogProgress(NotSpecified, "Removed device with Id=[%d:0x" ChipLogFormatX64 "] from dynamic endpoint %d (index=%d)", From 9e85e85d09184b5813d5314e25e5435460d22c3a Mon Sep 17 00:00:00 2001 From: arun-silabs <141724790+arun-silabs@users.noreply.github.com> Date: Tue, 3 Dec 2024 23:50:02 +0530 Subject: [PATCH 12/74] FanControl: modify percentSetting/percentSpeedSetting return value in case NULL is written (match spec) (#36242) * Modified return value as per spec * Modified return value for speedSetting attribute * Updated test suite with return value. --- src/app/clusters/fan-control-server/fan-control-server.cpp | 4 ++-- src/app/tests/suites/TestFanControl.yaml | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/app/clusters/fan-control-server/fan-control-server.cpp b/src/app/clusters/fan-control-server/fan-control-server.cpp index 2c30c9c6cdfa70..9767dc92464797 100644 --- a/src/app/clusters/fan-control-server/fan-control-server.cpp +++ b/src/app/clusters/fan-control-server/fan-control-server.cpp @@ -212,7 +212,7 @@ MatterFanControlClusterServerPreAttributeChangedCallback(const ConcreteAttribute } else { - res = Status::WriteIgnored; + res = Status::InvalidInState; } } else @@ -252,7 +252,7 @@ MatterFanControlClusterServerPreAttributeChangedCallback(const ConcreteAttribute } else { - res = Status::WriteIgnored; + res = Status::InvalidInState; } } else diff --git a/src/app/tests/suites/TestFanControl.yaml b/src/app/tests/suites/TestFanControl.yaml index 92fca4f2a6e253..663bdf9e641db5 100644 --- a/src/app/tests/suites/TestFanControl.yaml +++ b/src/app/tests/suites/TestFanControl.yaml @@ -69,6 +69,8 @@ tests: attribute: "PercentSetting" arguments: value: null + response: + error: INVALID_IN_STATE - label: "Read back percent setting" command: "readAttribute" @@ -105,6 +107,8 @@ tests: attribute: "SpeedSetting" arguments: value: null + response: + error: INVALID_IN_STATE - label: "Read back speed setting" command: "readAttribute" From 8cd305004bc78114b3ef21a7b496ae6bb47b6d46 Mon Sep 17 00:00:00 2001 From: BoB13-Matter Date: Wed, 4 Dec 2024 06:43:49 +0900 Subject: [PATCH 13/74] Fix small typo in DataModelLogger-src.zapt (#36702) * Fix small typo in DataModelLogger-src.zapt * Update DataModelLogger.cpp --- examples/chip-tool/templates/logging/DataModelLogger-src.zapt | 2 +- .../chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/chip-tool/templates/logging/DataModelLogger-src.zapt b/examples/chip-tool/templates/logging/DataModelLogger-src.zapt index cbce6c27abf767..d22e1afb078067 100644 --- a/examples/chip-tool/templates/logging/DataModelLogger-src.zapt +++ b/examples/chip-tool/templates/logging/DataModelLogger-src.zapt @@ -100,7 +100,7 @@ CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributeP default: break; } - ChipLogProgress(chipTool, " Don't know how to log atribute value"); + ChipLogProgress(chipTool, " Don't know how to log attribute value"); return CHIP_NO_ERROR; } diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp index 1ea513ea1d3f95..9e44b001a17247 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp @@ -19484,7 +19484,7 @@ CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributeP default: break; } - ChipLogProgress(chipTool, " Don't know how to log atribute value"); + ChipLogProgress(chipTool, " Don't know how to log attribute value"); return CHIP_NO_ERROR; } From 4cf28abd3a1ed2f6f754c66990ef932432fa1f19 Mon Sep 17 00:00:00 2001 From: Kiel Oleson Date: Tue, 3 Dec 2024 14:55:02 -0800 Subject: [PATCH 14/74] [Darwin] Framework diagnostics at startup (#36696) * add script to make git commit SHA of build available to framework via derived header * trigger diagnostic log at framework init * enumerate derived output file --- src/darwin/Framework/CHIP/MTRFramework.mm | 3 ++ .../Framework/CHIP/MTRFrameworkDiagnostics.h | 17 +++++++++++ .../Framework/CHIP/MTRFrameworkDiagnostics.mm | 24 ++++++++++++++++ .../Matter.xcodeproj/project.pbxproj | 28 +++++++++++++++++++ 4 files changed, 72 insertions(+) create mode 100644 src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.h create mode 100644 src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.mm diff --git a/src/darwin/Framework/CHIP/MTRFramework.mm b/src/darwin/Framework/CHIP/MTRFramework.mm index e6a0e672955be3..49c9b7ee02ef76 100644 --- a/src/darwin/Framework/CHIP/MTRFramework.mm +++ b/src/darwin/Framework/CHIP/MTRFramework.mm @@ -15,6 +15,7 @@ */ #import "MTRFramework.h" +#import "MTRFrameworkDiagnostics.h" #include #include @@ -34,5 +35,7 @@ void MTRFrameworkInit() // Suppress CHIP logging until we actually need it for redirection // (see MTRSetLogCallback()). Logging to os_log is always enabled. chip::Logging::SetLogFilter(chip::Logging::kLogCategory_None); + + MTRFrameworkInitDiagnosticLog(); }); } diff --git a/src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.h b/src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.h new file mode 100644 index 00000000000000..57a90e3f95dd38 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +void MTRFrameworkInitDiagnosticLog(); diff --git a/src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.mm b/src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.mm new file mode 100644 index 00000000000000..0cf93dc5b4daf4 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.mm @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#include "git_commit_sha.h" + +#import "MTRLogging_Internal.h" + +void MTRFrameworkInitDiagnosticLog() +{ + MTR_LOG("Matter Framework Init (git: %s)", GIT_COMMIT_SHA); +} diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index 13f0eb8e203e7b..8510fc3456fed0 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -331,6 +331,8 @@ 99C65E10267282F1003402F6 /* MTRControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 99C65E0F267282F1003402F6 /* MTRControllerTests.m */; }; 99D466E12798936D0089A18F /* MTRCommissioningParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 99D466E02798936D0089A18F /* MTRCommissioningParameters.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9B0484F52C701154006C2D5F /* MTRDeviceController_Concrete.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B0484F42C701154006C2D5F /* MTRDeviceController_Concrete.h */; }; + 9B1728F02CFE573C00825030 /* MTRFrameworkDiagnostics.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B1728EF2CFE573600825030 /* MTRFrameworkDiagnostics.h */; }; + 9B1728F22CFE574600825030 /* MTRFrameworkDiagnostics.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B1728F12CFE574000825030 /* MTRFrameworkDiagnostics.mm */; }; 9B231B042C62EF650030EB37 /* (null) in Headers */ = {isa = PBXBuildFile; }; 9B231B052C62EF650030EB37 /* MTRDeviceController_Concrete.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B231B032C62EF650030EB37 /* MTRDeviceController_Concrete.mm */; }; 9B5CCB592C6E6FD3009DD99B /* MTRDeviceController_XPC_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B5CCB582C6E6FD3009DD99B /* MTRDeviceController_XPC_Internal.h */; }; @@ -811,6 +813,8 @@ 99C65E0F267282F1003402F6 /* MTRControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MTRControllerTests.m; sourceTree = ""; }; 99D466E02798936D0089A18F /* MTRCommissioningParameters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRCommissioningParameters.h; sourceTree = ""; }; 9B0484F42C701154006C2D5F /* MTRDeviceController_Concrete.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDeviceController_Concrete.h; sourceTree = ""; }; + 9B1728EF2CFE573600825030 /* MTRFrameworkDiagnostics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRFrameworkDiagnostics.h; sourceTree = ""; }; + 9B1728F12CFE574000825030 /* MTRFrameworkDiagnostics.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRFrameworkDiagnostics.mm; sourceTree = ""; }; 9B231B032C62EF650030EB37 /* MTRDeviceController_Concrete.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRDeviceController_Concrete.mm; sourceTree = ""; }; 9B5CCB582C6E6FD3009DD99B /* MTRDeviceController_XPC_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDeviceController_XPC_Internal.h; sourceTree = ""; }; 9B5CCB5A2C6EC890009DD99B /* MTRDevice_XPC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDevice_XPC.h; sourceTree = ""; }; @@ -1514,6 +1518,8 @@ 754F3DF327FBB94B00E60580 /* MTREventTLVValueDecoder_Internal.h */, 515C1C6E284F9FFB00A48F0C /* MTRFramework.h */, 515C1C6D284F9FFB00A48F0C /* MTRFramework.mm */, + 9B1728EF2CFE573600825030 /* MTRFrameworkDiagnostics.h */, + 9B1728F12CFE574000825030 /* MTRFrameworkDiagnostics.mm */, 998F286C26D55E10001846C6 /* MTRKeypair.h */, 3DECCB6F2934AC1C00585AEC /* MTRLogging.h */, 991DC08A247704DC00C13860 /* MTRLogging_Internal.h */, @@ -1844,6 +1850,7 @@ 5178E6822AE098520069DF72 /* MTRCommissionableBrowserResult_Internal.h in Headers */, 516415FD2B6ACA8300D5CE11 /* MTRServerAccessControl.h in Headers */, 3CF134AB289D8DF70017A19E /* MTRDeviceAttestationInfo.h in Headers */, + 9B1728F02CFE573C00825030 /* MTRFrameworkDiagnostics.h in Headers */, B2E0D7B2245B0B5C003C5B48 /* MTRManualSetupPayloadParser.h in Headers */, 5109E9C02CCAD64F0006884B /* MTRDeviceDataValidation.h in Headers */, 3CF134A7289D8ADA0017A19E /* MTRCSRInfo.h in Headers */, @@ -1946,6 +1953,7 @@ isa = PBXNativeTarget; buildConfigurationList = B20252A12459E34F00F97062 /* Build configuration list for PBXNativeTarget "Matter" */; buildPhases = ( + 9B7838562CFE3AE600FB04C4 /* Acquire git revision info */, 0C40A67D246C9AC700885C81 /* Run GN Build (chip_xcode_build_connector) */, B20252882459E34F00F97062 /* Headers */, B20252892459E34F00F97062 /* Sources */, @@ -2059,6 +2067,25 @@ shellPath = /bin/sh; shellScript = "./chip_xcode_build_connector.sh\n"; }; + 9B7838562CFE3AE600FB04C4 /* Acquire git revision info */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Acquire git revision info"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/git_commit_sha.h", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "GIT_COMMIT_SHA=$(git rev-parse --short HEAD)\n\n# Create a temporary header file to hold the commit SHA\ntmp_header_path=\"${DERIVED_FILES_DIR}/git_commit_sha.h\"\ncat << EOF > \"$tmp_header_path\"\n#ifndef GIT_COMMIT_SHA_H\n#define GIT_COMMIT_SHA_H\n\n#define GIT_COMMIT_SHA \"${GIT_COMMIT_SHA}\"\n\n#endif /* GIT_COMMIT_SHA_H */\nEOF\n\necho \"git sha available in ${DERIVED_FILES_DIR}/git_commit_sha.h\"\n"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -2198,6 +2225,7 @@ AF5F90FF2878D351005503FA /* MTROTAProviderDelegateBridge.mm in Sources */, 516415FF2B6B132200D5CE11 /* DataModelHandler.cpp in Sources */, 75139A6F2B7FE5E900E3A919 /* MTRDeviceControllerLocalTestStorage.mm in Sources */, + 9B1728F22CFE574600825030 /* MTRFrameworkDiagnostics.mm in Sources */, 51E95DFC2A78443C00A434F0 /* MTRSessionResumptionStorageBridge.mm in Sources */, 7534F12828BFF20300390851 /* MTRDeviceAttestationDelegate.mm in Sources */, B4C8E6B72B3453AD00FCD54D /* MTRDiagnosticLogsDownloader.mm in Sources */, From 0495a4eab31e12bba0f099fed15a83dc84ebb953 Mon Sep 17 00:00:00 2001 From: C Freeman Date: Tue, 3 Dec 2024 18:24:49 -0500 Subject: [PATCH 15/74] Python testing: Update commissioning window API (#36669) * Python testing: Update commissioning window API - add some defaults to make this easier to use - change the name to match the other methods in the class * Fix API for new test --- src/python_testing/TC_ACE_1_5.py | 2 +- src/python_testing/TC_BRBINFO_4_1.py | 2 +- src/python_testing/TC_CADMIN_1_19.py | 4 ++-- src/python_testing/TC_CCTRL_2_2.py | 2 +- src/python_testing/TC_OPCREDS_3_4.py | 2 +- .../chip/testing/matter_testing.py | 10 +++++----- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/python_testing/TC_ACE_1_5.py b/src/python_testing/TC_ACE_1_5.py index 15c7380d23cff9..9bcd92f81e5f6d 100644 --- a/src/python_testing/TC_ACE_1_5.py +++ b/src/python_testing/TC_ACE_1_5.py @@ -71,7 +71,7 @@ async def test_TC_ACE_1_5(self): self.th2 = new_fabric_admin.NewController(nodeId=TH2_nodeid, paaTrustStorePath=str(self.matter_test_config.paa_trust_store_path)) - params = await self.openCommissioningWindow(self.th1, self.dut_node_id) + params = await self.open_commissioning_window(self.th1, self.dut_node_id) self.print_step(2, "TH1 opens the commissioning window on the DUT") await self.th2.CommissionOnNetwork( diff --git a/src/python_testing/TC_BRBINFO_4_1.py b/src/python_testing/TC_BRBINFO_4_1.py index f5eeec33449589..8c929d39b94f09 100644 --- a/src/python_testing/TC_BRBINFO_4_1.py +++ b/src/python_testing/TC_BRBINFO_4_1.py @@ -189,7 +189,7 @@ async def setup_class(self): filter=self.th_icd_server_discriminator) logging.info("Commissioning of ICD to fabric two (DUT)") - params = await self.openCommissioningWindow(dev_ctrl=self.default_controller, node_id=self.icd_nodeid) + params = await self.open_commissioning_window(dev_ctrl=self.default_controller, node_id=self.icd_nodeid) if not self.is_pics_sdk_ci_only: self._ask_for_vendor_commissioning_ux_operation( diff --git a/src/python_testing/TC_CADMIN_1_19.py b/src/python_testing/TC_CADMIN_1_19.py index 5ec3da867da6f1..90a3d676b7043d 100644 --- a/src/python_testing/TC_CADMIN_1_19.py +++ b/src/python_testing/TC_CADMIN_1_19.py @@ -111,7 +111,7 @@ async def test_TC_CADMIN_1_19(self): self.current_step_index = 4 self.step("4a") - params = await self.openCommissioningWindow(dev_ctrl=self.th1, timeout=self.max_window_duration, node_id=self.dut_node_id) + params = await self.open_commissioning_window(dev_ctrl=self.th1, timeout=self.max_window_duration, node_id=self.dut_node_id) self.step("4b") fids_ca_dir[fid] = self.certificate_authority_manager.NewCertificateAuthority() @@ -128,7 +128,7 @@ async def test_TC_CADMIN_1_19(self): asserts.assert_equal(current_fabrics, max_fabrics, "Expected number of fabrics not correct") self.step(6) - params = await self.openCommissioningWindow(dev_ctrl=self.th1, node_id=self.dut_node_id) + params = await self.open_commissioning_window(dev_ctrl=self.th1, node_id=self.dut_node_id) self.step(7) # TH creates a controller on a new fabric and attempts to commission DUT_CE using that controller diff --git a/src/python_testing/TC_CCTRL_2_2.py b/src/python_testing/TC_CCTRL_2_2.py index 1bc403a7e48031..3f60fd9e382bac 100644 --- a/src/python_testing/TC_CCTRL_2_2.py +++ b/src/python_testing/TC_CCTRL_2_2.py @@ -170,7 +170,7 @@ async def test_TC_CCTRL_2_2(self): asserts.assert_equal(e.status, Status.Failure, "Incorrect error returned") self.step(6) - params = await self.openCommissioningWindow(dev_ctrl=self.default_controller, node_id=self.dut_node_id) + params = await self.open_commissioning_window(dev_ctrl=self.default_controller, node_id=self.dut_node_id) self.step(7) pase_nodeid = self.dut_node_id + 1 await self.default_controller.FindOrEstablishPASESession(setupCode=params.commissioningParameters.setupQRCode, nodeid=pase_nodeid) diff --git a/src/python_testing/TC_OPCREDS_3_4.py b/src/python_testing/TC_OPCREDS_3_4.py index e2657ba1604815..c13f1ced756ab8 100644 --- a/src/python_testing/TC_OPCREDS_3_4.py +++ b/src/python_testing/TC_OPCREDS_3_4.py @@ -273,7 +273,7 @@ async def test_TC_OPCREDS_3_4(self): "Failure status returned from arm failsafe") self.step(22) - resp = await self.openCommissioningWindow(self.default_controller, self.dut_node_id) + resp = await self.open_commissioning_window() self.step(23) await self.default_controller.FindOrEstablishPASESession(setupCode=resp.commissioningParameters.setupQRCode, nodeid=self.dut_node_id) diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py index a88b57e6028e8c..e5bdf2b3be3e6b 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py @@ -1141,8 +1141,12 @@ def check_pics(self, pics_key: str) -> bool: def is_pics_sdk_ci_only(self) -> bool: return self.check_pics('PICS_SDK_CI_ONLY') - async def openCommissioningWindow(self, dev_ctrl: ChipDeviceCtrl, node_id: int, timeout: int = 900) -> CustomCommissioningParameters: + async def open_commissioning_window(self, dev_ctrl: Optional[ChipDeviceCtrl] = None, node_id: Optional[int] = None, timeout: int = 900) -> CustomCommissioningParameters: rnd_discriminator = random.randint(0, 4095) + if dev_ctrl is None: + dev_ctrl = self.default_controller + if node_id is None: + node_id = self.dut_node_id try: commissioning_params = await dev_ctrl.OpenCommissioningWindow(nodeid=node_id, timeout=timeout, iteration=1000, discriminator=rnd_discriminator, option=1) @@ -1166,7 +1170,6 @@ async def read_single_attribute_check_success( if node_id is None: node_id = self.dut_node_id if endpoint is None: - #endpoint = 0 if self.matter_test_config.endpoint is None else self.matter_test_config.endpoint endpoint = self.get_endpoint() result = await dev_ctrl.ReadAttribute(node_id, [(endpoint, attribute)], fabricFiltered=fabric_filtered) @@ -1199,7 +1202,6 @@ async def read_single_attribute_expect_error( if node_id is None: node_id = self.dut_node_id if endpoint is None: - #endpoint = 0 if self.matter_test_config.endpoint is None else self.matter_test_config.endpoint endpoint = self.get_endpoint() result = await dev_ctrl.ReadAttribute(node_id, [(endpoint, attribute)], fabricFiltered=fabric_filtered) @@ -1248,7 +1250,6 @@ async def send_single_cmd( if node_id is None: node_id = self.dut_node_id if endpoint is None: - #endpoint = 0 if self.matter_test_config.endpoint is None else self.matter_test_config.endpoint endpoint = self.get_endpoint() result = await dev_ctrl.SendCommand(nodeid=node_id, endpoint=endpoint, payload=cmd, timedRequestTimeoutMs=timedRequestTimeoutMs, @@ -1842,7 +1843,6 @@ def convert_args_to_matter_config(args: argparse.Namespace) -> MatterTestConfig: config.pics = {} if args.PICS is None else read_pics_from_file(args.PICS) config.tests = [] if args.tests is None else args.tests config.timeout = args.timeout # This can be none, we pull the default from the test if it's unspecified - #config.endpoint = args.endpoint config.endpoint = args.endpoint # This can be None, the get_endpoint function allows the tests to supply a default config.app_pid = 0 if args.app_pid is None else args.app_pid From e0fc29a8f10a37a6dde44a5c6ba1686e1b55274d Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Tue, 3 Dec 2024 15:59:27 -0800 Subject: [PATCH 16/74] [Fabric-Sync]: Convert ember-driven functions to interface functions (#36659) * [Fabric-Sync]: Convert ember-driven functions to interface functions * Address review comments --- .../linux/CommissionerControlDelegate.cpp | 6 +- .../include/CommissionerControlDelegate.h | 6 + .../include/CommissionerControlDelegate.h | 7 +- .../src/CommissionerControlDelegate.cpp | 6 +- .../commissioner-control-server.cpp | 169 +++++++++--------- .../commissioner-control-server.h | 45 ++++- src/app/common/templates/config-data.yaml | 1 + .../app-common/zap-generated/callback.h | 12 -- 8 files changed, 143 insertions(+), 109 deletions(-) diff --git a/examples/fabric-bridge-app/linux/CommissionerControlDelegate.cpp b/examples/fabric-bridge-app/linux/CommissionerControlDelegate.cpp index aa12a4274ca0f8..ca963a178dad94 100644 --- a/examples/fabric-bridge-app/linux/CommissionerControlDelegate.cpp +++ b/examples/fabric-bridge-app/linux/CommissionerControlDelegate.cpp @@ -116,7 +116,7 @@ CHIP_ERROR CommissionerControlDelegate::HandleCommissioningApprovalRequest(const mLabel.ClearValue(); } - CHIP_ERROR err = CommissionerControlServer::Instance().GenerateCommissioningRequestResultEvent(kAggregatorEndpointId, result); + CHIP_ERROR err = mCommissionerControlServer.GenerateCommissioningRequestResultEvent(kAggregatorEndpointId, result); if (err == CHIP_NO_ERROR) { @@ -228,7 +228,7 @@ CHIP_ERROR CommissionerControlInit() return CHIP_ERROR_NO_MEMORY; } - err = Clusters::CommissionerControl::CommissionerControlServer::Instance().Init(*sCommissionerControlDelegate); + err = sCommissionerControlDelegate->GetCommissionerControlServer().Init(); if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, "Initialization failed on Commissioner Control Delegate."); @@ -242,7 +242,7 @@ CHIP_ERROR CommissionerControlInit() supportedDeviceCategories.SetField(Clusters::CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization, 1); Protocols::InteractionModel::Status status = - Clusters::CommissionerControl::CommissionerControlServer::Instance().SetSupportedDeviceCategoriesValue( + sCommissionerControlDelegate->GetCommissionerControlServer().SetSupportedDeviceCategoriesValue( Clusters::CommissionerControl::kAggregatorEndpointId, supportedDeviceCategories); if (status != Protocols::InteractionModel::Status::Success) diff --git a/examples/fabric-bridge-app/linux/include/CommissionerControlDelegate.h b/examples/fabric-bridge-app/linux/include/CommissionerControlDelegate.h index 2f9e15f508cccb..a39f49066882ee 100644 --- a/examples/fabric-bridge-app/linux/include/CommissionerControlDelegate.h +++ b/examples/fabric-bridge-app/linux/include/CommissionerControlDelegate.h @@ -31,6 +31,8 @@ inline constexpr EndpointId kAggregatorEndpointId = 1; class CommissionerControlDelegate : public Delegate { public: + CommissionerControlDelegate() : mCommissionerControlServer(this, kAggregatorEndpointId, CommissionerControl::Id) {} + CHIP_ERROR HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) override; // TODO(#35627) clientNodeId should move towards ScopedNodeId. CHIP_ERROR ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId) override; @@ -39,6 +41,8 @@ class CommissionerControlDelegate : public Delegate ~CommissionerControlDelegate() = default; + CommissionerControlServer & GetCommissionerControlServer() { return mCommissionerControlServer; } + private: enum class Step : uint8_t { @@ -82,6 +86,8 @@ class CommissionerControlDelegate : public Delegate ByteSpan mPBKDFSalt; Crypto::Spake2pVerifierSerialized mPAKEPasscodeVerifierBuffer; ByteSpan mPAKEPasscodeVerifier; + + CommissionerControlServer mCommissionerControlServer; }; } // namespace CommissionerControl diff --git a/examples/fabric-sync/bridge/include/CommissionerControlDelegate.h b/examples/fabric-sync/bridge/include/CommissionerControlDelegate.h index 45a927307bb9a7..9dc4fac37423ae 100644 --- a/examples/fabric-sync/bridge/include/CommissionerControlDelegate.h +++ b/examples/fabric-sync/bridge/include/CommissionerControlDelegate.h @@ -32,7 +32,9 @@ inline constexpr EndpointId kAggregatorEndpointId = 1; class CommissionerControlDelegate : public Delegate { public: - CommissionerControlDelegate(bridge::FabricAdminDelegate * fabricAdmin) : mFabricAdmin(fabricAdmin) {} + CommissionerControlDelegate(bridge::FabricAdminDelegate * fabricAdmin) : + mFabricAdmin(fabricAdmin), mCommissionerControlServer(this, kAggregatorEndpointId, CommissionerControl::Id) + {} CHIP_ERROR HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) override; // TODO(#35627) clientNodeId should move towards ScopedNodeId. @@ -42,6 +44,8 @@ class CommissionerControlDelegate : public Delegate ~CommissionerControlDelegate() = default; + CommissionerControlServer & GetCommissionerControlServer() { return mCommissionerControlServer; } + private: enum class Step : uint8_t { @@ -87,6 +91,7 @@ class CommissionerControlDelegate : public Delegate ByteSpan mPAKEPasscodeVerifier; bridge::FabricAdminDelegate * mFabricAdmin; + CommissionerControlServer mCommissionerControlServer; }; } // namespace CommissionerControl diff --git a/examples/fabric-sync/bridge/src/CommissionerControlDelegate.cpp b/examples/fabric-sync/bridge/src/CommissionerControlDelegate.cpp index 12851177bcb212..f3b0a398d15b89 100644 --- a/examples/fabric-sync/bridge/src/CommissionerControlDelegate.cpp +++ b/examples/fabric-sync/bridge/src/CommissionerControlDelegate.cpp @@ -114,7 +114,7 @@ CHIP_ERROR CommissionerControlDelegate::HandleCommissioningApprovalRequest(const mLabel.ClearValue(); } - CHIP_ERROR err = CommissionerControlServer::Instance().GenerateCommissioningRequestResultEvent(kAggregatorEndpointId, result); + CHIP_ERROR err = mCommissionerControlServer.GenerateCommissioningRequestResultEvent(kAggregatorEndpointId, result); if (err == CHIP_NO_ERROR) { @@ -227,7 +227,7 @@ CHIP_ERROR CommissionerControlInit(bridge::FabricAdminDelegate * fabricAdmin) return CHIP_ERROR_NO_MEMORY; } - err = Clusters::CommissionerControl::CommissionerControlServer::Instance().Init(*sCommissionerControlDelegate); + err = sCommissionerControlDelegate->GetCommissionerControlServer().Init(); if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, "Initialization failed on Commissioner Control Delegate."); @@ -241,7 +241,7 @@ CHIP_ERROR CommissionerControlInit(bridge::FabricAdminDelegate * fabricAdmin) supportedDeviceCategories.SetField(Clusters::CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization, 1); Protocols::InteractionModel::Status status = - Clusters::CommissionerControl::CommissionerControlServer::Instance().SetSupportedDeviceCategoriesValue( + sCommissionerControlDelegate->GetCommissionerControlServer().SetSupportedDeviceCategoriesValue( Clusters::CommissionerControl::kAggregatorEndpointId, supportedDeviceCategories); if (status != Protocols::InteractionModel::Status::Success) diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp index ea0c9b1203f58f..9a0e91a2d0a3bd 100644 --- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp +++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp @@ -22,11 +22,11 @@ #include #include #include -#include -#include #include +#include #include #include +#include #include #include @@ -38,9 +38,9 @@ using chip::Protocols::InteractionModel::Status; namespace { -NodeId GetNodeId(const CommandHandler * commandObj) +NodeId GetNodeId(const CommandHandler & commandHandler) { - auto descriptor = commandObj->GetSubjectDescriptor(); + auto descriptor = commandHandler.GetSubjectDescriptor(); if (descriptor.authMode != Access::AuthMode::kCase) { @@ -49,7 +49,7 @@ NodeId GetNodeId(const CommandHandler * commandObj) return descriptor.subject; } -void AddReverseOpenCommissioningWindowResponse(CommandHandler * commandObj, const ConcreteCommandPath & path, +void AddReverseOpenCommissioningWindowResponse(CommandHandler & commandHandler, const ConcreteCommandPath & path, const Clusters::CommissionerControl::CommissioningWindowParams & params) { Clusters::CommissionerControl::Commands::ReverseOpenCommissioningWindow::Type response; @@ -59,30 +59,7 @@ void AddReverseOpenCommissioningWindowResponse(CommandHandler * commandObj, cons response.PAKEPasscodeVerifier = params.PAKEPasscodeVerifier; response.salt = params.salt; - commandObj->AddResponse(path, response); -} - -void RunDeferredCommissionNode(intptr_t commandArg) -{ - auto * params = reinterpret_cast(commandArg); - - Clusters::CommissionerControl::Delegate * delegate = - Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate(); - - if (delegate != nullptr) - { - CHIP_ERROR err = delegate->HandleCommissionNode(*params); - if (err != CHIP_NO_ERROR) - { - ChipLogError(Zcl, "HandleCommissionNode error: %" CHIP_ERROR_FORMAT, err.Format()); - } - } - else - { - ChipLogError(Zcl, "No delegate available for HandleCommissionNode"); - } - - delete params; + commandHandler.AddResponse(path, response); } } // namespace @@ -92,16 +69,20 @@ namespace app { namespace Clusters { namespace CommissionerControl { -CommissionerControlServer CommissionerControlServer::sInstance; +CommissionerControlServer::CommissionerControlServer(Delegate * delegate, EndpointId endpointId, ClusterId clusterId) : + CommandHandlerInterface(MakeOptional(endpointId), clusterId) +{ + mDelegate = delegate; +} -CommissionerControlServer & CommissionerControlServer::Instance() +CommissionerControlServer::~CommissionerControlServer() { - return sInstance; + CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); } -CHIP_ERROR CommissionerControlServer::Init(Delegate & delegate) +CHIP_ERROR CommissionerControlServer::Init() { - mDelegate = &delegate; + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this)); return CHIP_NO_ERROR; } @@ -146,38 +127,53 @@ CommissionerControlServer::GenerateCommissioningRequestResultEvent(EndpointId en return error; } -} // namespace CommissionerControl -} // namespace Clusters -} // namespace app -} // namespace chip +void CommissionerControlServer::InvokeCommand(HandlerContext & handlerContext) +{ + ChipLogDetail(Zcl, "CommissionerControl: InvokeCommand"); + switch (handlerContext.mRequestPath.mCommandId) + { + case Commands::RequestCommissioningApproval::Id: + ChipLogDetail(Zcl, "CommissionerControl: Entering RequestCommissioningApproval"); -bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback( - app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, - const Clusters::CommissionerControl::Commands::RequestCommissioningApproval::DecodableType & commandData) + CommandHandlerInterface::HandleCommand( + handlerContext, [this](HandlerContext & ctx, const auto & req) { HandleRequestCommissioningApproval(ctx, req); }); + break; + + case Commands::CommissionNode::Id: + ChipLogDetail(Zcl, "CommissionerControl: Entering CommissionNode"); + + CommandHandlerInterface::HandleCommand( + handlerContext, [this](HandlerContext & ctx, const auto & req) { HandleCommissionNode(ctx, req); }); + break; + } +} + +void CommissionerControlServer::HandleRequestCommissioningApproval( + HandlerContext & ctx, const Commands::RequestCommissioningApproval::DecodableType & req) { CHIP_ERROR err = CHIP_NO_ERROR; Status status = Status::Success; ChipLogProgress(Zcl, "Received command to request commissioning approval"); - auto sourceNodeId = GetNodeId(commandObj); + auto sourceNodeId = GetNodeId(ctx.mCommandHandler); // Check if the command is executed via a CASE session if (sourceNodeId == kUndefinedNodeId) { ChipLogError(Zcl, "Commissioning approval request not executed via CASE session, failing with UNSUPPORTED_ACCESS"); - commandObj->AddStatus(commandPath, Status::UnsupportedAccess); - return true; + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::UnsupportedAccess); + return; } - auto fabricIndex = commandObj->GetAccessingFabricIndex(); - auto requestId = commandData.requestID; - auto vendorId = commandData.vendorID; - auto productId = commandData.productID; + auto fabricIndex = ctx.mCommandHandler.GetAccessingFabricIndex(); + auto requestId = req.requestID; + auto vendorId = req.vendorID; + auto productId = req.productID; - // The label assigned from commandData need to be stored in CommissionerControl::Delegate which ensure that the backing buffer + // The label assigned from req need to be stored in CommissionerControl::Delegate which ensure that the backing buffer // of it has a valid lifespan during fabric sync setup process. - auto & label = commandData.label; + auto & label = req.label; // Create a CommissioningApprovalRequest struct and populate it with the command data Clusters::CommissionerControl::CommissioningApprovalRequest request = { .requestId = requestId, @@ -187,86 +183,93 @@ bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback( .fabricIndex = fabricIndex, .label = label }; - Clusters::CommissionerControl::Delegate * delegate = - Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate(); - - VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE); // Handle commissioning approval request - err = delegate->HandleCommissioningApprovalRequest(request); + err = mDelegate->HandleCommissioningApprovalRequest(request); exit: if (err != CHIP_NO_ERROR) { - ChipLogError(Zcl, "emberAfCommissionerControlClusterRequestCommissioningApprovalCallback error: %" CHIP_ERROR_FORMAT, - err.Format()); + ChipLogError(Zcl, "HandleRequestCommissioningApproval error: %" CHIP_ERROR_FORMAT, err.Format()); status = StatusIB(err).mStatus; } - commandObj->AddStatus(commandPath, status); - return true; + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); } -bool emberAfCommissionerControlClusterCommissionNodeCallback( - app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, - const Clusters::CommissionerControl::Commands::CommissionNode::DecodableType & commandData) +void CommissionerControlServer::HandleCommissionNode(HandlerContext & ctx, const Commands::CommissionNode::DecodableType & req) { CHIP_ERROR err = CHIP_NO_ERROR; ChipLogProgress(Zcl, "Received command to commission node"); - auto sourceNodeId = GetNodeId(commandObj); + auto sourceNodeId = GetNodeId(ctx.mCommandHandler); // Constraint on responseTimeoutSeconds is [30; 120] seconds - if ((commandData.responseTimeoutSeconds < 30) || (commandData.responseTimeoutSeconds > 120)) + if ((req.responseTimeoutSeconds < 30) || (req.responseTimeoutSeconds > 120)) { ChipLogError(Zcl, "Invalid responseTimeoutSeconds for CommissionNode."); - commandObj->AddStatus(commandPath, Status::ConstraintError); - return true; + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); + return; } // Check if the command is executed via a CASE session if (sourceNodeId == kUndefinedNodeId) { ChipLogError(Zcl, "Commission node request not executed via CASE session, failing with UNSUPPORTED_ACCESS"); - commandObj->AddStatus(commandPath, Status::UnsupportedAccess); - return true; + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::UnsupportedAccess); + return; } - auto requestId = commandData.requestID; - + auto requestId = req.requestID; + auto delegate = mDelegate; auto commissioningWindowParams = std::make_unique(); - Clusters::CommissionerControl::Delegate * delegate = - Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate(); - - VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE); // Validate the commission node command. - err = delegate->ValidateCommissionNodeCommand(sourceNodeId, requestId); + err = mDelegate->ValidateCommissionNodeCommand(sourceNodeId, requestId); SuccessOrExit(err); // Populate the parameters for the commissioning window - err = delegate->GetCommissioningWindowParams(*commissioningWindowParams); + err = mDelegate->GetCommissioningWindowParams(*commissioningWindowParams); SuccessOrExit(err); // Add the response for the commissioning window. - AddReverseOpenCommissioningWindowResponse(commandObj, commandPath, *commissioningWindowParams); + AddReverseOpenCommissioningWindowResponse(ctx.mCommandHandler, ctx.mRequestPath, *commissioningWindowParams); // Schedule the deferred reverse commission node task - DeviceLayer::PlatformMgr().ScheduleWork(RunDeferredCommissionNode, - reinterpret_cast(commissioningWindowParams.release())); + DeviceLayer::SystemLayer().ScheduleLambda([delegate, params = commissioningWindowParams.release()]() { + if (delegate != nullptr) + { + CHIP_ERROR error = delegate->HandleCommissionNode(*params); + if (error != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "HandleCommissionNode error: %" CHIP_ERROR_FORMAT, error.Format()); + } + } + else + { + ChipLogError(Zcl, "No delegate available for HandleCommissionNode"); + } + + delete params; + }); exit: if (err != CHIP_NO_ERROR) { - ChipLogError(Zcl, "emberAfCommissionerControlClusterCommissionNodeCallback error: %" CHIP_ERROR_FORMAT, err.Format()); - commandObj->AddStatus(commandPath, StatusIB(err).mStatus); + ChipLogError(Zcl, "HandleCommissionNode error: %" CHIP_ERROR_FORMAT, err.Format()); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, StatusIB(err).mStatus); } - - return true; } +} // namespace CommissionerControl +} // namespace Clusters +} // namespace app +} // namespace chip + void MatterCommissionerControlPluginServerInitCallback() { ChipLogProgress(Zcl, "Initializing Commissioner Control cluster."); diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.h b/src/app/clusters/commissioner-control-server/commissioner-control-server.h index 56f43620b56114..2319a71cc950a2 100644 --- a/src/app/clusters/commissioner-control-server/commissioner-control-server.h +++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.h @@ -18,6 +18,7 @@ #pragma once #include +#include namespace chip { namespace app { @@ -100,14 +101,27 @@ class Delegate virtual ~Delegate() = default; }; -class CommissionerControlServer +class CommissionerControlServer : public CommandHandlerInterface { public: - static CommissionerControlServer & Instance(); + /** + * @brief Creates a Commissioner Control cluster instance. The Init() function needs to be called for this instance + * to be registered and called by the interaction model at the appropriate times. + * @param delegate A pointer to the delegate to be used by this server. + * Note: the caller must ensure that the delegate lives throughout the instance's lifetime. + * @param endpointId The endpoint on which this cluster exists. This must match the zap configuration. + * @param clusterId The ID of the Microwave Oven Control cluster to be instantiated. + */ + CommissionerControlServer(Delegate * delegate, EndpointId endpointId, ClusterId clusterId); - CHIP_ERROR Init(Delegate & delegate); + ~CommissionerControlServer() override; - Delegate * GetDelegate() { return mDelegate; } + /** + * @brief Initialise the Commissioner Control server instance. + * This function must be called after defining an CommissionerControlServer class object. + * @return Returns an error if the CommandHandler registration fails, else returns CHIP_NO_ERROR. + */ + CHIP_ERROR Init(); Protocols::InteractionModel::Status GetSupportedDeviceCategoriesValue(EndpointId endpoint, @@ -124,10 +138,27 @@ class CommissionerControlServer const Events::CommissioningRequestResult::Type & result); private: - CommissionerControlServer() = default; - ~CommissionerControlServer() = default; + /** + * @brief Inherited from CommandHandlerInterface + */ + void InvokeCommand(HandlerContext & ctx) override; - static CommissionerControlServer sInstance; + /** + * @brief Handle Command: SetCookingParameters. + * @param ctx Returns the Interaction Model status code which was user determined in the business logic. + * If the input value is invalid, returns the Interaction Model status code of INVALID_COMMAND. + * If the operational state is not in 'Stopped', returns the Interaction Model status code of INVALID_IN_STATE. + */ + void HandleRequestCommissioningApproval(HandlerContext & ctx, + const Commands::RequestCommissioningApproval::DecodableType & req); + + /** + * @brief Handle Command: AddMoreTime. + * @param ctx Returns the Interaction Model status code which was user determined in the business logic. + * If the cook time value is out of range, returns the Interaction Model status code of CONSTRAINT_ERROR. + * If the operational state is in 'Error', returns the Interaction Model status code of INVALID_IN_STATE. + */ + void HandleCommissionNode(HandlerContext & ctx, const Commands::CommissionNode::DecodableType & req); Delegate * mDelegate = nullptr; }; diff --git a/src/app/common/templates/config-data.yaml b/src/app/common/templates/config-data.yaml index f5259748d9421c..b014f103e96fda 100644 --- a/src/app/common/templates/config-data.yaml +++ b/src/app/common/templates/config-data.yaml @@ -37,6 +37,7 @@ CommandHandlerInterfaceOnlyClusters: - Sample MEI - Microwave Oven Control - Chime + - Commissioner Control - Energy EVSE - Energy EVSE Mode - Device Energy Management diff --git a/zzz_generated/app-common/app-common/zap-generated/callback.h b/zzz_generated/app-common/app-common/zap-generated/callback.h index 1c8cccc476c6dd..b594c4cce72675 100644 --- a/zzz_generated/app-common/app-common/zap-generated/callback.h +++ b/zzz_generated/app-common/app-common/zap-generated/callback.h @@ -6906,18 +6906,6 @@ bool emberAfWebRTCTransportRequestorClusterICECandidateCallback( bool emberAfWebRTCTransportRequestorClusterEndCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::WebRTCTransportRequestor::Commands::End::DecodableType & commandData); -/** - * @brief Commissioner Control Cluster RequestCommissioningApproval Command callback (from client) - */ -bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::CommissionerControl::Commands::RequestCommissioningApproval::DecodableType & commandData); -/** - * @brief Commissioner Control Cluster CommissionNode Command callback (from client) - */ -bool emberAfCommissionerControlClusterCommissionNodeCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::CommissionerControl::Commands::CommissionNode::DecodableType & commandData); /** * @brief Unit Testing Cluster Test Command callback (from client) */ From 9fe08439dcefb0fc189400b51034acec608140fa Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Wed, 4 Dec 2024 12:57:58 +0100 Subject: [PATCH 17/74] Support for generating QR-code and manual code in Python chip binding (#36692) * Support for generating QR-code and manual code in Python chip binding * Add SetupParameters wrapper to matter testing * Migrate to SetupParameters in tests * Restyled by autopep8 * Restyled by isort * Remove unused import --------- Co-authored-by: Restyled.io --- .../python/chip/setup_payload/Generator.cpp | 71 +++++++++++++++---- .../chip/setup_payload/setup_payload.py | 22 +++++- src/python_testing/TC_MCORE_FS_1_2.py | 24 ++----- src/python_testing/TC_MCORE_FS_1_5.py | 24 ++----- .../chip/testing/matter_testing.py | 21 ++++++ 5 files changed, 115 insertions(+), 47 deletions(-) diff --git a/src/controller/python/chip/setup_payload/Generator.cpp b/src/controller/python/chip/setup_payload/Generator.cpp index 4481a404462394..442d009414290f 100644 --- a/src/controller/python/chip/setup_payload/Generator.cpp +++ b/src/controller/python/chip/setup_payload/Generator.cpp @@ -15,30 +15,30 @@ * limitations under the License. */ +#include +#include + #include +#include #include #include #include -#include -#include - using namespace chip; -extern "C" PyChipError pychip_SetupPayload_PrintOnboardingCodes(uint32_t passcode, uint16_t vendorId, uint16_t productId, - uint16_t discriminator, uint8_t customFlow, uint8_t capabilities, - uint8_t version) +namespace { + +CHIP_ERROR InitSetupPayload(SetupPayload & payload, uint32_t passcode, uint16_t vendorId, uint16_t productId, + uint16_t discriminator, uint8_t customFlow, uint8_t capabilities, uint8_t version) { - std::string QRCode; - std::string manualPairingCode; - SetupPayload payload; - RendezvousInformationFlags rendezvousFlags = RendezvousInformationFlag::kNone; payload.version = version; payload.setUpPINCode = passcode; payload.vendorID = vendorId; payload.productID = productId; payload.discriminator.SetLongValue(discriminator); + + RendezvousInformationFlags rendezvousFlags = RendezvousInformationFlag::kNone; payload.rendezvousInformation.SetValue(rendezvousFlags.SetRaw(capabilities)); switch (customFlow) @@ -54,16 +54,63 @@ extern "C" PyChipError pychip_SetupPayload_PrintOnboardingCodes(uint32_t passcod break; default: ChipLogError(SetupPayload, "Invalid Custom Flow"); - return ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT); + return CHIP_ERROR_INVALID_ARGUMENT; } - CHIP_ERROR err = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualPairingCode); + return CHIP_NO_ERROR; +} + +} // namespace + +extern "C" PyChipError pychip_SetupPayload_PrintOnboardingCodes(uint32_t passcode, uint16_t vendorId, uint16_t productId, + uint16_t discriminator, uint8_t customFlow, uint8_t capabilities, + uint8_t version) +{ + SetupPayload payload; + CHIP_ERROR err = InitSetupPayload(payload, passcode, vendorId, productId, discriminator, customFlow, capabilities, version); + VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); + + std::string manualPairingCode; + err = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualPairingCode); VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); ChipLogProgress(SetupPayload, "Manual pairing code: [%s]", manualPairingCode.c_str()); + std::string QRCode; err = QRCodeSetupPayloadGenerator(payload).payloadBase38Representation(QRCode); VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); ChipLogProgress(SetupPayload, "SetupQRCode: [%s]", QRCode.c_str()); return ToPyChipError(CHIP_NO_ERROR); } + +extern "C" PyChipError pychip_SetupPayload_GenerateQrCode(char * output, size_t size, uint32_t passcode, uint16_t vendorId, + uint16_t productId, uint16_t discriminator, uint8_t customFlow, + uint8_t capabilities, uint8_t version) +{ + SetupPayload payload; + CHIP_ERROR err = InitSetupPayload(payload, passcode, vendorId, productId, discriminator, customFlow, capabilities, version); + VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); + + std::string QRCode; + err = QRCodeSetupPayloadGenerator(payload).payloadBase38Representation(QRCode); + VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); + + Platform::CopyString(output, size, QRCode.c_str()); + return ToPyChipError(CHIP_NO_ERROR); +} + +extern "C" PyChipError pychip_SetupPayload_GenerateManualPairingCode(char * output, size_t size, uint32_t passcode, + uint16_t vendorId, uint16_t productId, uint16_t discriminator, + uint8_t customFlow, uint8_t capabilities, uint8_t version) +{ + SetupPayload payload; + CHIP_ERROR err = InitSetupPayload(payload, passcode, vendorId, productId, discriminator, customFlow, capabilities, version); + VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); + + std::string manualPairingCode; + err = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualPairingCode); + VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); + + Platform::CopyString(output, size, manualPairingCode.c_str()); + return ToPyChipError(CHIP_NO_ERROR); +} diff --git a/src/controller/python/chip/setup_payload/setup_payload.py b/src/controller/python/chip/setup_payload/setup_payload.py index 702fb319b4e233..31a703018717d9 100644 --- a/src/controller/python/chip/setup_payload/setup_payload.py +++ b/src/controller/python/chip/setup_payload/setup_payload.py @@ -14,7 +14,7 @@ # limitations under the License. # -from ctypes import CFUNCTYPE, c_char_p, c_uint8, c_uint16, c_uint32 +from ctypes import CFUNCTYPE, c_char_p, c_uint8, c_uint16, c_uint32, c_uint64, create_string_buffer from typing import Optional from chip.native import GetLibraryHandle, NativeLibraryHandleMethodArguments, PyChipError @@ -43,6 +43,20 @@ def AddVendorAttribute(tag, value): self.vendor_attribute_visitor = SetupPayload.VendorAttributeVisitor( AddVendorAttribute) + def GenerateQrCode(self, passcode: int, vendorId: int = 0xFFF1, productId: int = 0x8001, discriminator: int = 3840, + customFlow: int = 0, capabilities: int = 4, version: int = 0) -> str: + buffer = create_string_buffer(256) + self.chipLib.pychip_SetupPayload_GenerateQrCode(buffer, 256, passcode, vendorId, productId, + discriminator, customFlow, capabilities, version).raise_on_error() + return buffer.value.decode() + + def GenerateManualPairingCode(self, passcode: int, vendorId: int = 0xFFF1, productId: int = 0x8001, discriminator: int = 3840, + customFlow: int = 0, capabilities: int = 4, version: int = 0) -> str: + buffer = create_string_buffer(256) + self.chipLib.pychip_SetupPayload_GenerateManualPairingCode(buffer, 256, passcode, vendorId, productId, + discriminator, customFlow, capabilities, version).raise_on_error() + return buffer.value.decode() + def ParseQrCode(self, qrCode: str): self.Clear() self.chipLib.pychip_SetupPayload_ParseQrCode(qrCode.upper().encode(), @@ -99,6 +113,12 @@ def __InitNativeFunctions(self, chipLib): if chipLib.pychip_SetupPayload_ParseQrCode.argtypes is not None: return setter = NativeLibraryHandleMethodArguments(chipLib) + setter.Set("pychip_SetupPayload_GenerateQrCode", + PyChipError, + [c_char_p, c_uint64, c_uint32, c_uint16, c_uint16, c_uint16, c_uint8, c_uint8, c_uint8]) + setter.Set("pychip_SetupPayload_GenerateManualPairingCode", + PyChipError, + [c_char_p, c_uint64, c_uint32, c_uint16, c_uint16, c_uint16, c_uint8, c_uint8, c_uint8]) setter.Set("pychip_SetupPayload_ParseQrCode", PyChipError, [c_char_p, SetupPayload.AttributeVisitor, SetupPayload.VendorAttributeVisitor]) diff --git a/src/python_testing/TC_MCORE_FS_1_2.py b/src/python_testing/TC_MCORE_FS_1_2.py index f806db4d0921e6..97b5b87017676d 100644 --- a/src/python_testing/TC_MCORE_FS_1_2.py +++ b/src/python_testing/TC_MCORE_FS_1_2.py @@ -42,16 +42,17 @@ import logging import os import queue +import random import secrets import struct import tempfile import time -from dataclasses import dataclass import chip.clusters as Clusters from chip import ChipDeviceCtrl from chip.testing.apps import AppServerSubprocess -from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main, type_matches +from chip.testing.matter_testing import (MatterBaseTest, SetupParameters, TestStep, async_test_body, default_matter_test_main, + type_matches) from ecdsa.curves import NIST256p from mobly import asserts from TC_SC_3_6 import AttributeChangeAccumulator @@ -69,14 +70,6 @@ def _generate_verifier(passcode: int, salt: bytes, iterations: int) -> bytes: return w0.to_bytes(NIST256p.baselen, byteorder='big') + L.to_bytes('uncompressed') -@dataclass -class _SetupParameters: - setup_qr_code: str - manual_code: int - discriminator: int - passcode: int - - class TC_MCORE_FS_1_2(MatterBaseTest): @async_test_body async def setup_class(self): @@ -105,11 +98,8 @@ async def setup_class(self): self.dut_fsa_stdin = open(dut_fsa_stdin_pipe, "w") self.th_server_port = th_server_port - # These are default testing values. - self.th_server_setup_params = _SetupParameters( - setup_qr_code="MT:-24J0AFN00KA0648G00", - manual_code=34970112332, - discriminator=3840, + self.th_server_setup_params = SetupParameters( + discriminator=random.randint(0, 4095), passcode=20202021) # Start the TH_SERVER app. @@ -133,12 +123,12 @@ def teardown_class(self): self.storage.cleanup() super().teardown_class() - def _ask_for_vendor_commissioning_ux_operation(self, setup_params: _SetupParameters): + def _ask_for_vendor_commissioning_ux_operation(self, setup_params: SetupParameters): self.wait_for_user_input( prompt_msg=f"Using the DUT vendor's provided interface, commission the ICD device using the following parameters:\n" f"- discriminator: {setup_params.discriminator}\n" f"- setupPinCode: {setup_params.passcode}\n" - f"- setupQRCode: {setup_params.setup_qr_code}\n" + f"- setupQRCode: {setup_params.qr_code}\n" f"- setupManualCode: {setup_params.manual_code}\n" f"If using FabricSync Admin test app, you may type:\n" f">>> pairing onnetwork 111 {setup_params.passcode}") diff --git a/src/python_testing/TC_MCORE_FS_1_5.py b/src/python_testing/TC_MCORE_FS_1_5.py index e8d6b3e6784a90..fc2eca6ee05cea 100755 --- a/src/python_testing/TC_MCORE_FS_1_5.py +++ b/src/python_testing/TC_MCORE_FS_1_5.py @@ -42,16 +42,17 @@ import logging import os import queue +import random import secrets import struct import tempfile import time -from dataclasses import dataclass import chip.clusters as Clusters from chip import ChipDeviceCtrl from chip.testing.apps import AppServerSubprocess -from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main, type_matches +from chip.testing.matter_testing import (MatterBaseTest, SetupParameters, TestStep, async_test_body, default_matter_test_main, + type_matches) from ecdsa.curves import NIST256p from mobly import asserts from TC_SC_3_6 import AttributeChangeAccumulator @@ -69,14 +70,6 @@ def _generate_verifier(passcode: int, salt: bytes, iterations: int) -> bytes: return w0.to_bytes(NIST256p.baselen, byteorder='big') + L.to_bytes('uncompressed') -@dataclass -class _SetupParameters: - setup_qr_code: str - manual_code: int - discriminator: int - passcode: int - - class TC_MCORE_FS_1_5(MatterBaseTest): @async_test_body async def setup_class(self): @@ -106,11 +99,8 @@ async def setup_class(self): self.dut_fsa_stdin = open(dut_fsa_stdin_pipe, "w") self.th_server_port = th_server_port - # These are default testing values. - self.th_server_setup_params = _SetupParameters( - setup_qr_code="MT:-24J0AFN00KA0648G00", - manual_code=34970112332, - discriminator=3840, + self.th_server_setup_params = SetupParameters( + discriminator=random.randint(0, 4095), passcode=20202021) # Start the TH_SERVER app. @@ -137,12 +127,12 @@ def teardown_class(self): self.storage.cleanup() super().teardown_class() - def _ask_for_vendor_commissioning_ux_operation(self, setup_params: _SetupParameters): + def _ask_for_vendor_commissioning_ux_operation(self, setup_params: SetupParameters): self.wait_for_user_input( prompt_msg=f"Using the DUT vendor's provided interface, commission the ICD device using the following parameters:\n" f"- discriminator: {setup_params.discriminator}\n" f"- setupPinCode: {setup_params.passcode}\n" - f"- setupQRCode: {setup_params.setup_qr_code}\n" + f"- setupQRCode: {setup_params.qr_code}\n" f"- setupManualCode: {setup_params.manual_code}\n" f"If using FabricSync Admin test app, you may type:\n" f">>> pairing onnetwork 111 {setup_params.passcode}") diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py index e5bdf2b3be3e6b..c176904ce101e8 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py @@ -821,6 +821,27 @@ def __str__(self): f'\n spec_location: {self.spec_location}\n') +@dataclass +class SetupParameters: + passcode: int + vendor_id: int = 0xFFF1 + product_id: int = 0x8001 + discriminator: int = 3840 + custom_flow: int = 0 + capabilities: int = 0b0100 + version: int = 0 + + @property + def qr_code(self): + return SetupPayload().GenerateQrCode(self.passcode, self.vendor_id, self.product_id, self.discriminator, + self.custom_flow, self.capabilities, self.version) + + @property + def manual_code(self): + return SetupPayload().GenerateManualPairingCode(self.passcode, self.vendor_id, self.product_id, self.discriminator, + self.custom_flow, self.capabilities, self.version) + + @dataclass class SetupPayloadInfo: filter_type: discovery.FilterType = discovery.FilterType.LONG_DISCRIMINATOR From 53952494640d3ab06bbfb0a56b4bf10d4561d643 Mon Sep 17 00:00:00 2001 From: yeaissa <133245269+yeaissa@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:41:46 +0100 Subject: [PATCH 18/74] [NXP] Fix access to SSID array (#36704) Code is accessing the second slot of the ssid array. The size of ssid array in wifi_scan_params is set to 1 by default. Here the code is accessing the second slot of the array without taking into account the size. --- src/platform/Zephyr/wifi/WiFiManager.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/platform/Zephyr/wifi/WiFiManager.cpp b/src/platform/Zephyr/wifi/WiFiManager.cpp index a0730c1fa168fd..13188df8a425c3 100644 --- a/src/platform/Zephyr/wifi/WiFiManager.cpp +++ b/src/platform/Zephyr/wifi/WiFiManager.cpp @@ -216,9 +216,11 @@ CHIP_ERROR WiFiManager::Scan(const ByteSpan & ssid, ScanResultCallback resultCal memcpy(mScanSsidBuffer, ssid.data(), ssid.size()); mScanSsidBuffer[ssid.size()] = 0; // indicate the end of ssid string mScanParams.ssids[0] = mScanSsidBuffer; - mScanParams.ssids[1] = nullptr; // indicate the end of ssids list - scanParams = &mScanParams; - scanParamsSize = sizeof(*scanParams); +#if (CONFIG_WIFI_MGMT_SCAN_SSID_FILT_MAX > 1) + mScanParams.ssids[1] = nullptr; // indicate the end of ssids list +#endif + scanParams = &mScanParams; + scanParamsSize = sizeof(*scanParams); } if (0 != net_mgmt(NET_REQUEST_WIFI_SCAN, mNetIf, scanParams, scanParamsSize)) { From 9e57208880a4e7360d707697358b6cfbd84b10a3 Mon Sep 17 00:00:00 2001 From: Mathieu Kardous <84793247+mkardous-silabs@users.noreply.github.com> Date: Wed, 4 Dec 2024 09:14:21 -0500 Subject: [PATCH 19/74] [SIlabs] Refactor GetMacAddress function and initial clean up of the Notify functions (#36693) * Rename WifiEvent to WifiPlatformEvent * Refactor Notify function and associated data structures * Rename mac address function * Refactor Mac Address handling * Fix wf200 init * Restyled by clang-format * add init value workaroudn * Update src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.h Co-authored-by: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> * start enums at 0 --------- Co-authored-by: Restyled.io Co-authored-by: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> --- examples/platform/silabs/efr32/BUILD.gn | 3 +- examples/platform/silabs/uart.cpp | 2 +- src/platform/silabs/CHIPDevicePlatformEvent.h | 20 --- .../silabs/ConfigurationManagerImpl.cpp | 7 +- .../silabs/ConnectivityManagerImpl_WIFI.cpp | 73 ++++----- src/platform/silabs/PlatformManagerImpl.cpp | 90 ++++------- src/platform/silabs/PlatformManagerImpl.h | 2 +- src/platform/silabs/rs911x/BLEManagerImpl.cpp | 3 - .../silabs/wifi/SiWx/WifiInterface.cpp | 77 +++++---- .../silabs/wifi/WifiInterfaceAbstraction.cpp | 134 +++++++--------- .../silabs/wifi/WifiInterfaceAbstraction.h | 147 +++++++++++------- .../silabs/wifi/lwip-support/ethernetif.cpp | 12 +- .../silabs/wifi/rs911x/WifiInterface.cpp | 81 +++++----- .../silabs/wifi/wf200/WifiInterface.cpp | 65 ++++---- src/platform/silabs/wifi/wfx_msgs.h | 12 -- .../WiseconnectInterfaceAbstraction.cpp | 38 ++--- .../WiseconnectInterfaceAbstraction.h | 20 ++- 17 files changed, 345 insertions(+), 441 deletions(-) diff --git a/examples/platform/silabs/efr32/BUILD.gn b/examples/platform/silabs/efr32/BUILD.gn index 7b9dccf7ccaa06..46cfae71ecef99 100644 --- a/examples/platform/silabs/efr32/BUILD.gn +++ b/examples/platform/silabs/efr32/BUILD.gn @@ -174,7 +174,8 @@ source_set("efr32-common") { "${silabs_common_plat_dir}/syscalls_stubs.cpp", ] - if (chip_enable_pw_rpc || chip_build_libshell || enable_openthread_cli) { + if (chip_enable_pw_rpc || chip_build_libshell || enable_openthread_cli || + sl_uart_log_output) { sources += [ "${silabs_common_plat_dir}/uart.cpp" ] } diff --git a/examples/platform/silabs/uart.cpp b/examples/platform/silabs/uart.cpp index 809c4e53e05b7a..5bf9eeb51da156 100644 --- a/examples/platform/silabs/uart.cpp +++ b/examples/platform/silabs/uart.cpp @@ -53,7 +53,7 @@ extern "C" { #endif #include "sl_uartdrv_instances.h" #if SL_WIFI -#include +#include #endif // SL_WIFI #ifdef SL_CATALOG_UARTDRV_EUSART_PRESENT #include "sl_uartdrv_eusart_vcom_config.h" diff --git a/src/platform/silabs/CHIPDevicePlatformEvent.h b/src/platform/silabs/CHIPDevicePlatformEvent.h index 090ada64037c6f..10c57a1a3b306d 100644 --- a/src/platform/silabs/CHIPDevicePlatformEvent.h +++ b/src/platform/silabs/CHIPDevicePlatformEvent.h @@ -63,32 +63,12 @@ struct ChipDevicePlatformEvent final #if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION struct { - wfx_event_base_t eventBase; union { sl_wfx_generic_message_t genericMsgEvent; sl_wfx_startup_ind_t startupEvent; sl_wfx_connect_ind_t connectEvent; sl_wfx_disconnect_ind_t disconnectEvent; - - /* - * NOT CURRENTLY USED - *Some structs might be bigger in size than the one we use - * so we reduce the union size by commenting them out. - * Keep for possible future implementation. - */ - - // sl_wfx_generic_ind_t genericEvent; - // sl_wfx_exception_ind_t exceptionEvent; - // sl_wfx_error_ind_t errorEvent; - // sl_wfx_received_ind_t receivedEvent; - // sl_wfx_scan_result_ind_t scanResultEvent; - // sl_wfx_scan_complete_ind_t scanCompleteEvent; - // sl_wfx_start_ap_ind_t startApEvent; - // sl_wfx_stop_ap_ind_t stopApEvent; - // sl_wfx_ap_client_connected_ind_t apClientConnectedEvent; - // sl_wfx_ap_client_rejected_ind_t apClientRejectedEvent; - // sl_wfx_ap_client_disconnected_ind_t apClientDisconnectedEvent; } data; } WFXSystemEvent; #endif diff --git a/src/platform/silabs/ConfigurationManagerImpl.cpp b/src/platform/silabs/ConfigurationManagerImpl.cpp index 3a144eb1160370..5e38cabd4b363a 100644 --- a/src/platform/silabs/ConfigurationManagerImpl.cpp +++ b/src/platform/silabs/ConfigurationManagerImpl.cpp @@ -313,11 +313,10 @@ void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) #ifdef SL_WIFI CHIP_ERROR ConfigurationManagerImpl::GetPrimaryWiFiMACAddress(uint8_t * buf) { - sl_wfx_mac_address_t macaddr; - wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &macaddr); - memcpy(buf, &macaddr.octet[0], sizeof(macaddr.octet)); + VerifyOrReturnError(buf != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - return CHIP_NO_ERROR; + MutableByteSpan byteSpan(buf, kPrimaryMACAddressLength); + return GetMacAddress(SL_WFX_STA_INTERFACE, byteSpan); } #endif diff --git a/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp b/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp index 0d9d63317ef637..441579ead04837 100644 --- a/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp +++ b/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp @@ -81,60 +81,45 @@ void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) // Handle Wfx wifi events... if (event->Type == DeviceEventType::kWFXSystemEvent) { - if (event->Platform.WFXSystemEvent.eventBase == WIFI_EVENT) + + switch (event->Platform.WFXSystemEvent.data.genericMsgEvent.header.id) { - switch (event->Platform.WFXSystemEvent.data.genericMsgEvent.header.id) + case to_underlying(WifiEvent::kStartUp): + ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_START"); + DriveStationState(); + break; + case to_underlying(WifiEvent::kConnect): + ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_CONNECTED"); + if (mWiFiStationState == kWiFiStationState_Connecting) { - case SL_WFX_STARTUP_IND_ID: - ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_START"); - DriveStationState(); - break; - case SL_WFX_CONNECT_IND_ID: - ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_CONNECTED"); - if (mWiFiStationState == kWiFiStationState_Connecting) + if (event->Platform.WFXSystemEvent.data.connectEvent.body.status == 0) { - if (event->Platform.WFXSystemEvent.data.connectEvent.body.status == 0) - { - ChangeWiFiStationState(kWiFiStationState_Connecting_Succeeded); - } - else - { - ChangeWiFiStationState(kWiFiStationState_Connecting_Failed); - } + ChangeWiFiStationState(kWiFiStationState_Connecting_Succeeded); } - DriveStationState(); - break; - case SL_WFX_DISCONNECT_IND_ID: - ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_DISCONNECTED"); - if (mWiFiStationState == kWiFiStationState_Connecting) + else { ChangeWiFiStationState(kWiFiStationState_Connecting_Failed); } - DriveStationState(); - break; - default: - break; } - } - else if (event->Platform.WFXSystemEvent.eventBase == IP_EVENT) - { - switch (event->Platform.WFXSystemEvent.data.genericMsgEvent.header.id) + DriveStationState(); + break; + case to_underlying(WifiEvent::kDisconnect): + ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_DISCONNECTED"); + if (mWiFiStationState == kWiFiStationState_Connecting) { - case IP_EVENT_STA_GOT_IP: - ChipLogProgress(DeviceLayer, "IP_EVENT_STA_GOT_IP"); - UpdateInternetConnectivityState(); - break; - case IP_EVENT_STA_LOST_IP: - ChipLogProgress(DeviceLayer, "IP_EVENT_STA_LOST_IP"); - UpdateInternetConnectivityState(); - break; - case IP_EVENT_GOT_IP6: - ChipLogProgress(DeviceLayer, "IP_EVENT_GOT_IP6"); - UpdateInternetConnectivityState(); - break; - default: - break; + ChangeWiFiStationState(kWiFiStationState_Connecting_Failed); } + DriveStationState(); + break; + + case to_underlying(WifiEvent::kGotIPv4): + case to_underlying(WifiEvent::kLostIP): + case to_underlying(WifiEvent::kGotIPv6): + ChipLogProgress(DeviceLayer, "IP Change Event"); + UpdateInternetConnectivityState(); + break; + default: + break; } } } diff --git a/src/platform/silabs/PlatformManagerImpl.cpp b/src/platform/silabs/PlatformManagerImpl.cpp index b3d7f80052dd3a..7b33b934b3664d 100644 --- a/src/platform/silabs/PlatformManagerImpl.cpp +++ b/src/platform/silabs/PlatformManagerImpl.cpp @@ -141,71 +141,47 @@ void PlatformManagerImpl::_Shutdown() #if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION // This function needs to be global so it can be used from the platform implementation without depending on the platfrom itself. // This is a workaround to avoid a circular dependency. -void HandleWFXSystemEvent(wfx_event_base_t eventBase, sl_wfx_generic_message_t * eventData) +void HandleWFXSystemEvent(sl_wfx_generic_message_t * eventData) { using namespace chip; using namespace chip::DeviceLayer; ChipDeviceEvent event; memset(&event, 0, sizeof(event)); - event.Type = DeviceEventType::kWFXSystemEvent; - event.Platform.WFXSystemEvent.eventBase = eventBase; + event.Type = DeviceEventType::kWFXSystemEvent; - if (eventBase == WIFI_EVENT) + switch (eventData->header.id) { - switch (eventData->header.id) - { - case SL_WFX_STARTUP_IND_ID: - memcpy(&event.Platform.WFXSystemEvent.data.startupEvent, eventData, - sizeof(event.Platform.WFXSystemEvent.data.startupEvent)); - break; - case SL_WFX_CONNECT_IND_ID: - memcpy(&event.Platform.WFXSystemEvent.data.connectEvent, eventData, - sizeof(event.Platform.WFXSystemEvent.data.connectEvent)); - break; - case SL_WFX_DISCONNECT_IND_ID: - memcpy(&event.Platform.WFXSystemEvent.data.disconnectEvent, eventData, - sizeof(event.Platform.WFXSystemEvent.data.disconnectEvent)); - break; - // case SL_WFX_RECEIVED_IND_ID: - // memcpy(&event.Platform.WFXSystemEvent.data.receivedEvent, eventData, - // sizeof(event.Platform.WFXSystemEvent.data.receivedEvent)); - // break; - // case SL_WFX_GENERIC_IND_ID: - // memcpy(&event.Platform.WFXSystemEvent.data.genericEvent, eventData, - // sizeof(event.Platform.WFXSystemEvent.data.genericEvent)); - // break; - // case SL_WFX_EXCEPTION_IND_ID: - // memcpy(&event.Platform.WFXSystemEvent.data.exceptionEvent, eventData, - // sizeof(event.Platform.WFXSystemEvent.data.exceptionEvent)); - // break; - // case SL_WFX_ERROR_IND_ID: - // memcpy(&event.Platform.WFXSystemEvent.data.errorEvent, eventData, - // sizeof(event.Platform.WFXSystemEvent.data.errorEvent)); - // break; - default: - break; - } - } - else if (eventBase == IP_EVENT) - { - switch (eventData->header.id) - { - case IP_EVENT_STA_GOT_IP: - memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData, - sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent)); - break; - case IP_EVENT_GOT_IP6: - memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData, - sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent)); - break; - case IP_EVENT_STA_LOST_IP: - memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData, - sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent)); - break; - default: - break; - } +// TODO: Work around until we unify the data structures behind a Matter level common structure +#if WF200_WIFI + case SL_WFX_STARTUP_IND_ID: +#endif + case to_underlying(WifiEvent::kStartUp): + memcpy(&event.Platform.WFXSystemEvent.data.startupEvent, eventData, + sizeof(event.Platform.WFXSystemEvent.data.startupEvent)); + // TODO: This is a workaround until we unify the Matter Data structures + event.Platform.WFXSystemEvent.data.startupEvent.header.id = to_underlying(WifiEvent::kStartUp); + break; + + case to_underlying(WifiEvent::kConnect): + memcpy(&event.Platform.WFXSystemEvent.data.connectEvent, eventData, + sizeof(event.Platform.WFXSystemEvent.data.connectEvent)); + break; + + case to_underlying(WifiEvent::kDisconnect): + memcpy(&event.Platform.WFXSystemEvent.data.disconnectEvent, eventData, + sizeof(event.Platform.WFXSystemEvent.data.disconnectEvent)); + break; + + case to_underlying(WifiEvent::kGotIPv4): + case to_underlying(WifiEvent::kLostIP): + case to_underlying(WifiEvent::kGotIPv6): + memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData, + sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent)); + break; + + default: + break; } // TODO: We should add error processing here diff --git a/src/platform/silabs/PlatformManagerImpl.h b/src/platform/silabs/PlatformManagerImpl.h index dddc491384a86f..ee5897bbf1d868 100644 --- a/src/platform/silabs/PlatformManagerImpl.h +++ b/src/platform/silabs/PlatformManagerImpl.h @@ -31,7 +31,7 @@ #include #if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION -void HandleWFXSystemEvent(wfx_event_base_t eventBase, sl_wfx_generic_message_t * eventData); +void HandleWFXSystemEvent(sl_wfx_generic_message_t * eventData); #endif namespace chip { diff --git a/src/platform/silabs/rs911x/BLEManagerImpl.cpp b/src/platform/silabs/rs911x/BLEManagerImpl.cpp index 75f118b38a99a4..90103f74e77758 100644 --- a/src/platform/silabs/rs911x/BLEManagerImpl.cpp +++ b/src/platform/silabs/rs911x/BLEManagerImpl.cpp @@ -699,9 +699,6 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising(void) mFlags.Clear(Flags::kRestartAdvertising); - sl_wfx_mac_address_t macaddr; - wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &macaddr); - status = sInstance.SendBLEAdvertisementCommand(); if (status == RSI_SUCCESS) diff --git a/src/platform/silabs/wifi/SiWx/WifiInterface.cpp b/src/platform/silabs/wifi/SiWx/WifiInterface.cpp index 291c9988d83215..7ff167fc718813 100644 --- a/src/platform/silabs/wifi/SiWx/WifiInterface.cpp +++ b/src/platform/silabs/wifi/SiWx/WifiInterface.cpp @@ -196,7 +196,7 @@ constexpr uint16_t kWifiScanTimeoutTicks = 10000; void DHCPTimerEventHandler(void * arg) { - WifiEvent event = WifiEvent::kStationDhcpPoll; + WifiPlatformEvent event = WifiPlatformEvent::kStationDhcpPoll; sl_matter_wifi_post_event(event); } @@ -257,7 +257,7 @@ sl_status_t sl_wifi_siwx917_init(void) ChipLogDetail(DeviceLayer, "Firmware version is: %x%x.%d.%d.%d.%d.%d.%d", version.chip_id, version.rom_id, version.major, version.minor, version.security_version, version.patch_num, version.customer_id, version.build_num); - status = sl_wifi_get_mac_address(SL_WIFI_CLIENT_INTERFACE, (sl_mac_address_t *) &wfx_rsi.sta_mac.octet[0]); + status = sl_wifi_get_mac_address(SL_WIFI_CLIENT_INTERFACE, reinterpret_cast(wfx_rsi.sta_mac.data())); VerifyOrReturnError(status == SL_STATUS_OK, status, ChipLogError(DeviceLayer, "sl_wifi_get_mac_address failed: 0x%lx", static_cast(status))); @@ -300,7 +300,7 @@ sl_status_t ScanCallback(sl_wifi_event_t event, sl_wifi_scan_result_t * scan_res { security = static_cast(scan_result->scan_info[0].security_mode); wfx_rsi.ap_chan = scan_result->scan_info[0].rf_channel; - memcpy(&wfx_rsi.ap_mac.octet, scan_result->scan_info[0].bssid, BSSID_LEN); + memcpy(wfx_rsi.ap_mac.data(), scan_result->scan_info[0].bssid, kWifiMacAddressLength); } osSemaphoreRelease(sScanCompleteSemaphore); @@ -410,7 +410,7 @@ sl_status_t JoinWifiNetwork(void) if (status == SL_STATUS_OK || status == SL_STATUS_IN_PROGRESS) { - WifiEvent event = WifiEvent::kStationConnect; + WifiPlatformEvent event = WifiPlatformEvent::kStationConnect; sl_matter_wifi_post_event(event); return status; } @@ -424,7 +424,7 @@ sl_status_t JoinWifiNetwork(void) ChipLogProgress(DeviceLayer, "Connection retry attempt %d", wfx_rsi.join_retries); wfx_retry_connection(++wfx_rsi.join_retries); - WifiEvent event = WifiEvent::kStationStartJoin; + WifiPlatformEvent event = WifiPlatformEvent::kStationStartJoin; sl_matter_wifi_post_event(event); return status; @@ -453,7 +453,7 @@ sl_status_t sl_matter_wifi_platform_init(void) VerifyOrReturnError(sScanCompleteSemaphore != nullptr, SL_STATUS_ALLOCATION_FAILED); // Create the message queue - sWifiEventQueue = osMessageQueueNew(kWfxQueueSize, sizeof(WifiEvent), nullptr); + sWifiEventQueue = osMessageQueueNew(kWfxQueueSize, sizeof(WifiPlatformEvent), nullptr); VerifyOrReturnError(sWifiEventQueue != nullptr, SL_STATUS_ALLOCATION_FAILED); // Create timer for DHCP polling @@ -480,7 +480,7 @@ int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t * ap) ap->security = wfx_rsi.sec.security; ap->chan = wfx_rsi.ap_chan; chip::Platform::CopyString(ap->ssid, ap->ssid_length, wfx_rsi.sec.ssid); - memcpy(&ap->bssid[0], &wfx_rsi.ap_mac.octet[0], BSSID_LEN); + memcpy(&ap->bssid[0], wfx_rsi.ap_mac.data(), kWifiMacAddressLength); sl_wifi_get_signal_strength(SL_WIFI_CLIENT_INTERFACE, &rssi); ap->rssi = rssi; return status; @@ -570,7 +570,7 @@ sl_status_t show_scan_results(sl_wifi_scan_result_t * scan_result) } cur_scan_result.security = static_cast(scan_result->scan_info[idx].security_mode); cur_scan_result.rssi = (-1) * scan_result->scan_info[idx].rssi_val; - memcpy(cur_scan_result.bssid, scan_result->scan_info[idx].bssid, BSSID_LEN); + memcpy(cur_scan_result.bssid, scan_result->scan_info[idx].bssid, kWifiMacAddressLength); wfx_rsi.scan_cb(&cur_scan_result); // if user has not provided the ssid, then call the callback for each scan result @@ -606,13 +606,13 @@ sl_status_t bg_scan_callback_handler(sl_wifi_event_t event, sl_wifi_scan_result_ void NotifyConnectivity(void) { VerifyOrReturn(!hasNotifiedWifiConnectivity); - wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &wfx_rsi.ap_mac); + NotifyConnection(wfx_rsi.ap_mac); hasNotifiedWifiConnectivity = true; } void HandleDHCPPolling(void) { - WifiEvent event; + WifiPlatformEvent event; // TODO: Notify the application that the interface is not set up or Chipdie here because we are in an unkonwn state struct netif * sta_netif = &wifi_client_context.netif; @@ -624,13 +624,13 @@ void HandleDHCPPolling(void) { wfx_dhcp_got_ipv4((uint32_t) sta_netif->ip_addr.u_addr.ip4.addr); hasNotifiedIPV4 = true; - event = WifiEvent::kStationDhcpDone; + event = WifiPlatformEvent::kStationDhcpDone; sl_matter_wifi_post_event(event); NotifyConnectivity(); } else if (dhcp_state == DHCP_OFF) { - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); hasNotifiedIPV4 = false; } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ @@ -642,14 +642,14 @@ void HandleDHCPPolling(void) char addrStr[chip::Inet::IPAddress::kMaxStringLength] = { 0 }; VerifyOrReturn(ip6addr_ntoa_r(netif_ip6_addr(sta_netif, 0), addrStr, sizeof(addrStr)) != nullptr); ChipLogProgress(DeviceLayer, "SLAAC OK: linklocal addr: %s", addrStr); - wfx_ipv6_notify(GET_IPV6_SUCCESS); + NotifyIPv6Change(true); hasNotifiedIPV6 = true; - event = WifiEvent::kStationDhcpDone; + event = WifiPlatformEvent::kStationDhcpDone; sl_matter_wifi_post_event(event); NotifyConnectivity(); } } -void sl_matter_wifi_post_event(WifiEvent event) +void sl_matter_wifi_post_event(WifiPlatformEvent event) { sl_status_t status = osMessageQueuePut(sWifiEventQueue, &event, 0, 0); @@ -662,7 +662,7 @@ void sl_matter_wifi_post_event(WifiEvent event) } /// ResetDHCPNotificationFlags /// @brief Reset the flags that are used to notify the application about DHCP connectivity -/// and emits a WifiEvent::kStationDoDhcp event to trigger DHCP polling checks. Helper function for ProcessEvent. +/// and emits a WifiPlatformEvent::kStationDoDhcp event to trigger DHCP polling checks. Helper function for ProcessEvent. void ResetDHCPNotificationFlags(void) { @@ -672,23 +672,23 @@ void ResetDHCPNotificationFlags(void) hasNotifiedIPV6 = false; hasNotifiedWifiConnectivity = false; - WifiEvent event = WifiEvent::kStationDoDhcp; + WifiPlatformEvent event = WifiPlatformEvent::kStationDoDhcp; sl_matter_wifi_post_event(event); } -void ProcessEvent(WifiEvent event) +void ProcessEvent(WifiPlatformEvent event) { // Process event switch (event) { - case WifiEvent::kStationConnect: - ChipLogDetail(DeviceLayer, "WifiEvent::kStationConnect"); + case WifiPlatformEvent::kStationConnect: + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationConnect"); wfx_rsi.dev_state.Set(WifiState::kStationConnected); ResetDHCPNotificationFlags(); break; - case WifiEvent::kStationDisconnect: { - ChipLogDetail(DeviceLayer, "WifiEvent::kStationDisconnect"); + case WifiPlatformEvent::kStationDisconnect: { + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDisconnect"); // TODO: This event is not being posted anywhere, seems to be a dead code or we are missing something wfx_rsi.dev_state.Clear(WifiState::kStationReady) @@ -699,24 +699,23 @@ void ProcessEvent(WifiEvent event) /* TODO: Implement disconnect notify */ ResetDHCPNotificationFlags(); #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) - wfx_ip_changed_notify(0); // for IPV4 - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - wfx_ipv6_notify(GET_IPV6_FAIL); + NotifyIPv6Change(false); } break; - case WifiEvent::kAPStart: + case WifiPlatformEvent::kAPStart: // TODO: Currently unimplemented break; - case WifiEvent::kScan: - ChipLogDetail(DeviceLayer, "WifiEvent::kScan"); + case WifiPlatformEvent::kScan: + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kScan"); #ifdef SL_WFX_CONFIG_SCAN if (!(wfx_rsi.dev_state.Has(WifiState::kScanStarted))) { - ChipLogDetail(DeviceLayer, "WifiEvent::kScan"); + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kScan"); sl_wifi_scan_configuration_t wifi_scan_configuration; memset(&wifi_scan_configuration, 0, sizeof(wifi_scan_configuration)); @@ -761,25 +760,25 @@ void ProcessEvent(WifiEvent event) #endif /* SL_WFX_CONFIG_SCAN */ break; - case WifiEvent::kStationStartJoin: - ChipLogDetail(DeviceLayer, "WifiEvent::kStationStartJoin"); + case WifiPlatformEvent::kStationStartJoin: + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationStartJoin"); InitiateScan(); JoinWifiNetwork(); break; - case WifiEvent::kStationDoDhcp: - ChipLogDetail(DeviceLayer, "WifiEvent::kStationDoDhcp"); + case WifiPlatformEvent::kStationDoDhcp: + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDoDhcp"); StartDHCPTimer(WFX_RSI_DHCP_POLL_INTERVAL); break; - case WifiEvent::kStationDhcpDone: - ChipLogDetail(DeviceLayer, "WifiEvent::kStationDhcpDone"); + case WifiPlatformEvent::kStationDhcpDone: + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDhcpDone"); CancelDHCPTimer(); break; - case WifiEvent::kStationDhcpPoll: - ChipLogDetail(DeviceLayer, "WifiEvent::kStationDhcpPoll"); + case WifiPlatformEvent::kStationDhcpPoll: + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDhcpPoll"); HandleDHCPPolling(); break; @@ -802,7 +801,7 @@ void ProcessEvent(WifiEvent event) void sl_matter_wifi_task(void * arg) { (void) arg; - WifiEvent event; + WifiPlatformEvent event; sl_status_t status = SL_STATUS_OK; status = sl_wifi_siwx917_init(); @@ -848,7 +847,7 @@ void wfx_dhcp_got_ipv4(uint32_t ip) wfx_rsi.ip4_addr[3]); /* Notify the Connectivity Manager - via the app */ wfx_rsi.dev_state.Set(WifiState::kStationDhcpDone).Set(WifiState::kStationReady); - wfx_ip_changed_notify(IP_STATUS_SUCCESS); + NotifyIPv4Change(true); } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ diff --git a/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp b/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp index 698c839a10e43a..d6ea0beca7006a 100644 --- a/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp +++ b/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,7 @@ using namespace chip::DeviceLayer; // TODO: This is a workaround because we depend on the platform lib which depends on the platform implementation. // As such we can't depend on the platform here as well -extern void HandleWFXSystemEvent(wfx_event_base_t eventBase, sl_wfx_generic_message_t * eventData); +extern void HandleWFXSystemEvent(sl_wfx_generic_message_t * eventData); namespace { @@ -61,109 +62,82 @@ void RetryConnectionTimerHandler(void * arg) } // namespace -/*********************************************************************************** - * @fn sl_matter_wifi_task_started(void) - * @brief - * Wifi device started notification - * @param[in]: None - * @return None - *************************************************************************************/ -void sl_matter_wifi_task_started(void) +/* Updated functions */ + +void NotifyIPv6Change(bool gotIPv6Addr) { - sl_wfx_startup_ind_t evt; - sl_wfx_mac_address_t mac; + sl_wfx_generic_message_t eventData = {}; + eventData.header.id = gotIPv6Addr ? to_underlying(WifiEvent::kGotIPv6) : to_underlying(WifiEvent::kLostIP); + eventData.header.length = sizeof(eventData.header); - // Creating a timer which will be used to retry connection with AP - sRetryTimer = osTimerNew(RetryConnectionTimerHandler, osTimerOnce, NULL, NULL); - VerifyOrReturn(sRetryTimer != NULL); + HandleWFXSystemEvent(&eventData); +} - memset(&evt, 0, sizeof(evt)); - evt.header.id = SL_WFX_STARTUP_IND_ID; - evt.header.length = sizeof evt; - evt.body.status = 0; - wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &mac); - memcpy(&evt.body.mac_addr[0], &mac.octet[0], MAC_ADDRESS_FIRST_OCTET); +void NotifyIPv4Change(bool gotIPv4Addr) +{ + sl_wfx_generic_message_t eventData; - HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt); + memset(&eventData, 0, sizeof(eventData)); + eventData.header.id = gotIPv4Addr ? to_underlying(WifiEvent::kGotIPv4) : to_underlying(WifiEvent::kLostIP); + eventData.header.length = sizeof(eventData.header); + HandleWFXSystemEvent(&eventData); } -/*********************************************************************************** - * @fn void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t *ap) - * @brief - * For now we are not notifying anything other than AP Mac - - * Other stuff such as DTIM etc. may be required for later - * @param[in] status: - * @param[in] ap: access point - * @return None - *************************************************************************************/ -void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t * ap) +void NotifyDisconnection(WifiDisconnectionReasons reason) { - sl_wfx_connect_ind_t evt; - - VerifyOrReturn(status == SUCCESS_STATUS); + sl_wfx_disconnect_ind_t evt = {}; + evt.header.id = to_underlying(WifiEvent::kDisconnect); + evt.header.length = sizeof evt; + evt.body.reason = to_underlying(reason); - memset(&evt, 0, sizeof(evt)); - evt.header.id = SL_WFX_CONNECT_IND_ID; - evt.header.length = sizeof evt; + HandleWFXSystemEvent((sl_wfx_generic_message_t *) &evt); +} +void NotifyConnection(const MacAddress & ap) +{ + sl_wfx_connect_ind_t evt = {}; + evt.header.id = to_underlying(WifiEvent::kConnect); + evt.header.length = sizeof evt; #ifdef RS911X_WIFI evt.body.channel = wfx_rsi.ap_chan; #endif - memcpy(&evt.body.mac[0], &ap->octet[0], MAC_ADDRESS_FIRST_OCTET); + std::copy(ap.begin(), ap.end(), evt.body.mac); - HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt); + HandleWFXSystemEvent((sl_wfx_generic_message_t *) &evt); } -/************************************************************************************** - * @fn void wfx_disconnected_notify(int32_t status) +/* Function to update */ + +/*********************************************************************************** + * @fn sl_matter_wifi_task_started(void) * @brief - * notification of disconnection - * @param[in] status: + * Wifi device started notification + * @param[in]: None * @return None *************************************************************************************/ -void wfx_disconnected_notify(int32_t status) +void sl_matter_wifi_task_started(void) { - sl_wfx_disconnect_ind_t evt; + sl_wfx_startup_ind_t evt = {}; - memset(&evt, 0, sizeof(evt)); - evt.header.id = SL_WFX_DISCONNECT_IND_ID; - evt.header.length = sizeof evt; - evt.body.reason = status; - HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt); -} + // Creating a timer which will be used to retry connection with AP + sRetryTimer = osTimerNew(RetryConnectionTimerHandler, osTimerOnce, NULL, NULL); + VerifyOrReturn(sRetryTimer != NULL); -/************************************************************************************** - * @fn void wfx_ipv6_notify(int got_ip) - * @brief - * notification of ipv6 - * @param[in] got_ip: - * @return None - *************************************************************************************/ -void wfx_ipv6_notify(int got_ip) -{ - sl_wfx_generic_message_t eventData; + evt.header.id = to_underlying(WifiEvent::kStartUp); + evt.header.length = sizeof evt; + evt.body.status = 0; - memset(&eventData, 0, sizeof(eventData)); - eventData.header.id = got_ip ? IP_EVENT_GOT_IP6 : IP_EVENT_STA_LOST_IP; - eventData.header.length = sizeof(eventData.header); - HandleWFXSystemEvent(IP_EVENT, &eventData); -} + // TODO : Remove workwound when sl_wfx_startup_ind_t is unified + // Issue is same structure name but different contents +#if WF200_WIFI + MutableByteSpan macSpan(evt.body.mac_addr[SL_WFX_STA_INTERFACE], kWifiMacAddressLength); +#else + MutableByteSpan macSpan(evt.body.mac_addr, kWifiMacAddressLength); +#endif // WF200_WIFI -/************************************************************************************** - * @fn void wfx_ip_changed_notify(int got_ip) - * @brief - * notification of ip change - * @param[in] got_ip: - * @return None - *************************************************************************************/ -void wfx_ip_changed_notify(int got_ip) -{ - sl_wfx_generic_message_t eventData; + GetMacAddress(SL_WFX_STA_INTERFACE, macSpan); - memset(&eventData, 0, sizeof(eventData)); - eventData.header.id = got_ip ? IP_EVENT_STA_GOT_IP : IP_EVENT_STA_LOST_IP; - eventData.header.length = sizeof(eventData.header); - HandleWFXSystemEvent(IP_EVENT, &eventData); + HandleWFXSystemEvent((sl_wfx_generic_message_t *) &evt); } /************************************************************************************** diff --git a/src/platform/silabs/wifi/WifiInterfaceAbstraction.h b/src/platform/silabs/wifi/WifiInterfaceAbstraction.h index 012683aef60333..f89f3fefed532d 100644 --- a/src/platform/silabs/wifi/WifiInterfaceAbstraction.h +++ b/src/platform/silabs/wifi/WifiInterfaceAbstraction.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -36,35 +37,41 @@ #include "sl_si91x_types.h" #include "sl_wifi_constants.h" #include "sl_wifi_device.h" +#endif // (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) -/* - * Interface to RSI Sapis - */ +/* Updated constants */ -#define WFX_RSI_DHCP_POLL_INTERVAL (250) /* Poll interval in ms for DHCP */ +constexpr size_t kWifiMacAddressLength = 6; -// MAX SSID LENGTH excluding NULL character -#define WFX_MAX_SSID_LENGTH (32) +/* Defines to update */ + +// TODO: Not sure why the pass key max length differs for the 917 SoC & NCP +#if (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) // MAX PASSKEY LENGTH including NULL character #define WFX_MAX_PASSKEY_LENGTH (SL_WIFI_MAX_PSK_LENGTH) -#define SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME_MS (1000) #else -// MAX SSID LENGTH excluding NULL character -#define WFX_MAX_SSID_LENGTH (32) // MAX PASSKEY LENGTH including NULL character #define WFX_MAX_PASSKEY_LENGTH (64) #endif // (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) +// MAX SSID LENGTH excluding NULL character +#define WFX_MAX_SSID_LENGTH (32) #define MAX_JOIN_RETRIES_COUNT (5) -#define BSSID_LEN (6) -#define MAC_ADDRESS_FIRST_OCTET (6) -#define CONNECTION_STATUS_SUCCESS (1) -#define IP_STATUS_FAIL (0) -#define GET_IPV6_FAIL (0) -#define IP_STATUS_SUCCESS (1) -// TASK and Interrupt Macros -#define SUCCESS_STATUS (1) +/* Updated types */ + +using MacAddress = std::array; + +enum class WifiEvent : uint8_t +{ + kStartUp = 0, + kConnect = 1, + kDisconnect = 2, + kScanComplete = 3, + kGotIPv4 = 4, + kGotIPv6 = 5, + kLostIP = 6, +}; enum class WifiState : uint16_t { @@ -81,24 +88,16 @@ enum class WifiState : uint16_t kScanStarted = (1 << 10), /* Scan Started */ }; -enum class WifiEvent : uint8_t +enum class WifiDisconnectionReasons : uint16_t // using uint16 to match current structure during the transition { - kStationConnect = 0, - kStationDisconnect = 1, - kAPStart = 2, - kAPStop = 3, - kScan = 4, /* This is used as scan result and start */ - kStationStartJoin = 5, - kStationDoDhcp = 6, - kStationDhcpDone = 7, - kStationDhcpPoll = 8 + kUnknownError = 1, // Disconnation due to an internal error + kAccessPointLost = 2, // Device did not receive AP beacon too many times + kAccessPoint = 3, // AP disconnected the device + kApplication = 4, // Application requested disconnection + kWPACouterMeasures = 5, // WPA contermeasures triggered a disconnection }; -typedef enum -{ - WIFI_EVENT, - IP_EVENT, -} wfx_event_base_t; +/* Enums to update */ /* Note that these are same as RSI_security */ typedef enum @@ -135,7 +134,7 @@ typedef struct wfx_wifi_scan_result char ssid[WFX_MAX_SSID_LENGTH + 1]; size_t ssid_length; wfx_sec_t security; - uint8_t bssid[BSSID_LEN]; + uint8_t bssid[kWifiMacAddressLength]; uint8_t chan; int16_t rssi; /* I suspect this is in dBm - so signed */ } wfx_wifi_scan_result_t; @@ -151,13 +150,6 @@ typedef struct wfx_wifi_scan_ext uint32_t overrun_count; } wfx_wifi_scan_ext_t; -typedef enum -{ - IP_EVENT_STA_GOT_IP, - IP_EVENT_GOT_IP6, - IP_EVENT_STA_LOST_IP, -} ip_event_id_t; - #ifdef RS911X_WIFI /* * This Sh%t is here to support WFXUtils - and the Matter stuff that uses it @@ -181,11 +173,11 @@ typedef struct wfx_rsi_s size_t scan_ssid_length; #endif #ifdef SL_WFX_CONFIG_SOFTAP - sl_wfx_mac_address_t softap_mac; + MacAddress softap_mac; #endif - sl_wfx_mac_address_t sta_mac; - sl_wfx_mac_address_t ap_mac; /* To which our STA is connected */ - sl_wfx_mac_address_t ap_bssid; /* To which our STA is connected */ + MacAddress sta_mac; + MacAddress ap_mac; /* To which our STA is connected */ + MacAddress ap_bssid; /* To which our STA is connected */ uint16_t join_retries; uint8_t ip4_addr[4]; /* Not sure if this is enough */ } WfxRsi_t; @@ -193,9 +185,59 @@ typedef struct wfx_rsi_s // TODO: We shouldn't need to have access to a global variable in the interface here extern WfxRsi_t wfx_rsi; +/* Updated functions */ + +/** + * @brief Function notifies the PlatformManager that an IPv6 event occured on the WiFi interface. + * + * @param gotIPv6Addr true, got an IPv6 address + * false, lost or wasn't able to get an IPv6 address + */ +void NotifyIPv6Change(bool gotIPv6Addr); + +#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 +/** + * @brief Function notifies the PlatformManager that an IPv4 event occured on the WiFi interface. + * + * @param gotIPv4Addr true, got an IPv4 address + * false, lost or wasn't able to get an IPv4 address + */ +void NotifyIPv4Change(bool gotIPv4Addr); +#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ + +/** + * @brief Function notifies the PlatformManager that a disconnection event occurred + * + * @param reason reason for the disconnection + */ +void NotifyDisconnection(WifiDisconnectionReasons reason); + +/** + * @brief Function notifies the PlatformManager that a connection event occurred + * + * @param[in] ap pointer to the structure that contains the MAC address of the AP + */ +void NotifyConnection(const MacAddress & ap); + +/** + * @brief Returns the provide interfaces MAC address + * Valid buffer large enough for the MAC address must be provided to the function + * + * @param[in] interface SL_WFX_STA_INTERFACE or SL_WFX_SOFTAP_INTERFACE. + * If soft AP is not enabled, the interface is ignored and the function always returns the Station MAC + * address + * @param[out] addr Interface MAC addres + * + * @return CHIP_ERROR CHIP_NO_ERROR on success + * CHIP_ERROR_BUFFER_TOO_SMALL if the provided ByteSpan size is too small + * + */ +CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, chip::MutableByteSpan & addr); + +/* Function to update */ + sl_status_t wfx_wifi_start(void); void wfx_enable_sta_mode(void); -void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t * addr); void wfx_set_wifi_provision(wfx_wifi_provision_t * wifiConfig); bool wfx_get_wifi_provision(wfx_wifi_provision_t * wifiConfig); bool wfx_is_sta_mode_enabled(void); @@ -221,8 +263,6 @@ void wfx_cancel_scan(void); * Call backs into the Matter Platform code */ void sl_matter_wifi_task_started(void); -void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t * ap); -void wfx_disconnected_notify(int32_t status); /* Implemented for LWIP */ void wfx_lwip_set_sta_link_up(void); @@ -232,9 +272,7 @@ struct netif * wfx_get_netif(sl_wfx_interface_t interface); #if CHIP_DEVICE_CONFIG_ENABLE_IPV4 void wfx_dhcp_got_ipv4(uint32_t); -void wfx_ip_changed_notify(int got_ip); #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ -void wfx_ipv6_notify(int got_ip); void wfx_retry_connection(uint16_t retryAttempt); #ifdef RS911X_WIFI @@ -261,22 +299,11 @@ sl_status_t wfx_power_save(); void sl_matter_wifi_task(void * arg); -#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 -void wfx_ip_changed_notify(int got_ip); -#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t * ap); int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t * extra_info); int32_t wfx_rsi_reset_count(); int32_t sl_wifi_platform_disconnect(); -/** - * @brief Posts an event to the Wi-Fi task - * - * @param[in] event Event to process. - */ -void sl_matter_wifi_post_event(WifiEvent event); - #ifdef __cplusplus extern "C" { #endif diff --git a/src/platform/silabs/wifi/lwip-support/ethernetif.cpp b/src/platform/silabs/wifi/lwip-support/ethernetif.cpp index c37d6ab93337e8..9d9115ba4204e3 100644 --- a/src/platform/silabs/wifi/lwip-support/ethernetif.cpp +++ b/src/platform/silabs/wifi/lwip-support/ethernetif.cpp @@ -88,16 +88,8 @@ static void low_level_init(struct netif * netif) netif->hwaddr_len = ETH_HWADDR_LEN; /* Set netif MAC hardware address */ - sl_wfx_mac_address_t mac_addr; - - wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &mac_addr); - - netif->hwaddr[0] = mac_addr.octet[0]; - netif->hwaddr[1] = mac_addr.octet[1]; - netif->hwaddr[2] = mac_addr.octet[2]; - netif->hwaddr[3] = mac_addr.octet[3]; - netif->hwaddr[4] = mac_addr.octet[4]; - netif->hwaddr[5] = mac_addr.octet[5]; + chip::MutableByteSpan byteSpan(netif->hwaddr, ETH_HWADDR_LEN); + GetMacAddress(SL_WFX_STA_INTERFACE, byteSpan); /* Set netif maximum transfer unit */ netif->mtu = 1500; diff --git a/src/platform/silabs/wifi/rs911x/WifiInterface.cpp b/src/platform/silabs/wifi/rs911x/WifiInterface.cpp index 8b811534ca3e20..fa0fac5482a505 100644 --- a/src/platform/silabs/wifi/rs911x/WifiInterface.cpp +++ b/src/platform/silabs/wifi/rs911x/WifiInterface.cpp @@ -104,7 +104,7 @@ static void rsi_wireless_driver_task_wrapper(void * argument) static void DHCPTimerEventHandler(void * arg) { - WifiEvent event = WifiEvent::kStationDhcpPoll; + WifiPlatformEvent event = WifiPlatformEvent::kStationDhcpPoll; sl_matter_wifi_post_event(event); } @@ -154,7 +154,7 @@ int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t * ap) uint8_t rssi; ap->security = wfx_rsi.sec.security; ap->chan = wfx_rsi.ap_chan; - memcpy(&ap->bssid[0], &wfx_rsi.ap_mac.octet[0], BSSID_LEN); + memcpy(&ap->bssid[0], wfx_rsi.ap_mac.data(), kWifiMacAddressLength); status = rsi_wlan_get(RSI_RSSI, &rssi, sizeof(rssi)); if (status == RSI_SUCCESS) { @@ -262,7 +262,7 @@ static void wfx_rsi_join_cb(uint16_t status, const uint8_t * buf, const uint16_t */ ChipLogProgress(DeviceLayer, "wfx_rsi_join_cb: success"); memset(&temp_reset, 0, sizeof(wfx_wifi_scan_ext_t)); - WifiEvent event = WifiEvent::kStationConnect; + WifiPlatformEvent event = WifiPlatformEvent::kStationConnect; sl_matter_wifi_post_event(event); wfx_rsi.join_retries = 0; } @@ -284,7 +284,7 @@ static void wfx_rsi_join_fail_cb(uint16_t status, uint8_t * buf, uint32_t len) wfx_rsi.dev_state.Clear(WifiState::kStationConnecting).Clear(WifiState::kStationConnected); - WifiEvent event = WifiEvent::kStationStartJoin; + WifiPlatformEvent event = WifiPlatformEvent::kStationStartJoin; sl_matter_wifi_post_event(event); } /************************************************************************************* @@ -375,17 +375,17 @@ static int32_t sl_matter_wifi_init(void) /* initializes wlan radio parameters and WLAN supplicant parameters. */ (void) rsi_wlan_radio_init(); /* Required so we can get MAC address */ - if ((status = rsi_wlan_get(RSI_MAC_ADDRESS, &wfx_rsi.sta_mac.octet[0], RESP_BUFF_SIZE)) != RSI_SUCCESS) + if ((status = rsi_wlan_get(RSI_MAC_ADDRESS, wfx_rsi.sta_mac.data(), RESP_BUFF_SIZE)) != RSI_SUCCESS) { ChipLogError(DeviceLayer, "rsi_wlan_get(RSI_MAC_ADDRESS) failed: %ld", status); return status; } - ChipLogDetail(DeviceLayer, "MAC: %02x:%02x:%02x %02x:%02x:%02x", wfx_rsi.sta_mac.octet[0], wfx_rsi.sta_mac.octet[1], - wfx_rsi.sta_mac.octet[2], wfx_rsi.sta_mac.octet[3], wfx_rsi.sta_mac.octet[4], wfx_rsi.sta_mac.octet[5]); + ChipLogDetail(DeviceLayer, "MAC: %02x:%02x:%02x %02x:%02x:%02x", wfx_rsi.sta_mac.at(0), wfx_rsi.sta_mac.at(1), + wfx_rsi.sta_mac.at(2), wfx_rsi.sta_mac.at(3), wfx_rsi.sta_mac.at(4), wfx_rsi.sta_mac.at(5)); // Create the message queue - sWifiEventQueue = osMessageQueueNew(WFX_QUEUE_SIZE, sizeof(WifiEvent), NULL); + sWifiEventQueue = osMessageQueueNew(WFX_QUEUE_SIZE, sizeof(WifiPlatformEvent), NULL); if (sWifiEventQueue == NULL) { return SL_STATUS_ALLOCATION_FAILED; @@ -451,7 +451,7 @@ static void wfx_rsi_save_ap_info(void) // translation } wfx_rsi.sec.security = WFX_SEC_UNSPECIFIED; wfx_rsi.ap_chan = rsp.scan_info->rf_channel; - memcpy(&wfx_rsi.ap_mac.octet[0], &rsp.scan_info->bssid[0], BSSID_LEN); + memcpy(wfx_rsi.ap_mac.data(), &rsp.scan_info->bssid[0], kWifiMacAddressLength); switch (rsp.scan_info->security_mode) { @@ -563,7 +563,7 @@ void NotifyConnectivity(void) { if (!hasNotifiedWifiConnectivity) { - wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &wfx_rsi.ap_mac); + NotifyConnection(wfx_rsi.ap_mac); hasNotifiedWifiConnectivity = true; } } @@ -590,7 +590,7 @@ void HandleDHCPPolling(void) } else if (dhcp_state == DHCP_OFF) { - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); hasNotifiedIPV4 = false; } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ @@ -599,9 +599,9 @@ void HandleDHCPPolling(void) */ if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !hasNotifiedIPV6) { - wfx_ipv6_notify(GET_IPV6_SUCCESS); - hasNotifiedIPV6 = true; - WifiEvent event = WifiEvent::kStationDhcpDone; + NotifyIPv6Change(true); + hasNotifiedIPV6 = true; + WifiPlatformEvent event = WifiPlatformEvent::kStationDhcpDone; sl_matter_wifi_post_event(event); NotifyConnectivity(); } @@ -609,11 +609,11 @@ void HandleDHCPPolling(void) /** ResetDHCPNotificationFlags * @brief Reset the flags that are used to notify the application about DHCP connectivity - * and emits a WifiEvent::kStationDoDhcp event to trigger DHCP polling checks. Helper function for ProcessEvent. + * and emits a WifiPlatformEvent::kStationDoDhcp event to trigger DHCP polling checks. Helper function for ProcessEvent. */ void ResetDHCPNotificationFlags(void) { - WifiEvent outEvent; + WifiPlatformEvent outEvent; #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) hasNotifiedIPV4 = false; @@ -621,11 +621,11 @@ void ResetDHCPNotificationFlags(void) hasNotifiedIPV6 = false; hasNotifiedWifiConnectivity = false; - outEvent = WifiEvent::kStationDoDhcp; + outEvent = WifiPlatformEvent::kStationDoDhcp; sl_matter_wifi_post_event(outEvent); } -void sl_matter_wifi_post_event(WifiEvent event) +void sl_matter_wifi_post_event(WifiPlatformEvent event) { sl_status_t status = osMessageQueuePut(sWifiEventQueue, &event, 0, 0); @@ -645,43 +645,38 @@ void sl_matter_wifi_post_event(WifiEvent event) * * @param event The input Wi-Fi event to be processed. */ -void ProcessEvent(WifiEvent event) +void ProcessEvent(WifiPlatformEvent event) { // Process event switch (event) { - case WifiEvent::kStationConnect: { - ChipLogDetail(DeviceLayer, "WifiEvent::kStationConnect"); + case WifiPlatformEvent::kStationConnect: { + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationConnect"); wfx_rsi.dev_state.Set(WifiState::kStationConnected); ResetDHCPNotificationFlags(); wfx_lwip_set_sta_link_up(); - /* We need to get AP Mac - TODO */ - // Uncomment once the hook into MATTER is moved to IP connectivty instead - // of AP connectivity. - // wfx_connected_notify(0, &wfx_rsi.ap_mac); // This - // is independant of IP connectivity. } break; - case WifiEvent::kStationDisconnect: { - ChipLogDetail(DeviceLayer, "WifiEvent::kStationDisconnect"); + case WifiPlatformEvent::kStationDisconnect: { + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDisconnect"); // TODO: This event is not being posted anywhere, seems to be a dead code or we are missing something WifiStateFlags flagsToClear = WifiStateFlags(WifiState::kStationReady, WifiState::kStationConnecting, WifiState::kStationConnected, WifiState::kStationDhcpDone); wfx_rsi.dev_state.Clear(flagsToClear); /* TODO: Implement disconnect notify */ ResetDHCPNotificationFlags(); - wfx_lwip_set_sta_link_down(); // Internally dhcpclient_poll(netif) -> - // wfx_ip_changed_notify(0) for IPV4 + wfx_lwip_set_sta_link_down(); + #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - wfx_ipv6_notify(GET_IPV6_FAIL); + NotifyIPv6Change(false); } break; - case WifiEvent::kAPStart: + case WifiPlatformEvent::kAPStart: // TODO: Currently unimplemented break; - case WifiEvent::kScan: { + case WifiPlatformEvent::kScan: { #ifdef SL_WFX_CONFIG_SCAN rsi_rsp_scan_t scan_rsp = { 0 }; memset(&scan_rsp, 0, sizeof(scan_rsp)); @@ -720,9 +715,9 @@ void ProcessEvent(WifiEvent event) ap.security = static_cast(scan->security_mode); ap.rssi = (-1) * scan->rssi_val; - configASSERT(sizeof(ap.bssid) == BSSID_LEN); - configASSERT(sizeof(scan->bssid) == BSSID_LEN); - memcpy(ap.bssid, scan->bssid, BSSID_LEN); + configASSERT(sizeof(ap.bssid) == kWifiMacAddressLength); + configASSERT(sizeof(scan->bssid) == kWifiMacAddressLength); + memcpy(ap.bssid, scan->bssid, kWifiMacAddressLength); (*wfx_rsi.scan_cb)(&ap); // no ssid filter set, return all results @@ -746,22 +741,22 @@ void ProcessEvent(WifiEvent event) #endif /* SL_WFX_CONFIG_SCAN */ } break; - case WifiEvent::kStationStartJoin: { + case WifiPlatformEvent::kStationStartJoin: { // saving the AP related info wfx_rsi_save_ap_info(); // Joining to the network sl_wifi_platform_join_network(); } break; - case WifiEvent::kStationDoDhcp: { + case WifiPlatformEvent::kStationDoDhcp: { StartDHCPTimer(WFX_RSI_DHCP_POLL_INTERVAL); } break; - case WifiEvent::kStationDhcpDone: { + case WifiPlatformEvent::kStationDhcpDone: { CancelDHCPTimer(); } break; - case WifiEvent::kStationDhcpPoll: { + case WifiPlatformEvent::kStationDhcpPoll: { HandleDHCPPolling(); } break; @@ -790,7 +785,7 @@ void sl_matter_wifi_task(void * arg) ChipLogError(DeviceLayer, "sl_matter_wifi_task: sl_matter_wifi_init failed: %ld", rsi_status); return; } - WifiEvent event; + WifiPlatformEvent event; sl_matter_lwip_start(); sl_matter_wifi_task_started(); @@ -831,7 +826,7 @@ void wfx_dhcp_got_ipv4(uint32_t ip) wfx_rsi.ip4_addr[3]); /* Notify the Connectivity Manager - via the app */ wfx_rsi.dev_state.Set(WifiState::kStationDhcpDone, WifiState::kStationReady); - wfx_ip_changed_notify(IP_STATUS_SUCCESS); + NotifyIPv4Change(true); } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ diff --git a/src/platform/silabs/wifi/wf200/WifiInterface.cpp b/src/platform/silabs/wifi/wf200/WifiInterface.cpp index 1ff37ab61727b6..d93bb170111081 100644 --- a/src/platform/silabs/wifi/wf200/WifiInterface.cpp +++ b/src/platform/silabs/wifi/wf200/WifiInterface.cpp @@ -45,7 +45,7 @@ using namespace ::chip::DeviceLayer; // TODO: This is a workaround because we depend on the platform lib which depends on the platform implementation. // As such we can't depend on the platform here as well -extern void HandleWFXSystemEvent(wfx_event_base_t eventBase, sl_wfx_generic_message_t * eventData); +extern void HandleWFXSystemEvent(sl_wfx_generic_message_t * eventData); /* wfxRsi Task will use as its stack */ StackType_t wfxEventTaskStack[1024] = { 0 }; @@ -58,7 +58,7 @@ StaticEventGroup_t wfxEventGroup; EventGroupHandle_t sl_wfx_event_group; TaskHandle_t wfx_events_task_handle; -static sl_wfx_mac_address_t ap_mac; +static MacAddress ap_mac; static uint32_t sta_ip; static wfx_wifi_scan_result_t ap_info; @@ -92,9 +92,6 @@ static wfx_wifi_scan_result_t ap_info; #define STA_IP_FAIL (0) #define WLAN_TASK_PRIORITY (1) -/***************************************************************************** - * macros - ******************************************************************************/ #define WE_ST_STARTED 1 #define WE_ST_STA_CONN 2 #define WE_ST_HW_STARTED 4 @@ -295,6 +292,19 @@ sl_status_t get_all_counters(void) } // namespace +CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, MutableByteSpan & address) +{ + VerifyOrReturnError(address.size() >= kWifiMacAddressLength, CHIP_ERROR_BUFFER_TOO_SMALL); + +#ifdef SL_WFX_CONFIG_SOFTAP + chip::ByteSpan byteSpan((interface == SL_WFX_SOFTAP_INTERFACE) ? wifiContext.mac_addr_1.octet : wifiContext.mac_addr_0.octet); +#else + chip::ByteSpan byteSpan(wifiContext.mac_addr_0.octet); +#endif + + return CopySpanToMutableSpan(byteSpan, address); +} + /*************************************************************************** * @brief * Creates WFX events processing task. @@ -326,7 +336,7 @@ extern "C" sl_status_t sl_wfx_host_process_event(sl_wfx_generic_message_t * even /******** INDICATION ********/ case SL_WFX_STARTUP_IND_ID: { ChipLogProgress(DeviceLayer, "startup completed."); - HandleWFXSystemEvent(WIFI_EVENT, event_payload); + HandleWFXSystemEvent(event_payload); break; } case SL_WFX_CONNECT_IND_ID: { @@ -480,7 +490,7 @@ static void sl_wfx_scan_result_callback(sl_wfx_scan_result_ind_body_t * scan_res } ap->scan.chan = scan_result->channel; ap->scan.rssi = scan_result->rcpi; - memcpy(&ap->scan.bssid[0], &scan_result->mac[0], BSSID_LEN); + memcpy(&ap->scan.bssid[0], &scan_result->mac[0], kWifiMacAddressLength); scan_count++; } } @@ -515,7 +525,7 @@ static void sl_wfx_connect_callback(sl_wfx_connect_ind_body_t connect_indication { case WFM_STATUS_SUCCESS: { ChipLogProgress(DeviceLayer, "STA-Connected"); - memcpy(&ap_mac.octet[0], mac, MAC_ADDRESS_FIRST_OCTET); + memcpy(ap_mac.data(), mac, kWifiMacAddressLength); sl_wfx_context->state = static_cast(static_cast(sl_wfx_context->state) | static_cast(SL_WFX_STA_INTERFACE_CONNECTED)); xEventGroupSetBits(sl_wfx_event_group, SL_WFX_CONNECT); @@ -692,23 +702,23 @@ static void wfx_events_task(void * p_arg) if (!hasNotifiedWifiConnectivity) { ChipLogProgress(DeviceLayer, "will notify WiFi connectivity"); - wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &ap_mac); + NotifyConnection(ap_mac); hasNotifiedWifiConnectivity = true; } } else if (dhcp_state == DHCP_OFF) { - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); hasNotifiedIPV4 = false; } #endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !hasNotifiedIPV6) { - wfx_ipv6_notify(1); + NotifyIPv6Change(true); hasNotifiedIPV6 = true; if (!hasNotifiedWifiConnectivity) { - wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &ap_mac); + NotifyConnection(ap_mac); hasNotifiedWifiConnectivity = true; } } @@ -719,10 +729,10 @@ static void wfx_events_task(void * p_arg) if (flags & SL_WFX_CONNECT) { #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); hasNotifiedIPV4 = false; #endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 - wfx_ipv6_notify(GET_IPV6_FAIL); + NotifyIPv6Change(false); hasNotifiedIPV6 = false; hasNotifiedWifiConnectivity = false; ChipLogProgress(DeviceLayer, "connected to AP"); @@ -744,10 +754,10 @@ static void wfx_events_task(void * p_arg) { #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); hasNotifiedIPV4 = false; #endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 - wfx_ipv6_notify(GET_IPV6_FAIL); + NotifyIPv6Change(false); hasNotifiedIPV6 = false; hasNotifiedWifiConnectivity = false; wifi_extra &= ~WE_ST_STA_CONN; @@ -1078,27 +1088,6 @@ sl_status_t wfx_connect_to_ap(void) return result; } -/**************************************************************************** - * @brief - * get the wifi mac addresss - * @param[in] interface: - * @param[in] addr : address - *****************************************************************************/ -void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t * addr) -{ - sl_wfx_mac_address_t * mac; - -#ifdef SL_WFX_CONFIG_SOFTAP - mac = (interface == SL_WFX_SOFTAP_INTERFACE) ? &wifiContext.mac_addr_1 : &wifiContext.mac_addr_0; -#else - mac = &wifiContext.mac_addr_0; -#endif - *addr = *mac; - ChipLogDetail(DeviceLayer, "WLAN:Get WiFi Mac addr %02x:%02x:%02x:%02x:%02x:%02x", mac->octet[0], mac->octet[1], mac->octet[2], - mac->octet[3], mac->octet[4], mac->octet[5]); - memcpy(&ap_info.bssid[0], &mac->octet[0], 6); -} - /**************************************************************************** * @brief * function called when driver have ipv4 address @@ -1217,7 +1206,7 @@ void wfx_dhcp_got_ipv4(uint32_t ip) ChipLogDetail(DeviceLayer, "DHCP IP=%d.%d.%d.%d", ip4_addr[0], ip4_addr[1], ip4_addr[2], ip4_addr[3]); sta_ip = ip; - wfx_ip_changed_notify(IP_STATUS_SUCCESS); + NotifyIPv4Change(true); } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ diff --git a/src/platform/silabs/wifi/wfx_msgs.h b/src/platform/silabs/wifi/wfx_msgs.h index ec1744c998611b..5cef9a38ac2c95 100644 --- a/src/platform/silabs/wifi/wfx_msgs.h +++ b/src/platform/silabs/wifi/wfx_msgs.h @@ -27,18 +27,6 @@ #include "sl_wfx_constants.h" #else -// These names exists in the Si SDK as typedef enum. If they are present in the WF200 builds, we end up with conflicting -// definitions but no erros because one is a define the other is a typedef enum. This causes different files to use different -// values. -#define SL_WFX_STARTUP_IND_ID (1) -#define SL_WFX_CONNECT_IND_ID (2) -#define SL_WFX_DISCONNECT_IND_ID (3) -#define SL_WFX_SCAN_COMPLETE_ID (4) - -typedef struct -{ - uint8_t octet[6]; ///< Table to store a MAC address -} sl_wfx_mac_address_t; /** * @brief General Message header structure * diff --git a/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.cpp b/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.cpp index 2266989b906f79..f0b863419855d0 100644 --- a/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.cpp +++ b/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.cpp @@ -18,6 +18,8 @@ #include #include +extern WfxRsi_t wfx_rsi; + namespace { // Thread for the WLAN RSI @@ -35,6 +37,19 @@ constexpr osThreadAttr_t kWlanTaskAttr = { .name = "wlan_rsi", } // namespace +CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, chip::MutableByteSpan & address) +{ + VerifyOrReturnError(address.size() >= kWifiMacAddressLength, CHIP_ERROR_BUFFER_TOO_SMALL); + +#ifdef SL_WFX_CONFIG_SOFTAP + chip::ByteSpan byteSpan((interface == SL_WFX_SOFTAP_INTERFACE) ? wfx_rsi.softap_mac : wfx_rsi.sta_mac); +#else + chip::ByteSpan byteSpan(wfx_rsi.sta_mac); +#endif + + return CopySpanToMutableSpan(byteSpan, address); +} + /********************************************************************* * @fn sl_status_t wfx_wifi_start(void) * @brief @@ -82,25 +97,6 @@ bool wfx_is_sta_mode_enabled(void) return wfx_rsi.dev_state.Has(WifiState::kStationMode); } -/********************************************************************* - * @fn void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t *addr) - * @brief - * get the wifi mac address - * @param[in] Interface: - * @param[in] addr : address - * @return - * None - ***********************************************************************/ -void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t * addr) -{ - VerifyOrReturn(addr != nullptr); -#ifdef SL_WFX_CONFIG_SOFTAP - *addr = (interface == SL_WFX_SOFTAP_INTERFACE) ? wfx_rsi.softap_mac : wfx_rsi.sta_mac; -#else - *addr = wfx_rsi.sta_mac; -#endif -} - /********************************************************************* * @fn void wfx_set_wifi_provision(wfx_wifi_provision_t *cfg) * @brief @@ -160,7 +156,7 @@ sl_status_t wfx_connect_to_ap(void) VerifyOrReturnError(wfx_rsi.sec.ssid_length <= WFX_MAX_SSID_LENGTH, SL_STATUS_HAS_OVERFLOWED); ChipLogProgress(DeviceLayer, "connect to access point: %s", wfx_rsi.sec.ssid); - WifiEvent event = WifiEvent::kStationStartJoin; + WifiPlatformEvent event = WifiPlatformEvent::kStationStartJoin; sl_matter_wifi_post_event(event); return SL_STATUS_OK; } @@ -327,7 +323,7 @@ bool wfx_start_scan(char * ssid, void (*callback)(wfx_wifi_scan_result_t *)) VerifyOrReturnError(wfx_rsi.scan_ssid != nullptr, false); chip::Platform::CopyString(wfx_rsi.scan_ssid, wfx_rsi.scan_ssid_length, ssid); - WifiEvent event = WifiEvent::kScan; + WifiPlatformEvent event = WifiPlatformEvent::kScan; sl_matter_wifi_post_event(event); return true; diff --git a/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.h b/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.h index 9073a02ef64b5b..5ae23966f5ab61 100644 --- a/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.h +++ b/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.h @@ -22,16 +22,22 @@ #include #define WFX_RSI_DHCP_POLL_INTERVAL (250) /* Poll interval in ms for DHCP */ -#define GET_IPV6_SUCCESS (1) -extern WfxRsi_t wfx_rsi; +enum class WifiPlatformEvent : uint8_t +{ + kStationConnect = 0, + kStationDisconnect = 1, + kAPStart = 2, + kAPStop = 3, + kScan = 4, /* This combines the scan start and scan result events */ + kStationStartJoin = 5, + kStationDoDhcp = 6, + kStationDhcpDone = 7, + kStationDhcpPoll = 8, +}; void sl_matter_wifi_task(void * arg); -#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 -void wfx_ip_changed_notify(int got_ip); -#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t * ap); int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t * extra_info); int32_t wfx_rsi_reset_count(); @@ -44,4 +50,4 @@ sl_status_t sl_matter_wifi_platform_init(void); * * @param[in] event Event to process. */ -void sl_matter_wifi_post_event(WifiEvent event); +void sl_matter_wifi_post_event(WifiPlatformEvent event); From 38ad07d8742dd1a3106af68f6a612c6abedea5ca Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Wed, 4 Dec 2024 17:21:20 +0100 Subject: [PATCH 20/74] Allow to communicate with DUT via standard input (#36687) * Allow to communicate with DUT via standard input * Use fabric-sync-app.py stdin instead dedicated pipe * Drop pipe stdin forwarder in fabric-sync-app.py * Restyled by autopep8 * Wait for thread to stop * Fix referencing not-created variable --------- Co-authored-by: Restyled.io --- docs/testing/python.md | 5 ++ .../fabric-admin/scripts/fabric-sync-app.py | 37 +-------------- scripts/tests/run_python_test.py | 46 +++++++++++++++++-- src/python_testing/TC_BRBINFO_4_1.py | 3 +- src/python_testing/TC_CCTRL_2_1.py | 3 +- src/python_testing/TC_CCTRL_2_2.py | 3 +- src/python_testing/TC_CCTRL_2_3.py | 3 +- src/python_testing/TC_ECOINFO_2_1.py | 3 +- src/python_testing/TC_ECOINFO_2_2.py | 3 +- src/python_testing/TC_MCORE_FS_1_1.py | 3 +- src/python_testing/TC_MCORE_FS_1_2.py | 3 +- src/python_testing/TC_MCORE_FS_1_3.py | 13 +++--- src/python_testing/TC_MCORE_FS_1_4.py | 13 +++--- src/python_testing/TC_MCORE_FS_1_5.py | 3 +- .../chip/testing/metadata.py | 2 + 15 files changed, 82 insertions(+), 61 deletions(-) diff --git a/docs/testing/python.md b/docs/testing/python.md index a7bec6d07e17c3..9bda585726d409 100644 --- a/docs/testing/python.md +++ b/docs/testing/python.md @@ -722,6 +722,11 @@ for that run, e.g.: - Example: `"Manual pairing code: \\[\\d+\\]"` +- `app-stdin-pipe`: Specifies the path to the named pipe that the test runner + might use to send input to the application. + + - Example: `/tmp/app-fifo` + - `script-args`: Specifies the arguments to be passed to the test script. - Example: diff --git a/examples/fabric-admin/scripts/fabric-sync-app.py b/examples/fabric-admin/scripts/fabric-sync-app.py index 3de85b9f672887..a44a2a2d7ae543 100755 --- a/examples/fabric-admin/scripts/fabric-sync-app.py +++ b/examples/fabric-admin/scripts/fabric-sync-app.py @@ -16,7 +16,6 @@ import asyncio import contextlib -import os import shutil import signal import sys @@ -41,26 +40,6 @@ async def forward_f(prefix: bytes, f_in: asyncio.StreamReader, f_out.flush() -async def forward_pipe(pipe_path: str, f_out: asyncio.StreamWriter): - """Forward named pipe to f_out. - - Unfortunately, Python does not support async file I/O on named pipes. This - function performs busy waiting with a short asyncio-friendly sleep to read - from the pipe. - """ - fd = os.open(pipe_path, os.O_RDONLY | os.O_NONBLOCK) - while True: - try: - data = os.read(fd, 1024) - if data: - f_out.write(data) - await f_out.drain() - if not data: - await asyncio.sleep(0.1) - except BlockingIOError: - await asyncio.sleep(0.1) - - async def forward_stdin(f_out: asyncio.StreamWriter): """Forward stdin to f_out.""" loop = asyncio.get_event_loop() @@ -175,9 +154,6 @@ async def main(args): storage = TemporaryDirectory(prefix="fabric-sync-app") storage_dir = Path(storage.name) - if args.stdin_pipe and not args.stdin_pipe.exists(): - os.mkfifo(args.stdin_pipe) - admin, bridge = await asyncio.gather( run_admin( args.app_admin, @@ -206,8 +182,6 @@ def terminate(): admin.terminate() with contextlib.suppress(ProcessLookupError): bridge.terminate() - if args.stdin_pipe: - args.stdin_pipe.unlink(missing_ok=True) loop.remove_signal_handler(signal.SIGINT) loop.remove_signal_handler(signal.SIGTERM) @@ -249,17 +223,12 @@ def terminate(): await admin.send(f"pairing open-commissioning-window {bridge_node_id} {cw_endpoint_id}" f" {cw_option} {cw_timeout} {cw_iteration} {cw_discriminator}") - def get_input_forwarder(): - if args.stdin_pipe: - return forward_pipe(args.stdin_pipe, admin.p.stdin) - return forward_stdin(admin.p.stdin) - try: # Wait for any of the tasks to complete. _, pending = await asyncio.wait([ asyncio.create_task(admin.wait()), asyncio.create_task(bridge.wait()), - asyncio.create_task(get_input_forwarder()), + asyncio.create_task(forward_stdin(admin.p.stdin)), ], return_when=asyncio.FIRST_COMPLETED) # Cancel the remaining tasks. for task in pending: @@ -285,8 +254,6 @@ def get_input_forwarder(): help="fabric-admin RPC server port") parser.add_argument("--app-bridge-rpc-port", metavar="PORT", type=int, help="fabric-bridge RPC server port") - parser.add_argument("--stdin-pipe", metavar="PATH", type=Path, - help="read input from a named pipe instead of stdin") parser.add_argument("--storage-dir", metavar="PATH", type=Path, help=("directory to place storage files in; by default " "volatile storage is used")) @@ -309,7 +276,5 @@ def get_input_forwarder(): parser.error("fabric-admin executable not found in PATH. Use '--app-admin' argument to provide it.") if args.app_bridge is None or not args.app_bridge.exists(): parser.error("fabric-bridge-app executable not found in PATH. Use '--app-bridge' argument to provide it.") - if args.stdin_pipe and args.stdin_pipe.exists() and not args.stdin_pipe.is_fifo(): - parser.error("given stdin pipe exists and is not a named pipe") with contextlib.suppress(KeyboardInterrupt): asyncio.run(main(args)) diff --git a/scripts/tests/run_python_test.py b/scripts/tests/run_python_test.py index 0c40f9ac30f10b..267fb513952437 100755 --- a/scripts/tests/run_python_test.py +++ b/scripts/tests/run_python_test.py @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import contextlib import datetime import glob import io @@ -22,9 +23,12 @@ import os.path import pathlib import re +import select import shlex import sys +import threading import time +import typing import click import coloredlogs @@ -68,6 +72,23 @@ def process_test_script_output(line, is_stderr): return process_chip_output(line, is_stderr, TAG_PROCESS_TEST) +def forward_fifo(path: str, f_out: typing.BinaryIO, stop_event: threading.Event): + """Forward the content of a named pipe to a file-like object.""" + if not os.path.exists(path): + with contextlib.suppress(OSError): + os.mkfifo(path) + with open(os.open(path, os.O_RDONLY | os.O_NONBLOCK), 'rb') as f_in: + while not stop_event.is_set(): + if select.select([f_in], [], [], 0.5)[0]: + line = f_in.readline() + if not line: + break + f_out.write(line) + f_out.flush() + with contextlib.suppress(OSError): + os.unlink(path) + + @click.command() @click.option("--app", type=click.Path(exists=True), default=None, help='Path to local application to use, omit to use external apps.') @@ -79,6 +100,8 @@ def process_test_script_output(line, is_stderr): help='The extra arguments passed to the device. Can use placeholders like {SCRIPT_BASE_NAME}') @click.option("--app-ready-pattern", type=str, default=None, help='Delay test script start until given regular expression pattern is found in the application output.') +@click.option("--app-stdin-pipe", type=str, default=None, + help='Path for a standard input redirection named pipe to be used by the test script.') @click.option("--script", type=click.Path(exists=True), default=os.path.join(DEFAULT_CHIP_ROOT, 'src', 'controller', @@ -94,7 +117,8 @@ def process_test_script_output(line, is_stderr): help="Do not print output from passing tests. Use this flag in CI to keep GitHub log size manageable.") @click.option("--load-from-env", default=None, help="YAML file that contains values for environment variables.") def main(app: str, factory_reset: bool, factory_reset_app_only: bool, app_args: str, - app_ready_pattern: str, script: str, script_args: str, script_gdb: bool, quiet: bool, load_from_env): + app_ready_pattern: str, app_stdin_pipe: str, script: str, script_args: str, + script_gdb: bool, quiet: bool, load_from_env): if load_from_env: reader = MetadataReader(load_from_env) runs = reader.parse_script(script) @@ -106,6 +130,7 @@ def main(app: str, factory_reset: bool, factory_reset_app_only: bool, app_args: app=app, app_args=app_args, app_ready_pattern=app_ready_pattern, + app_stdin_pipe=app_stdin_pipe, script_args=script_args, script_gdb=script_gdb, ) @@ -128,11 +153,13 @@ def main(app: str, factory_reset: bool, factory_reset_app_only: bool, app_args: for run in runs: logging.info("Executing %s %s", run.py_script_path.split('/')[-1], run.run) main_impl(run.app, run.factory_reset, run.factory_reset_app_only, run.app_args or "", - run.app_ready_pattern, run.py_script_path, run.script_args or "", run.script_gdb, run.quiet) + run.app_ready_pattern, run.app_stdin_pipe, run.py_script_path, + run.script_args or "", run.script_gdb, run.quiet) def main_impl(app: str, factory_reset: bool, factory_reset_app_only: bool, app_args: str, - app_ready_pattern: str, script: str, script_args: str, script_gdb: bool, quiet: bool): + app_ready_pattern: str, app_stdin_pipe: str, script: str, script_args: str, + script_gdb: bool, quiet: bool): app_args = app_args.replace('{SCRIPT_BASE_NAME}', os.path.splitext(os.path.basename(script))[0]) script_args = script_args.replace('{SCRIPT_BASE_NAME}', os.path.splitext(os.path.basename(script))[0]) @@ -154,6 +181,8 @@ def main_impl(app: str, factory_reset: bool, factory_reset_app_only: bool, app_a pathlib.Path(match.group("path")).unlink(missing_ok=True) app_process = None + app_stdin_forwarding_thread = None + app_stdin_forwarding_stop_event = threading.Event() app_exit_code = 0 app_pid = 0 @@ -172,7 +201,13 @@ def main_impl(app: str, factory_reset: bool, factory_reset_app_only: bool, app_a f_stdout=stream_output, f_stderr=stream_output) app_process.start(expected_output=app_ready_pattern, timeout=30) - app_process.p.stdin.close() + if app_stdin_pipe: + logging.info("Forwarding stdin from '%s' to app", app_stdin_pipe) + app_stdin_forwarding_thread = threading.Thread( + target=forward_fifo, args=(app_stdin_pipe, app_process.p.stdin, app_stdin_forwarding_stop_event)) + app_stdin_forwarding_thread.start() + else: + app_process.p.stdin.close() app_pid = app_process.p.pid script_command = [script, "--paa-trust-store-path", os.path.join(DEFAULT_CHIP_ROOT, MATTER_DEVELOPMENT_PAA_ROOT_CERTS), @@ -204,6 +239,9 @@ def main_impl(app: str, factory_reset: bool, factory_reset_app_only: bool, app_a if app_process: logging.info("Stopping app with SIGTERM") + if app_stdin_forwarding_thread: + app_stdin_forwarding_stop_event.set() + app_stdin_forwarding_thread.join() app_process.terminate() app_exit_code = app_process.returncode diff --git a/src/python_testing/TC_BRBINFO_4_1.py b/src/python_testing/TC_BRBINFO_4_1.py index 8c929d39b94f09..9caa513906427e 100644 --- a/src/python_testing/TC_BRBINFO_4_1.py +++ b/src/python_testing/TC_BRBINFO_4_1.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_CCTRL_2_1.py b/src/python_testing/TC_CCTRL_2_1.py index b656973f6afe98..24ebd19c5291fa 100644 --- a/src/python_testing/TC_CCTRL_2_1.py +++ b/src/python_testing/TC_CCTRL_2_1.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_CCTRL_2_2.py b/src/python_testing/TC_CCTRL_2_2.py index 3f60fd9e382bac..01a4fc42cc5708 100644 --- a/src/python_testing/TC_CCTRL_2_2.py +++ b/src/python_testing/TC_CCTRL_2_2.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_CCTRL_2_3.py b/src/python_testing/TC_CCTRL_2_3.py index 83c25290cf6207..26a758bea01679 100644 --- a/src/python_testing/TC_CCTRL_2_3.py +++ b/src/python_testing/TC_CCTRL_2_3.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_ECOINFO_2_1.py b/src/python_testing/TC_ECOINFO_2_1.py index a0adf75ac4b8e2..d86200d320859e 100644 --- a/src/python_testing/TC_ECOINFO_2_1.py +++ b/src/python_testing/TC_ECOINFO_2_1.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_ECOINFO_2_2.py b/src/python_testing/TC_ECOINFO_2_2.py index 6ce1e490d53841..ce98a806cef785 100644 --- a/src/python_testing/TC_ECOINFO_2_2.py +++ b/src/python_testing/TC_ECOINFO_2_2.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_MCORE_FS_1_1.py b/src/python_testing/TC_MCORE_FS_1_1.py index 780089b807ecfe..8428a998782601 100755 --- a/src/python_testing/TC_MCORE_FS_1_1.py +++ b/src/python_testing/TC_MCORE_FS_1_1.py @@ -24,8 +24,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_MCORE_FS_1_2.py b/src/python_testing/TC_MCORE_FS_1_2.py index 97b5b87017676d..ffcbe006a3a50a 100644 --- a/src/python_testing/TC_MCORE_FS_1_2.py +++ b/src/python_testing/TC_MCORE_FS_1_2.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_MCORE_FS_1_3.py b/src/python_testing/TC_MCORE_FS_1_3.py index 4b732a1b3a8995..b4685f175d0fe5 100644 --- a/src/python_testing/TC_MCORE_FS_1_3.py +++ b/src/python_testing/TC_MCORE_FS_1_3.py @@ -26,8 +26,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json @@ -71,11 +72,11 @@ def setup_class(self): self.storage = None # Get the path to the TH_SERVER_NO_UID app from the user params. - th_server_app = self.user_params.get("th_server_no_uid_app_path", None) - if not th_server_app: + th_server_no_uid_app = self.user_params.get("th_server_no_uid_app_path", None) + if not th_server_no_uid_app: asserts.fail("This test requires a TH_SERVER_NO_UID app. Specify app path with --string-arg th_server_no_uid_app_path:") - if not os.path.exists(th_server_app): - asserts.fail(f"The path {th_server_app} does not exist") + if not os.path.exists(th_server_no_uid_app): + asserts.fail(f"The path {th_server_no_uid_app} does not exist") # Create a temporary storage directory for keeping KVS files. self.storage = tempfile.TemporaryDirectory(prefix=self.__class__.__name__) @@ -94,7 +95,7 @@ def setup_class(self): # Start the TH_SERVER_NO_UID app. self.th_server = AppServerSubprocess( - th_server_app, + th_server_no_uid_app, storage_dir=self.storage.name, port=self.th_server_port, discriminator=self.th_server_discriminator, diff --git a/src/python_testing/TC_MCORE_FS_1_4.py b/src/python_testing/TC_MCORE_FS_1_4.py index c8f3e764d5ce72..fb64378750cbf1 100644 --- a/src/python_testing/TC_MCORE_FS_1_4.py +++ b/src/python_testing/TC_MCORE_FS_1_4.py @@ -26,8 +26,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json @@ -129,11 +130,11 @@ def setup_class(self): asserts.fail(f"The path {th_fsa_bridge_path} does not exist") # Get the path to the TH_SERVER_NO_UID app from the user params. - th_server_app = self.user_params.get("th_server_no_uid_app_path", None) - if not th_server_app: + th_server_no_uid_app = self.user_params.get("th_server_no_uid_app_path", None) + if not th_server_no_uid_app: asserts.fail("This test requires a TH_SERVER_NO_UID app. Specify app path with --string-arg th_server_no_uid_app_path:") - if not os.path.exists(th_server_app): - asserts.fail(f"The path {th_server_app} does not exist") + if not os.path.exists(th_server_no_uid_app): + asserts.fail(f"The path {th_server_no_uid_app} does not exist") # Create a temporary storage directory for keeping KVS files. self.storage = tempfile.TemporaryDirectory(prefix=self.__class__.__name__) @@ -171,7 +172,7 @@ def setup_class(self): # Start the TH_SERVER_NO_UID app. self.th_server = AppServerSubprocess( - th_server_app, + th_server_no_uid_app, storage_dir=self.storage.name, port=self.th_server_port, discriminator=self.th_server_discriminator, diff --git a/src/python_testing/TC_MCORE_FS_1_5.py b/src/python_testing/TC_MCORE_FS_1_5.py index fc2eca6ee05cea..bd2f40a2ead49e 100755 --- a/src/python_testing/TC_MCORE_FS_1_5.py +++ b/src/python_testing/TC_MCORE_FS_1_5.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py b/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py index 2d40d792acbd34..3ec286dc779169 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py @@ -27,6 +27,7 @@ class Metadata: app: str = "" app_args: Optional[str] = None app_ready_pattern: Optional[str] = None + app_stdin_pipe: Optional[str] = None script_args: Optional[str] = None factory_reset: bool = False factory_reset_app_only: bool = False @@ -148,6 +149,7 @@ def parse_script(self, py_script_path: str) -> List[Metadata]: app=attr.get("app", ""), app_args=attr.get("app-args"), app_ready_pattern=attr.get("app-ready-pattern"), + app_stdin_pipe=attr.get("app-stdin-pipe"), script_args=attr.get("script-args"), factory_reset=attr.get("factory-reset", False), quiet=attr.get("quiet", True), From 71dc879501d0000fa9eadf734e8d1644871f104b Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 4 Dec 2024 15:44:10 -0500 Subject: [PATCH 21/74] Update Darwin availability annotations. (#36721) --- src/darwin/Framework/CHIP/MTRAttributeValueWaiter.h | 4 ++-- src/darwin/Framework/CHIP/MTRDevice.h | 6 +++--- .../Framework/CHIP/XPC Protocol/MTRXPCServerProtocol.h | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.h b/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.h index 98ee86a800da09..d1f40910f56025 100644 --- a/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.h +++ b/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.h @@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN -MTR_NEWLY_AVAILABLE +MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)) @interface MTRAttributeValueWaiter : NSObject - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; @@ -31,7 +31,7 @@ MTR_NEWLY_AVAILABLE */ - (void)cancel; -@property (readonly, nonatomic) NSUUID * UUID; +@property (readonly, nonatomic) NSUUID * UUID MTR_NEWLY_AVAILABLE; @end diff --git a/src/darwin/Framework/CHIP/MTRDevice.h b/src/darwin/Framework/CHIP/MTRDevice.h index 247223cbe43fbb..b1ca179df658f7 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.h +++ b/src/darwin/Framework/CHIP/MTRDevice.h @@ -114,14 +114,14 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) * * A non-nil value if the vendor identifier has been determined from the device, nil if unknown. */ -@property (nonatomic, readonly, nullable, copy) NSNumber * vendorID MTR_NEWLY_AVAILABLE; +@property (nonatomic, readonly, nullable, copy) NSNumber * vendorID MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); /** * The Product Identifier associated with the device. * * A non-nil value if the product identifier has been determined from the device, nil if unknown. */ -@property (nonatomic, readonly, nullable, copy) NSNumber * productID MTR_NEWLY_AVAILABLE; +@property (nonatomic, readonly, nullable, copy) NSNumber * productID MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); /** * Network commissioning features supported by the device. @@ -362,7 +362,7 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) - (MTRAttributeValueWaiter *)waitForAttributeValues:(NSDictionary *> *)values timeout:(NSTimeInterval)timeout queue:(dispatch_queue_t)queue - completion:(void (^)(NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; + completion:(void (^)(NSError * _Nullable error))completion MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); @end diff --git a/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCServerProtocol.h b/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCServerProtocol.h index 6daec1bb9d05bf..45d19185d9184e 100644 --- a/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCServerProtocol.h +++ b/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCServerProtocol.h @@ -21,10 +21,10 @@ NS_ASSUME_NONNULL_BEGIN MTR_EXTERN NSString * const MTRDeviceControllerRegistrationNodeIDsKey MTR_AVAILABLE(ios(18.2), macos(15.2), watchos(11.2), tvos(18.2)); MTR_EXTERN NSString * const MTRDeviceControllerRegistrationNodeIDKey MTR_AVAILABLE(ios(18.2), macos(15.2), watchos(11.2), tvos(18.2)); MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerContextKey MTR_AVAILABLE(ios(18.2), macos(15.2), watchos(11.2), tvos(18.2)); -MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerNodeIDKey MTR_NEWLY_AVAILABLE; -MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerIsRunningKey MTR_NEWLY_AVAILABLE; -MTR_EXTERN NSString * const MTRDeviceControllerRegistrationDeviceInternalStateKey MTR_NEWLY_AVAILABLE; -MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerCompressedFabricIDKey MTR_NEWLY_AVAILABLE; +MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerNodeIDKey MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); +MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerIsRunningKey MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); +MTR_EXTERN NSString * const MTRDeviceControllerRegistrationDeviceInternalStateKey MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); +MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerCompressedFabricIDKey MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); MTR_AVAILABLE(ios(18.2), macos(15.2), watchos(11.2), tvos(18.2)) @protocol MTRXPCServerProtocol_MTRDevice From ca772d7565fe48e01fecbb16f7a8491229dcb864 Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:07:30 +0100 Subject: [PATCH 22/74] [Android] Implement DiagnosticLog (#36591) * Implement Android DiagnosticLog * Update from comment * Restyled * Update DiagnosticLog UX (Download complete / failed) * Fix timeout issue * Fix java-controller build error * modify from comment * Add javadoc, test cases * kotlin code style * Fix from comment * Fix build error --- .github/workflows/java-tests.yaml | 11 + .../CHIPTool/app/src/main/AndroidManifest.xml | 9 + .../chip/chiptool/SelectActionFragment.kt | 5 + .../clusterclient/DiagnosticLogFragment.kt | 172 ++++++++++ .../res/layout/diagnostic_log_fragment.xml | 87 ++++++ .../res/layout/select_action_fragment.xml | 8 + .../app/src/main/res/values/strings.xml | 4 + .../app/src/main/res/xml/file_paths.xml | 4 + examples/java-matter-controller/BUILD.gn | 2 + .../java/src/com/matter/controller/Main.kt | 12 + .../commands/bdx/DownloadLogCommand.kt | 73 +++++ .../PairOnNetworkLongDownloadLogCommand.kt | 96 ++++++ kotlin-detect-config.yaml | 1 + scripts/tests/java/bdx_test.py | 87 ++++++ scripts/tests/run_java_test.py | 42 +++ .../java/AndroidLogDownloadFromNode.cpp | 294 ++++++++++++++++++ .../java/AndroidLogDownloadFromNode.h | 95 ++++++ src/controller/java/BUILD.gn | 6 + .../java/BdxDiagnosticLogsReceiver.cpp | 121 +++++++ .../java/BdxDiagnosticLogsReceiver.h | 65 ++++ .../java/CHIPDeviceController-JNI.cpp | 23 ++ .../ChipDeviceController.java | 21 ++ .../devicecontroller/DiagnosticLogType.java | 52 ++++ .../devicecontroller/DownloadLogCallback.java | 49 +++ src/protocols/bdx/BdxUri.h | 2 + 25 files changed, 1341 insertions(+) create mode 100644 examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/DiagnosticLogFragment.kt create mode 100644 examples/android/CHIPTool/app/src/main/res/layout/diagnostic_log_fragment.xml create mode 100644 examples/android/CHIPTool/app/src/main/res/xml/file_paths.xml create mode 100644 examples/java-matter-controller/java/src/com/matter/controller/commands/bdx/DownloadLogCommand.kt create mode 100644 examples/java-matter-controller/java/src/com/matter/controller/commands/bdx/PairOnNetworkLongDownloadLogCommand.kt create mode 100755 scripts/tests/java/bdx_test.py create mode 100644 src/controller/java/AndroidLogDownloadFromNode.cpp create mode 100644 src/controller/java/AndroidLogDownloadFromNode.h create mode 100644 src/controller/java/BdxDiagnosticLogsReceiver.cpp create mode 100644 src/controller/java/BdxDiagnosticLogsReceiver.h create mode 100644 src/controller/java/src/chip/devicecontroller/DiagnosticLogType.java create mode 100644 src/controller/java/src/chip/devicecontroller/DownloadLogCallback.java diff --git a/.github/workflows/java-tests.yaml b/.github/workflows/java-tests.yaml index 504cb865a9cc0b..473cd482357a75 100644 --- a/.github/workflows/java-tests.yaml +++ b/.github/workflows/java-tests.yaml @@ -236,6 +236,17 @@ jobs: --tool-args "onnetwork-long --nodeid 1 --setup-pin-code 20202021 --discriminator 3840 -t 1000" \ --factoryreset \ ' + - name: Run Pairing Onnetwork and get diagnostic log Test + run: | + scripts/run_in_python_env.sh out/venv \ + './scripts/tests/run_java_test.py \ + --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app \ + --app-args "--discriminator 3840 --interface-id -1 --crash_log ./crashLog.log --end_user_support_log ./enduser.log --network_diagnostics_log ./network.log" \ + --tool-path out/linux-x64-java-matter-controller \ + --tool-cluster "bdx" \ + --tool-args "onnetwork-long-downloadLog --nodeid 1 --setup-pin-code 20202021 --discriminator 3840 -t 3000 --logType CrashLogs --fileName ./crashLog.log" \ + --factoryreset \ + ' - name: Run Pairing Onnetwork Test run: | scripts/run_in_python_env.sh out/venv \ diff --git a/examples/android/CHIPTool/app/src/main/AndroidManifest.xml b/examples/android/CHIPTool/app/src/main/AndroidManifest.xml index 0526dc5a78160d..efd089817efe68 100644 --- a/examples/android/CHIPTool/app/src/main/AndroidManifest.xml +++ b/examples/android/CHIPTool/app/src/main/AndroidManifest.xml @@ -46,6 +46,15 @@ + + + diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt index 69bfdc109912c9..fb8141e72d33a8 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt @@ -72,6 +72,7 @@ class SelectActionFragment : Fragment() { binding.provisionCustomFlowBtn.setOnClickListener { handleProvisionCustomFlowClicked() } binding.wildcardBtn.setOnClickListener { handleWildcardClicked() } binding.unpairDeviceBtn.setOnClickListener { handleUnpairDeviceClicked() } + binding.diagnosticLogBtn.setOnClickListener { handleDiagnosticLogClicked() } binding.groupSettingBtn.setOnClickListener { handleGroupSettingClicked() } binding.otaProviderBtn.setOnClickListener { handleOTAProviderClicked() } binding.icdBtn.setOnClickListener { handleICDClicked() } @@ -225,6 +226,10 @@ class SelectActionFragment : Fragment() { showFragment(OtaProviderClientFragment.newInstance()) } + private fun handleDiagnosticLogClicked() { + showFragment(DiagnosticLogFragment.newInstance()) + } + /** Notifies listener of provision-WiFi-credentials button click. */ private fun handleProvisionWiFiCredentialsClicked() { getCallback()?.setNetworkType(ProvisionNetworkType.WIFI) diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/DiagnosticLogFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/DiagnosticLogFragment.kt new file mode 100644 index 00000000000000..ea7d5438d247c3 --- /dev/null +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/DiagnosticLogFragment.kt @@ -0,0 +1,172 @@ +package com.google.chip.chiptool.clusterclient + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.os.Environment +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import androidx.core.content.FileProvider +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import chip.devicecontroller.ChipDeviceController +import chip.devicecontroller.DiagnosticLogType +import chip.devicecontroller.DownloadLogCallback +import com.google.chip.chiptool.ChipClient +import com.google.chip.chiptool.R +import com.google.chip.chiptool.databinding.DiagnosticLogFragmentBinding +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +class DiagnosticLogFragment : Fragment() { + private val deviceController: ChipDeviceController + get() = ChipClient.getDeviceController(requireContext()) + + private lateinit var scope: CoroutineScope + + private lateinit var addressUpdateFragment: AddressUpdateFragment + + private var _binding: DiagnosticLogFragmentBinding? = null + private val binding + get() = _binding!! + + private val timeout: Long + get() = binding.timeoutEd.text.toString().toULongOrNull()?.toLong() ?: 0L + + private val diagnosticLogTypeList = DiagnosticLogType.values() + private val diagnosticLogType: DiagnosticLogType + get() = diagnosticLogTypeList[binding.diagnosticTypeSp.selectedItemPosition] + + private var mDownloadFile: File? = null + private var mDownloadFileOutputStream: FileOutputStream? = null + + private var mReceiveFileLen = 0U + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = DiagnosticLogFragmentBinding.inflate(inflater, container, false) + scope = viewLifecycleOwner.lifecycleScope + + addressUpdateFragment = + childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment + + binding.getDiagnosticLogBtn.setOnClickListener { scope.launch { getDiagnosticLogClick() } } + + binding.diagnosticTypeSp.adapter = + ArrayAdapter( + requireContext(), + android.R.layout.simple_spinner_dropdown_item, + diagnosticLogTypeList + ) + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + inner class ChipDownloadLogCallback : DownloadLogCallback { + override fun onError(fabricIndex: Int, nodeId: Long, errorCode: Long) { + Log.d(TAG, "onError: $fabricIndex, ${nodeId.toULong()}, $errorCode") + showMessage("Downloading Failed") + mDownloadFileOutputStream?.flush() ?: return + } + + override fun onSuccess(fabricIndex: Int, nodeId: Long) { + Log.d(TAG, "onSuccess: $fabricIndex, ${nodeId.toULong()}") + mDownloadFileOutputStream?.flush() ?: return + showMessage("Downloading Completed") + mDownloadFile?.let { showNotification(it) } ?: return + } + + override fun onTransferData(fabricIndex: Int, nodeId: Long, data: ByteArray): Boolean { + Log.d(TAG, "onTransferData : ${data.size}") + if (mDownloadFileOutputStream == null) { + Log.d(TAG, "mDownloadFileOutputStream or mDownloadFile is null") + return false + } + return addData(mDownloadFileOutputStream!!, data) + } + + private fun addData(outputStream: FileOutputStream, data: ByteArray): Boolean { + try { + outputStream.write(data) + } catch (e: IOException) { + Log.d(TAG, "IOException", e) + return false + } + mReceiveFileLen += data.size.toUInt() + showMessage("Receive Data Size : $mReceiveFileLen") + return true + } + } + + private fun getDiagnosticLogClick() { + mDownloadFile = + createLogFile( + deviceController.fabricIndex.toUInt(), + addressUpdateFragment.deviceId.toULong(), + diagnosticLogType + ) + mDownloadFileOutputStream = FileOutputStream(mDownloadFile) + deviceController.downloadLogFromNode( + addressUpdateFragment.deviceId, + diagnosticLogType, + timeout, + ChipDownloadLogCallback() + ) + } + + private fun isExternalStorageWritable(): Boolean { + return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED + } + + private fun createLogFile(fabricIndex: UInt, nodeId: ULong, type: DiagnosticLogType): File? { + if (!isExternalStorageWritable()) { + return null + } + val now = System.currentTimeMillis() + val fileName = "${type}_${fabricIndex}_${nodeId}_$now.txt" + mReceiveFileLen = 0U + return File(requireContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), fileName) + } + + private fun showNotification(file: File) { + val intent = + Intent(Intent.ACTION_VIEW).apply { + setDataAndType(getFileUri(file), "text/plain") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + } + + requireActivity().startActivity(intent) + } + + private fun getFileUri(file: File): Uri { + return FileProvider.getUriForFile( + requireContext(), + "${requireContext().packageName}.provider", + file + ) + } + + private fun showMessage(msg: String) { + requireActivity().runOnUiThread { binding.diagnosticLogTv.text = msg } + } + + companion object { + private const val TAG = "DiagnosticLogFragment" + + fun newInstance(): DiagnosticLogFragment = DiagnosticLogFragment() + } +} diff --git a/examples/android/CHIPTool/app/src/main/res/layout/diagnostic_log_fragment.xml b/examples/android/CHIPTool/app/src/main/res/layout/diagnostic_log_fragment.xml new file mode 100644 index 00000000000000..56b770a645b442 --- /dev/null +++ b/examples/android/CHIPTool/app/src/main/res/layout/diagnostic_log_fragment.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + +