diff --git a/.github/workflows/examples-cc13xx_26xx.yaml b/.github/workflows/examples-cc13xx_26xx.yaml index 86f789326cf473..b486415dbcc1ee 100644 --- a/.github/workflows/examples-cc13xx_26xx.yaml +++ b/.github/workflows/examples-cc13xx_26xx.yaml @@ -15,11 +15,15 @@ name: Build example - TI CC13XX_26XX on: - push: - branches-ignore: - - "dependabot/**" - pull_request: - merge_group: + workflow_dispatch: + # Temporarely disabled: + # - TI CI runs out of disk space + # - Image should be updated to an Ubuntu 24.04 or higher based one (move from :54 version) + # push: + # branches-ignore: + # - 'dependabot/**' + # pull_request: + # merge_group: concurrency: group: diff --git a/.github/workflows/examples-cc32xx.yaml b/.github/workflows/examples-cc32xx.yaml index 4c9e50a5ca33ac..091a5eeabc4361 100644 --- a/.github/workflows/examples-cc32xx.yaml +++ b/.github/workflows/examples-cc32xx.yaml @@ -15,11 +15,15 @@ name: Build example - TI CC32XX on: - push: - branches-ignore: - - 'dependabot/**' - pull_request: - merge_group: + workflow_dispatch: + # Temporarely disabled: + # - TI CI runs out of disk space + # - Image should be updated to an Ubuntu 24.04 or higher based one (move from :54 version) + # push: + # branches-ignore: + # - 'dependabot/**' + # pull_request: + # merge_group: concurrency: group: ${{ github.ref }}-${{ github.workflow }}-${{ (github.event_name == 'pull_request' && github.event.number) || (github.event_name == 'workflow_dispatch' && github.run_number) || github.sha }} diff --git a/docs/guides/fabric_synchronization_guide.md b/docs/guides/fabric_synchronization_guide.md index 1b545ce36ead27..b2cfd26d9f439e 100644 --- a/docs/guides/fabric_synchronization_guide.md +++ b/docs/guides/fabric_synchronization_guide.md @@ -2,7 +2,9 @@ - [Fabric Synchronization Guide](#fabric-synchronization-guide) - [Fabric Sync Example Applications](#fabric-sync-example-applications) - - [Run Fabric Sync Demo on RP4](#run-fabric-sync-demo-on-rp4) + - [Bootstrap Fabric Sync Demo on Linux](#bootstrap-fabric-sync-demo-on-linux) + - [Bootstrap Fabric Sync Demo on RP4](#bootstrap-fabric-sync-demo-on-rp4) + - [Run Fabric Sync Demo](#run-fabric-sync-demo) ## Fabric Sync Example Applications @@ -38,27 +40,29 @@ enables a seamless and efficient synchronization process. [Fabric-Bridge](https://github.com/project-chip/connectedhomeip/tree/master/examples/fabric-bridge-app/linux/README.md) -## Run Fabric Sync Demo on RP4 +## Bootstrap Fabric Sync Demo on Linux -### Setup Fabric Source +### Start Fabric Synchronization on Ecosystem 1 -Connect to the Fabric Source server: +Run the Fabric Synchronization script: ``` -ssh ubuntu@xxx.xxx.xxx.xxx +./examples/fabric-admin/scripts/run_fabric_sync.sh ``` -Password: +### Start Fabric Synchronization on Ecosystem 2 -Run the Fabric Source script: +Run the Fabric Synchronization script: ``` -./run_fabric_source.sh +./examples/fabric-admin/scripts/run_fabric_sync.sh ``` -### Setup Fabric Sink +## Bootstrap Fabric Sync Demo on RP4 -Connect to the Fabric Sink server: +### Start Fabric Synchronization on Ecosystem 1 + +Connect to the Ecosystem 1 server: ``` ssh ubuntu@xxx.xxx.xxx.xxx @@ -66,29 +70,41 @@ ssh ubuntu@xxx.xxx.xxx.xxx Password: -Run the Fabric Sink script: +Run the Fabric Synchronization script: ``` -./run_fabric_sink.sh +./run_fabric_sync.sh ``` -### Fabric Sync Setup +### Start Fabric Synchronization on Ecosystem 2 + +Connect to the Ecosystem 2 server: + +``` +ssh ubuntu@xxx.xxx.xxx.xxx +``` -Enable Fabric Auto Sync: +Password: -In Fabric-Sync console: +Run the Fabric Synchronization script: ``` -fabricsync enable-auto-sync 1 +./run_fabric_sync.sh ``` -Pair the Fabric-Source bridge to Fabric-Sync with node ID 1: +## Run Fabric Sync Demo + +### Fabric Sync Setup + +In Ecosystem 1 Fabric-Admin console: + +Pair the Ecosystem 2 bridge to Ecosystem 1 with node ID 2: ``` -fabricsync add-bridge 1 +fabricsync add-bridge 2 ``` -### Pair Light Example to Fabric-Source +### Pair Light Example to Ecosystem 2 Since Fabric-Bridge also functions as a Matter server, running it alongside the Light Example app on the same machine would cause conflicts. Therefore, you need @@ -114,26 +130,47 @@ Pair the Light Example with node ID 3 using its payload number: pairing already-discovered 3 20202021 5540 ``` -After the Light Example is successfully paired in Fabric-Source, it will be -synced to Fabric-Sink with a new assigned node ID. +After the device is successfully added, you will observe the following on +Ecosystem 2 with the newly assigned Node ID: + +``` +>>> New device with Node ID: 0x3 has been successfully added. +``` + +Additionally, you should also get notified when a new device is added to +Ecosystem 2 from the Ecosystem 1: + +``` +>>> A new device is added on Endpoint 3. +``` + +### Synchronize Light Example to Ecosystem 1 + +After the Light Example is successfully paired in Ecosystem 2, we can start to +synchronize the light device to Ecosystem 1 using the new assigned dynamic +endpointid on Ecosystem 2. + +``` +fabricsync sync-device +``` Toggle the Light Example: -From Fabric-Source: +From Ecosystem 1: ``` onoff on 1 onoff off 1 ``` -From Fabric-Sink: (Use the node ID assigned) +From Ecosystem 2: (Use the node ID assigned) ``` onoff on x 1 onoff off x 1 ``` -### Remove Light Example from Fabric-Source +### Remove Light Example from Ecosystem Unpair the Light Example: @@ -141,9 +178,6 @@ Unpair the Light Example: pairing unpair ``` -After the Light Example is successfully unpaired from Fabric-Source, it will -also be removed from the Fabric-Sink. - ### Pair Commercial Switch to Fabric-Source Pair the switch using its payload number: @@ -154,32 +188,36 @@ In Fabric-Source console: pairing code-wifi ``` -After the switch is successfully paired in Fabric-Source, it will be synced to -Fabric-Sink with a new assigned node ID. +### Synchronize Switch to Ecosystem 1 + +After the switch is successfully paired in Ecosystem 2, we can start to +synchronize it to Ecosystem 1 using the new assigned dynamic endpointid on +Ecosystem 2.. + +``` +fabricsync sync-device +``` Toggle the switch: -From Fabric-Source: +From Ecosystem 1: ``` onoff on 1 onoff off 1 ``` -From Fabric-Sink: (Use the node ID assigned) +From Ecosystem 2: (Use the node ID assigned) ``` onoff on 1 onoff off 1 ``` -### Remove Switch from Fabric-Source +### Remove Switch from Ecosystem Unpair the switch: ``` pairing unpair ``` - -After the switch is successfully unpaired from Fabric-Source, it will also be -removed from the Fabric-Sink. diff --git a/examples/fabric-admin/commands/fabric-sync/Commands.h b/examples/fabric-admin/commands/fabric-sync/Commands.h index 94de1d31d8ba09..a6bf1c258f9475 100644 --- a/examples/fabric-admin/commands/fabric-sync/Commands.h +++ b/examples/fabric-admin/commands/fabric-sync/Commands.h @@ -28,6 +28,8 @@ void registerCommandsFabricSync(Commands & commands, CredentialIssuerCommands * commands_list clusterCommands = { make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), }; diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp index dade5932fba758..704996d189d9c2 100644 --- a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp @@ -32,10 +32,6 @@ using namespace ::chip; namespace { -// Constants -constexpr uint32_t kCommissionPrepareTimeMs = 500; -constexpr uint16_t kMaxManaulCodeLength = 21; - void CheckFabricBridgeSynchronizationSupport(intptr_t ignored) { DeviceMgr().ReadSupportedDeviceCategories(); @@ -43,7 +39,7 @@ void CheckFabricBridgeSynchronizationSupport(intptr_t ignored) } // namespace -void FabricSyncAddBridgeCommand::OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err) +void FabricSyncAddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) { if (mBridgeNodeId != deviceId) { @@ -90,7 +86,7 @@ CHIP_ERROR FabricSyncAddBridgeCommand::RunCommand(NodeId remoteId) if (DeviceMgr().IsFabricSyncReady()) { // print to console - fprintf(stderr, "Remote Fabric Bridge has been alread configured."); + fprintf(stderr, "Remote Fabric Bridge has already been configured."); return CHIP_NO_ERROR; } @@ -98,7 +94,7 @@ CHIP_ERROR FabricSyncAddBridgeCommand::RunCommand(NodeId remoteId) if (pairingCommand == nullptr) { - ChipLogError(NotSpecified, "Pairing onnetwork command is not available"); + ChipLogError(NotSpecified, "Pairing already-discovered command is not available"); return CHIP_ERROR_NOT_IMPLEMENTED; } @@ -110,7 +106,7 @@ CHIP_ERROR FabricSyncAddBridgeCommand::RunCommand(NodeId remoteId) return CHIP_NO_ERROR; } -void FabricSyncRemoveBridgeCommand::OnDeviceRemoved(chip::NodeId deviceId, CHIP_ERROR err) +void FabricSyncRemoveBridgeCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) { if (mBridgeNodeId != deviceId) { @@ -150,7 +146,7 @@ CHIP_ERROR FabricSyncRemoveBridgeCommand::RunCommand() if (pairingCommand == nullptr) { - ChipLogError(NotSpecified, "Pairing code command is not available"); + ChipLogError(NotSpecified, "Pairing unpair command is not available"); return CHIP_ERROR_NOT_IMPLEMENTED; } @@ -161,13 +157,116 @@ CHIP_ERROR FabricSyncRemoveBridgeCommand::RunCommand() return CHIP_NO_ERROR; } +void FabricSyncAddLocalBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) +{ + if (mLocalBridgeNodeId != deviceId) + { + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to pair non-bridge device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + else + { + ChipLogProgress(NotSpecified, "Commissioning complete for non-bridge device: NodeId: " ChipLogFormatX64, + ChipLogValueX64(deviceId)); + } + return; + } + + if (err == CHIP_NO_ERROR) + { + DeviceMgr().SetLocalBridgeNodeId(mLocalBridgeNodeId); + ChipLogProgress(NotSpecified, "Successfully paired local bridge device: NodeId: " ChipLogFormatX64, + ChipLogValueX64(mLocalBridgeNodeId)); + } + else + { + ChipLogError(NotSpecified, "Failed to pair local bridge device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + + mLocalBridgeNodeId = kUndefinedNodeId; +} + +CHIP_ERROR FabricSyncAddLocalBridgeCommand::RunCommand(NodeId deviceId) +{ + if (DeviceMgr().IsLocalBridgeReady()) + { + // print to console + fprintf(stderr, "Local Fabric Bridge has already been configured."); + return CHIP_NO_ERROR; + } + + PairingCommand * pairingCommand = static_cast(CommandMgr().GetCommandByName("pairing", "already-discovered")); + VerifyOrDie(pairingCommand != nullptr); + + pairingCommand->RegisterCommissioningDelegate(this); + mLocalBridgeNodeId = deviceId; + + DeviceMgr().PairLocalFabricBridge(deviceId); + + return CHIP_NO_ERROR; +} + +void FabricSyncRemoveLocalBridgeCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) +{ + if (mLocalBridgeNodeId != deviceId) + { + ChipLogProgress(NotSpecified, "A non-bridge device: NodeId: " ChipLogFormatX64 " is removed.", ChipLogValueX64(deviceId)); + return; + } + + if (err == CHIP_NO_ERROR) + { + DeviceMgr().SetLocalBridgeNodeId(kUndefinedNodeId); + ChipLogProgress(NotSpecified, "Successfully removed local bridge device: NodeId: " ChipLogFormatX64, + ChipLogValueX64(mLocalBridgeNodeId)); + } + else + { + ChipLogError(NotSpecified, "Failed to remove local bridge device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + + mLocalBridgeNodeId = kUndefinedNodeId; +} + +CHIP_ERROR FabricSyncRemoveLocalBridgeCommand::RunCommand() +{ + NodeId bridgeNodeId = DeviceMgr().GetLocalBridgeNodeId(); + + if (bridgeNodeId == kUndefinedNodeId) + { + // print to console + fprintf(stderr, "Local Fabric Bridge is not configured yet, nothing to remove."); + return CHIP_NO_ERROR; + } + + mLocalBridgeNodeId = bridgeNodeId; + + PairingCommand * pairingCommand = static_cast(CommandMgr().GetCommandByName("pairing", "unpair")); + + if (pairingCommand == nullptr) + { + ChipLogError(NotSpecified, "Pairing unpair command is not available"); + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + pairingCommand->RegisterPairingDelegate(this); + + DeviceMgr().UnpairLocalFabricBridge(); + + return CHIP_NO_ERROR; +} + void FabricSyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ERROR err, chip::SetupPayload payload) { ChipLogProgress(NotSpecified, "FabricSyncDeviceCommand::OnCommissioningWindowOpened"); if (err == CHIP_NO_ERROR) { - char payloadBuffer[kMaxManaulCodeLength + 1]; + char payloadBuffer[kMaxManualCodeLength + 1]; MutableCharSpan manualCode(payloadBuffer); CHIP_ERROR error = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualCode); if (error == CHIP_NO_ERROR) @@ -202,7 +301,7 @@ void FabricSyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ } } -void FabricSyncDeviceCommand::OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err) +void FabricSyncDeviceCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) { if (mAssignedNodeId != deviceId) { @@ -252,6 +351,8 @@ CHIP_ERROR FabricAutoSyncCommand::RunCommand(bool enableAutoSync) // print to console fprintf(stderr, "Auto Fabric Sync is %s.\n", enableAutoSync ? "enabled" : "disabled"); + fprintf(stderr, + "WARNING: The auto-sync command is currently under development and may contain bugs. Use it at your own risk.\n"); return CHIP_NO_ERROR; } diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h index ca1b105207f832..1bbd22d293f39d 100644 --- a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h @@ -22,6 +22,10 @@ #include #include +// Constants +constexpr uint32_t kCommissionPrepareTimeMs = 500; +constexpr uint16_t kMaxManualCodeLength = 21; + class FabricSyncAddBridgeCommand : public CHIPCommand, public CommissioningDelegate { public: @@ -31,7 +35,7 @@ class FabricSyncAddBridgeCommand : public CHIPCommand, public CommissioningDeleg AddArgument("device-remote-ip", &mRemoteAddr); } - void OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) override; + void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err) override; /////////// CHIPCommand Interface ///////// CHIP_ERROR RunCommand() override { return RunCommand(mNodeId); } @@ -63,6 +67,47 @@ class FabricSyncRemoveBridgeCommand : public CHIPCommand, public PairingDelegate chip::NodeId mBridgeNodeId; }; +class FabricSyncAddLocalBridgeCommand : public CHIPCommand, public CommissioningDelegate +{ +public: + FabricSyncAddLocalBridgeCommand(CredentialIssuerCommands * credIssuerCommands) : + CHIPCommand("add-local-bridge", credIssuerCommands) + { + AddArgument("nodeid", 0, UINT64_MAX, &mNodeId); + } + + void OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) override; + + /////////// CHIPCommand Interface ///////// + CHIP_ERROR RunCommand() override { return RunCommand(mNodeId); } + + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(1); } + +private: + chip::NodeId mNodeId; + chip::NodeId mLocalBridgeNodeId; + + CHIP_ERROR RunCommand(chip::NodeId deviceId); +}; + +class FabricSyncRemoveLocalBridgeCommand : public CHIPCommand, public PairingDelegate +{ +public: + FabricSyncRemoveLocalBridgeCommand(CredentialIssuerCommands * credIssuerCommands) : + CHIPCommand("remove-local-bridge", credIssuerCommands) + {} + + void OnDeviceRemoved(chip::NodeId deviceId, CHIP_ERROR err) override; + + /////////// CHIPCommand Interface ///////// + CHIP_ERROR RunCommand() override; + + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(1); } + +private: + chip::NodeId mLocalBridgeNodeId; +}; + class FabricSyncDeviceCommand : public CHIPCommand, public CommissioningWindowDelegate, public CommissioningDelegate { public: diff --git a/examples/fabric-admin/device_manager/DeviceManager.cpp b/examples/fabric-admin/device_manager/DeviceManager.cpp index 4207378670f44e..17adcc2427f9c6 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.cpp +++ b/examples/fabric-admin/device_manager/DeviceManager.cpp @@ -33,6 +33,7 @@ namespace { // Constants constexpr uint32_t kSetupPinCode = 20202021; constexpr uint16_t kRemoteBridgePort = 5540; +constexpr uint16_t kLocalBridgePort = 5540; constexpr uint16_t kWindowTimeout = 300; constexpr uint16_t kIteration = 1000; constexpr uint16_t kSubscribeMinInterval = 0; @@ -117,6 +118,8 @@ void DeviceManager::RemoveSyncedDevice(NodeId nodeId) void DeviceManager::OpenDeviceCommissioningWindow(NodeId nodeId, uint32_t commissioningTimeout, uint32_t iterations, uint32_t discriminator, const char * saltHex, const char * verifierHex) { + ChipLogProgress(NotSpecified, "Open the commissioning window of device with NodeId:" ChipLogFormatX64, ChipLogValueX64(nodeId)); + // Open the commissioning window of a device within its own fabric. StringBuilder commandBuilder; @@ -132,7 +135,7 @@ void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpoin // Open the commissioning window of a device from another fabric via its fabric bridge. // This method constructs and sends a command to open the commissioning window for a device // that is part of a different fabric, accessed through a fabric bridge. - StringBuilder<512> commandBuilder; + StringBuilder commandBuilder; // Use random discriminator to have less chance of collission. uint16_t discriminator = @@ -166,6 +169,16 @@ void DeviceManager::PairRemoteDevice(chip::NodeId nodeId, const char * payload) PushCommand(commandBuilder.c_str()); } +void DeviceManager::PairLocalFabricBridge(NodeId nodeId) +{ + StringBuilder commandBuilder; + + commandBuilder.Add("pairing already-discovered "); + commandBuilder.AddFormat("%lu %d ::1 %d", nodeId, kSetupPinCode, kLocalBridgePort); + + PushCommand(commandBuilder.c_str()); +} + void DeviceManager::UnpairRemoteFabricBridge() { StringBuilder commandBuilder; @@ -176,6 +189,16 @@ void DeviceManager::UnpairRemoteFabricBridge() PushCommand(commandBuilder.c_str()); } +void DeviceManager::UnpairLocalFabricBridge() +{ + StringBuilder commandBuilder; + + commandBuilder.Add("pairing unpair "); + commandBuilder.AddFormat("%lu", mLocalBridgeNodeId); + + PushCommand(commandBuilder.c_str()); +} + void DeviceManager::SubscribeRemoteFabricBridge() { // Listen to the state changes of the remote fabric bridge. @@ -331,7 +354,8 @@ void DeviceManager::HandleAttributeData(const app::ConcreteDataAttributePath & p // Process added endpoints for (const auto & endpoint : addedEndpoints) { - ChipLogProgress(NotSpecified, "Endpoint added: %u", endpoint); + // print to console + fprintf(stderr, "A new devie is added on Endpoint: %u\n", endpoint); if (mAutoSyncEnabled) { diff --git a/examples/fabric-admin/device_manager/DeviceManager.h b/examples/fabric-admin/device_manager/DeviceManager.h index cad573a9311421..454986bd7a40f0 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.h +++ b/examples/fabric-admin/device_manager/DeviceManager.h @@ -55,14 +55,20 @@ class DeviceManager : public PairingDelegate chip::NodeId GetRemoteBridgeNodeId() const { return mRemoteBridgeNodeId; } + chip::NodeId GetLocalBridgeNodeId() const { return mLocalBridgeNodeId; } + void UpdateLastUsedNodeId(chip::NodeId nodeId); - void SetRemoteBridgeNodeId(chip::NodeId remoteBridgeNodeId) { mRemoteBridgeNodeId = remoteBridgeNodeId; } + void SetRemoteBridgeNodeId(chip::NodeId nodeId) { mRemoteBridgeNodeId = nodeId; } + + void SetLocalBridgeNodeId(chip::NodeId nodeId) { mLocalBridgeNodeId = nodeId; } bool IsAutoSyncEnabled() const { return mAutoSyncEnabled; } bool IsFabricSyncReady() const { return mRemoteBridgeNodeId != chip::kUndefinedNodeId; } + bool IsLocalBridgeReady() const { return mLocalBridgeNodeId != chip::kUndefinedNodeId; } + void EnableAutoSync(bool state) { mAutoSyncEnabled = state; } void AddSyncedDevice(const Device & device); @@ -126,8 +132,20 @@ class DeviceManager : public PairingDelegate */ void PairRemoteDevice(chip::NodeId nodeId, const char * payload); + /** + * @brief Pair a local fabric bridge with a given node ID. + * + * This function initiates the pairing process for the local fabric bridge using the specified parameters. + + * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, + * as for the first fabric. + */ + void PairLocalFabricBridge(chip::NodeId nodeId); + void UnpairRemoteFabricBridge(); + void UnpairLocalFabricBridge(); + void SubscribeRemoteFabricBridge(); void StartReverseCommissioning(); @@ -147,8 +165,16 @@ class DeviceManager : public PairingDelegate static DeviceManager sInstance; - chip::NodeId mLastUsedNodeId = 0; + chip::NodeId mLastUsedNodeId = 0; + + // The Node ID of the remote bridge used for Fabric-Sync + // This represents the bridge on the other ecosystem. chip::NodeId mRemoteBridgeNodeId = chip::kUndefinedNodeId; + + // The Node ID of the local bridge used for Fabric-Sync + // This represents the bridge within its own ecosystem. + chip::NodeId mLocalBridgeNodeId = chip::kUndefinedNodeId; + std::set mSyncedDevices; bool mAutoSyncEnabled = false; bool mInitialized = false; diff --git a/examples/fabric-admin/scripts/run_fabric_sink.sh b/examples/fabric-admin/scripts/run_fabric_sink.sh deleted file mode 100755 index 3013965479268a..00000000000000 --- a/examples/fabric-admin/scripts/run_fabric_sink.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/bash - -# Default paths -DEFAULT_CHOICES=( - "./fabric-admin" - "out/debug/standalone/fabric-admin" - "out/linux-x64-fabric-admin/fabric-admin" - "out/darwin-arm64-fabric-admin/fabric-admin" -) -FABRIC_ADMIN_LOG="/tmp/fabric_admin.log" -FABRIC_ADMIN_PATH="" - -# Function to find fabric-admin binary -find_fabric_admin() { - local choices=("$@") - for path in "${choices[@]}"; do - if [[ -e "$path" ]]; then - echo "$path" - return 0 - fi - done - return 1 -} - -# Parse arguments -VERBOSE=false -SPECIFIED_PATH="" - -for arg in "$@"; do - case $arg in - --verbose) - VERBOSE=true - ;; - --path=*) - SPECIFIED_PATH="${arg#*=}" - ;; - esac -done - -# Use specified path if provided -if [[ -n "$SPECIFIED_PATH" ]]; then - if [[ -e "$SPECIFIED_PATH" ]]; then - FABRIC_ADMIN_PATH="$SPECIFIED_PATH" - else - echo >&2 "Specified path does not exist: $SPECIFIED_PATH" - exit 1 - fi -else - FABRIC_ADMIN_PATH=$(find_fabric_admin "${DEFAULT_CHOICES[@]}") - if [[ $? -ne 0 ]]; then - echo >&2 "Could not find the fabric-admin binary" - exit 1 - fi -fi - -echo "PATH IS: $FABRIC_ADMIN_PATH" - -# Kill fabric-admin if it is running -echo "Checking for running fabric-admin process..." -fabric_admin_pid=$(pgrep -f "$FABRIC_ADMIN_PATH") -if [[ -n "$fabric_admin_pid" ]]; then - echo "Found fabric-admin with PID $fabric_admin_pid, attempting to kill..." - kill -9 "$fabric_admin_pid" - echo "Killed fabric-admin with PID $fabric_admin_pid" -fi - -# Remove /tmp/chip_* files and directories -echo "Removing /tmp/chip_* files and directories..." -sudo rm -rf /tmp/chip_* -echo "Removed /tmp/chip_* files and directories" - -# Start fabric-admin with or without log file path based on --verbose option -echo "Starting fabric-admin..." -if [ "$VERBOSE" = true ]; then - "$FABRIC_ADMIN_PATH" -else - "$FABRIC_ADMIN_PATH" --log-file-path "$FABRIC_ADMIN_LOG" -fi diff --git a/examples/fabric-admin/scripts/run_fabric_source.sh b/examples/fabric-admin/scripts/run_fabric_sync.sh similarity index 85% rename from examples/fabric-admin/scripts/run_fabric_source.sh rename to examples/fabric-admin/scripts/run_fabric_sync.sh index 95df7a135bb596..8c820d111c37c1 100755 --- a/examples/fabric-admin/scripts/run_fabric_source.sh +++ b/examples/fabric-admin/scripts/run_fabric_sync.sh @@ -86,19 +86,19 @@ fi echo "Admin path: $FABRIC_ADMIN_PATH" echo "Bridge path: $FABRIC_BRIDGE_APP_PATH" -# Determine the path to stop_fabric_source.sh based on the location of run_fabric_source.sh -RUN_FABRIC_SOURCE_PATH=$(find_binary "$SCRIPT_DIR/run_fabric_source.sh") +# Determine the path to stop_fabric_sync.sh based on the location of run_fabric_sync.sh +RUN_FABRIC_SOURCE_PATH=$(find_binary "$SCRIPT_DIR/run_fabric_sync.sh") if [[ $? -ne 0 ]]; then - echo >&2 "Could not find the run_fabric_source.sh script" + echo >&2 "Could not find the run_fabric_sync.sh script" exit 1 fi -STOP_FABRIC_SOURCE_PATH="${RUN_FABRIC_SOURCE_PATH/run_fabric_source/stop_fabric_source}" +STOP_FABRIC_SYNC_PATH="${RUN_FABRIC_SOURCE_PATH/run_fabric_sync/stop_fabric_sync}" # Stop any running instances and clean up -if [[ -e "$STOP_FABRIC_SOURCE_PATH" ]]; then - "$STOP_FABRIC_SOURCE_PATH" +if [[ -e "$STOP_FABRIC_SYNC_PATH" ]]; then + "$STOP_FABRIC_SYNC_PATH" else - echo >&2 "Could not find the stop_fabric_source.sh script" + echo >&2 "Could not find the stop_fabric_sync.sh script" exit 1 fi diff --git a/examples/fabric-admin/scripts/stop_fabric_source.sh b/examples/fabric-admin/scripts/stop_fabric_sync.sh similarity index 100% rename from examples/fabric-admin/scripts/stop_fabric_source.sh rename to examples/fabric-admin/scripts/stop_fabric_sync.sh diff --git a/examples/rvc-app/rvc-common/include/rvc-service-area-delegate.h b/examples/rvc-app/rvc-common/include/rvc-service-area-delegate.h index 4c13fcd493d7eb..fdad4f83f0666a 100644 --- a/examples/rvc-app/rvc-common/include/rvc-service-area-delegate.h +++ b/examples/rvc-app/rvc-common/include/rvc-service-area-delegate.h @@ -21,7 +21,7 @@ #include #include #include -#include +#include namespace chip { namespace app { diff --git a/integrations/docker/images/base/chip-build/version b/integrations/docker/images/base/chip-build/version index dfc4231a8e7a46..0ca6f37e4e236e 100644 --- a/integrations/docker/images/base/chip-build/version +++ b/integrations/docker/images/base/chip-build/version @@ -1 +1 @@ -73 : [Telink] Update Docker image (Zephyr update) +74 : Update Silabs docker SiSDK 2024.06.1 WiseConnect 3.3.1 Wiseconnect Wifi bt sdk 2.10.0 diff --git a/integrations/docker/images/stage-2/chip-build-efr32/Dockerfile b/integrations/docker/images/stage-2/chip-build-efr32/Dockerfile index 7927c5ef1ed4fc..4de8beb62a81be 100644 --- a/integrations/docker/images/stage-2/chip-build-efr32/Dockerfile +++ b/integrations/docker/images/stage-2/chip-build-efr32/Dockerfile @@ -13,8 +13,8 @@ RUN set -x \ && : # last line -# Download Simplicity SDK v2024.6.0 (a1a37fa) -RUN wget https://github.com/SiliconLabs/simplicity_sdk/releases/download/v2024.6.0/sisdk-sdk.zip -O /tmp/simplicity_sdk.zip \ +# Download Simplicity SDK v2024.6.1 (a1a37fa) +RUN wget https://github.com/SiliconLabs/simplicity_sdk/releases/download/v2024.6.1-0/sisdk-sdk.zip -O /tmp/simplicity_sdk.zip \ && unzip /tmp/simplicity_sdk.zip -d /tmp/simplicity_sdk \ && rm -rf /tmp/simplicity_sdk.zip \ # Deleting files that are not needed to save space @@ -23,14 +23,14 @@ RUN wget https://github.com/SiliconLabs/simplicity_sdk/releases/download/v2024.6 && find /tmp/simplicity_sdk/protocol/openthread -name "*efr32mg21*" -delete \ && : # last line -# Clone WiSeConnect Wi-Fi and Bluetooth Software 2.8.2 (4fa5c5f) -RUN git clone --depth=1 --single-branch --branch=2.8.2 https://github.com/SiliconLabs/wiseconnect-wifi-bt-sdk.git /tmp/wiseconnect-wifi-bt-sdk && \ +# Clone WiSeConnect Wi-Fi and Bluetooth Software 2.10.0 (f94b83d) +RUN git clone --depth=1 --single-branch --branch=2.10.0 https://github.com/SiliconLabs/wiseconnect-wifi-bt-sdk.git /tmp/wiseconnect-wifi-bt-sdk && \ cd /tmp/wiseconnect-wifi-bt-sdk && \ rm -rf .git \ && : # last line -# Clone WiSeConnect SDK v3.3.0 (e97a0ed) -RUN git clone --depth=1 --single-branch --branch=v3.3.0 https://github.com/SiliconLabs/wiseconnect.git /tmp/wifi_sdk && \ +# Clone WiSeConnect SDK v3.3.1 (841ea3f) +RUN git clone --depth=1 --single-branch --branch=v3.3.1 https://github.com/SiliconLabs/wiseconnect.git /tmp/wifi_sdk && \ cd /tmp/wifi_sdk && \ rm -rf .git \ && : # last line diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index 93ab5ccd0a1012..a0482b41db65b8 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -852,6 +852,31 @@ JNI_METHOD(void, establishPaseConnectionByAddress) } } +JNI_METHOD(void, establishPaseConnectionByCode) +(JNIEnv * env, jobject self, jlong handle, jlong deviceId, jstring setUpCode, jboolean useOnlyOnNetworkDiscovery) +{ + chip::DeviceLayer::StackLock lock; + CHIP_ERROR err = CHIP_NO_ERROR; + AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle); + + auto discoveryType = DiscoveryType::kAll; + if (useOnlyOnNetworkDiscovery) + { + discoveryType = DiscoveryType::kDiscoveryNetworkOnly; + } + + JniUtfString setUpCodeJniString(env, setUpCode); + + err = wrapper->Controller()->EstablishPASEConnection(static_cast(deviceId), setUpCodeJniString.c_str(), + discoveryType); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "Failed to establish PASE connection."); + JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err); + } +} + JNI_METHOD(void, continueCommissioning) (JNIEnv * env, jobject self, jlong handle, jlong devicePtr, jboolean ignoreAttestationFailure) { diff --git a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java index 37e9e7093a1afc..4a59b178f85ef6 100644 --- a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java +++ b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java @@ -470,6 +470,21 @@ public void establishPaseConnection(long deviceId, String address, int port, lon establishPaseConnectionByAddress(deviceControllerPtr, deviceId, address, port, setupPincode); } + /** + * Establish a secure PASE connection using the scanned QR code or manual entry code. + * + * @param deviceId the ID of the node to connect to + * @param setupCode the scanned QR code or manual entry code + * @param useOnlyOnNetworkDiscovery the flag to indicate the commissionable device is available on + * the network + */ + public void establishPaseConnection( + long deviceId, String setupCode, boolean useOnlyOnNetworkDiscovery) { + Log.d(TAG, "Establishing PASE connection using Code: " + setupCode); + establishPaseConnectionByCode( + deviceControllerPtr, deviceId, setupCode, useOnlyOnNetworkDiscovery); + } + /** * Initiates the automatic commissioning flow using the specified network credentials. It is * expected that a secure session has already been established via {@link @@ -1624,6 +1639,9 @@ private native void establishPaseConnection( private native void establishPaseConnectionByAddress( long deviceControllerPtr, long deviceId, String address, int port, long setupPincode); + private native void establishPaseConnectionByCode( + long deviceControllerPtr, long deviceId, String setupCode, boolean useOnlyOnNetworkDiscovery); + private native void commissionDevice( long deviceControllerPtr, long deviceId, diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.h b/src/darwin/Framework/CHIP/MTRDeviceController.h index eaae1fcf7d4c6a..9e2c833f6ef93b 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.h +++ b/src/darwin/Framework/CHIP/MTRDeviceController.h @@ -57,8 +57,8 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) * Once this returns non-nil, it's the caller's responsibility to call shutdown * on the controller to avoid leaking it. */ -- (nullable instancetype)initWithParameters:(MTRDeviceControllerAbstractParameters *)parameters - error:(NSError * __autoreleasing *)error MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6)); +- (nullable MTRDeviceController *)initWithParameters:(MTRDeviceControllerAbstractParameters *)parameters + error:(NSError * __autoreleasing *)error MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6)); /** * If true, the controller has not been shut down yet. diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm index 25a0e7d4dcd4c1..ee8cc2b7549190 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm @@ -108,10 +108,6 @@ using namespace chip::Tracing::DarwinFramework; @implementation MTRDeviceController { - // Atomic because they can be touched from multiple threads. - std::atomic _storedFabricIndex; - std::atomic> _storedCompressedFabricID; - // queue used to serialize all work performed by the MTRDeviceController dispatch_queue_t _chipWorkQueue; @@ -120,8 +116,6 @@ @implementation MTRDeviceController { chip::Credentials::DefaultDACVerifier * _defaultDACVerifier; MTRDeviceControllerDelegateBridge * _deviceControllerDelegateBridge; MTROperationalCredentialsDelegate * _operationalCredentialsDelegate; - MTRP256KeypairBridge _signingKeypairBridge; - MTRP256KeypairBridge _operationalKeypairBridge; MTRDeviceAttestationDelegateBridge * _deviceAttestationDelegateBridge; MTRDeviceControllerFactory * _factory; NSMapTable * _nodeIDToDeviceMap; @@ -133,9 +127,22 @@ @implementation MTRDeviceController { NSMutableArray * _serverEndpoints; MTRDeviceStorageBehaviorConfiguration * _storageBehaviorConfiguration; + std::atomic _storedFabricIndex; + std::atomic> _storedCompressedFabricID; + MTRP256KeypairBridge _signingKeypairBridge; + MTRP256KeypairBridge _operationalKeypairBridge; +} + +- (instancetype)initForSubclasses +{ + if (self = [super init]) { + // nothing, as superclass of MTRDeviceController is NSObject + } + + return self; } -- (nullable instancetype)initWithParameters:(MTRDeviceControllerAbstractParameters *)parameters error:(NSError * __autoreleasing *)error +- (nullable MTRDeviceController *)initWithParameters:(MTRDeviceControllerAbstractParameters *)parameters error:(NSError * __autoreleasing *)error { if (![parameters isKindOfClass:MTRDeviceControllerParameters.class]) { MTR_LOG_ERROR("Unsupported type of MTRDeviceControllerAbstractParameters: %@", parameters); @@ -1575,15 +1582,6 @@ + (void)forceLocalhostAdvertisingOnly @end -/** - * Shim to allow us to treat an MTRDevicePairingDelegate as an - * MTRDeviceControllerDelegate. - */ -@interface MTRDevicePairingDelegateShim : NSObject -@property (nonatomic, readonly) id delegate; -- (instancetype)initWithDelegate:(id)delegate; -@end - @implementation MTRDevicePairingDelegateShim - (instancetype)initWithDelegate:(id)delegate { diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h index 0f9de90363f821..5d1fc4c1809874 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h @@ -23,6 +23,7 @@ #import #import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -31,7 +32,6 @@ NS_ASSUME_NONNULL_BEGIN @protocol MTROTAProviderDelegate; @protocol MTRKeypair; -@class MTRDeviceController; @class MTRDeviceControllerStartupParams; @class MTRFabricInfo; diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm index 18128249376e21..5b089b392074e6 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm @@ -1133,9 +1133,9 @@ - (void)operationalInstanceAdded:(chip::PeerId &)operationalID } } -- (MTRDeviceController * _Nullable)initializeController:(MTRDeviceController *)controller - withParameters:(MTRDeviceControllerParameters *)parameters - error:(NSError * __autoreleasing *)error +- (nullable MTRDeviceController *)initializeController:(MTRDeviceController *)controller + withParameters:(MTRDeviceControllerParameters *)parameters + error:(NSError * __autoreleasing *)error { [self _assertCurrentQueueIsNotMatterQueue]; diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.h b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.h index eaae1fcf7d4c6a..c9587e910d3b1a 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.h +++ b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.h @@ -19,6 +19,7 @@ #import #import +#import #import @class MTRBaseDevice; @@ -37,15 +38,7 @@ typedef void (^MTRDeviceConnectionCallback)(MTRBaseDevice * _Nullable device, NS @protocol MTRDevicePairingDelegate; @protocol MTRDeviceControllerDelegate; -MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) -@interface MTRDeviceController : NSObject - -/** - * Controllers are created via the MTRDeviceControllerFactory object or - * initialized via initWithParameters:error:. - */ -- (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; +@interface MTRDeviceController_Concrete : MTRDeviceController /** * Initialize a device controller with the provided parameters. This will: @@ -57,8 +50,8 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) * Once this returns non-nil, it's the caller's responsibility to call shutdown * on the controller to avoid leaking it. */ -- (nullable instancetype)initWithParameters:(MTRDeviceControllerAbstractParameters *)parameters - error:(NSError * __autoreleasing *)error MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6)); +- (nullable MTRDeviceController *)initWithParameters:(MTRDeviceControllerAbstractParameters *)parameters + error:(NSError * __autoreleasing *)error MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6)); /** * If true, the controller has not been shut down yet. @@ -262,7 +255,7 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) @end -@interface MTRDeviceController (Deprecated) +@interface MTRDeviceController_Concrete (Deprecated) @property (readonly, nonatomic, nullable) NSNumber * controllerNodeId MTR_DEPRECATED( "Please use controllerNodeID", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4)); diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm index 6c312d510a93a7..c7ccab25e1cdc4 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm @@ -26,11 +26,13 @@ #import "MTRCommissionableBrowserResult_Internal.h" #import "MTRCommissioningParameters.h" #import "MTRConversion.h" +#import "MTRDeviceController.h" #import "MTRDeviceControllerDelegateBridge.h" #import "MTRDeviceControllerFactory_Internal.h" #import "MTRDeviceControllerLocalTestStorage.h" #import "MTRDeviceControllerStartupParams.h" #import "MTRDeviceControllerStartupParams_Internal.h" +#import "MTRDeviceController_Concrete.h" #import "MTRDevice_Concrete.h" #import "MTRDevice_Internal.h" #import "MTRError_Internal.h" @@ -79,61 +81,81 @@ #import -static NSString * const kErrorCommissionerInit = @"Init failure while initializing a commissioner"; -static NSString * const kErrorIPKInit = @"Init failure while initializing IPK"; -static NSString * const kErrorSigningKeypairInit = @"Init failure while creating signing keypair bridge"; -static NSString * const kErrorOperationalCredentialsInit = @"Init failure while creating operational credentials delegate"; -static NSString * const kErrorOperationalKeypairInit = @"Init failure while creating operational keypair bridge"; -static NSString * const kErrorPairingInit = @"Init failure while creating a pairing delegate"; -static NSString * const kErrorPartialDacVerifierInit = @"Init failure while creating a partial DAC verifier"; -static NSString * const kErrorPairDevice = @"Failure while pairing the device"; -static NSString * const kErrorStopPairing = @"Failure while trying to stop the pairing process"; -static NSString * const kErrorOpenPairingWindow = @"Open Pairing Window failed"; -static NSString * const kErrorNotRunning = @"Controller is not running. Call startup first."; -static NSString * const kErrorSetupCodeGen = @"Generating Manual Pairing Code failed"; -static NSString * const kErrorGenerateNOC = @"Generating operational certificate failed"; -static NSString * const kErrorKeyAllocation = @"Generating new operational key failed"; -static NSString * const kErrorCSRValidation = @"Extracting public key from CSR failed"; -static NSString * const kErrorGetCommissionee = @"Failure obtaining device being commissioned"; -static NSString * const kErrorGetAttestationChallenge = @"Failure getting attestation challenge"; -static NSString * const kErrorSpake2pVerifierGenerationFailed = @"PASE verifier generation failed"; -static NSString * const kErrorSpake2pVerifierSerializationFailed = @"PASE verifier serialization failed"; -static NSString * const kErrorCDCertStoreInit = @"Init failure while initializing Certificate Declaration Signing Keys store"; - typedef void (^SyncWorkQueueBlock)(void); typedef id (^SyncWorkQueueBlockWithReturnValue)(void); typedef BOOL (^SyncWorkQueueBlockWithBoolReturnValue)(void); using namespace chip::Tracing::DarwinFramework; -@implementation MTRDeviceController { - // Atomic because it can be touched from multiple threads. - std::atomic _storedFabricIndex; +@interface MTRDeviceController_Concrete () - // queue used to serialize all work performed by the MTRDeviceController - dispatch_queue_t _chipWorkQueue; +// MTRDeviceController ivar internal access + +@property (nonatomic, readonly) chip::Controller::DeviceCommissioner * cppCommissioner; +@property (nonatomic, readonly) chip::Credentials::PartialDACVerifier * partialDACVerifier; +@property (nonatomic, readonly) chip::Credentials::DefaultDACVerifier * defaultDACVerifier; +@property (nonatomic, readonly) MTRDeviceControllerDelegateBridge * deviceControllerDelegateBridge; +@property (nonatomic, readonly) MTROperationalCredentialsDelegate * operationalCredentialsDelegate; +@property (nonatomic, readonly) MTRDeviceAttestationDelegateBridge * deviceAttestationDelegateBridge; +@property (nonatomic, readwrite) NSUUID * uniqueIdentifier; +@property (nonatomic, readonly) dispatch_queue_t chipWorkQueue; +@property (nonatomic, readonly, nullable) MTRDeviceControllerFactory * factory; +@property (nonatomic, readonly, nullable) NSMapTable * nodeIDToDeviceMap; +@property (nonatomic, readonly) os_unfair_lock deviceMapLock; +@property (nonatomic, readonly, nullable) id otaProviderDelegate; +@property (nonatomic, readonly, nullable) dispatch_queue_t otaProviderDelegateQueue; +@property (nonatomic, readonly, nullable) MTRCommissionableBrowser * commissionableBrowser; +@property (nonatomic, readonly, nullable) MTRAttestationTrustStoreBridge * attestationTrustStoreBridge; +@property (nonatomic, readonly, nullable) NSMutableArray * serverEndpoints; + +@property (nonatomic, readonly) MTRAsyncWorkQueue * concurrentSubscriptionPool; - chip::Controller::DeviceCommissioner * _cppCommissioner; - chip::Credentials::PartialDACVerifier * _partialDACVerifier; - chip::Credentials::DefaultDACVerifier * _defaultDACVerifier; - MTRDeviceControllerDelegateBridge * _deviceControllerDelegateBridge; - MTROperationalCredentialsDelegate * _operationalCredentialsDelegate; +@property (nonatomic, readonly) MTRDeviceStorageBehaviorConfiguration * storageBehaviorConfiguration; + +@end + +@implementation MTRDeviceController_Concrete { + // queue used to serialize all work performed by the MTRDeviceController + std::atomic _storedFabricIndex; + std::atomic> _storedCompressedFabricID; MTRP256KeypairBridge _signingKeypairBridge; MTRP256KeypairBridge _operationalKeypairBridge; - MTRDeviceAttestationDelegateBridge * _deviceAttestationDelegateBridge; - MTRDeviceControllerFactory * _factory; - NSMapTable * _nodeIDToDeviceMap; - os_unfair_lock _deviceMapLock; // protects nodeIDToDeviceMap - MTRCommissionableBrowser * _commissionableBrowser; - MTRAttestationTrustStoreBridge * _attestationTrustStoreBridge; +} - // _serverEndpoints is only touched on the Matter queue. - NSMutableArray * _serverEndpoints; +// MTRDeviceController ivar internal access +@synthesize uniqueIdentifier = _uniqueIdentifier; +@synthesize chipWorkQueue = _chipWorkQueue; +@synthesize controllerDataStore = _controllerDataStore; +@synthesize factory = _factory; +@synthesize deviceMapLock = _deviceMapLock; +@synthesize otaProviderDelegate = _otaProviderDelegate; +@synthesize otaProviderDelegateQueue = _otaProviderDelegateQueue; +@synthesize commissionableBrowser = _commissionableBrowser; +@synthesize concurrentSubscriptionPool = _concurrentSubscriptionPool; +@synthesize storageBehaviorConfiguration = _storageBehaviorConfiguration; + +- (nullable MTRDeviceController_Concrete *)initWithParameters:(MTRDeviceControllerAbstractParameters *)parameters + error:(NSError * __autoreleasing *)error +{ + if (![parameters isKindOfClass:MTRDeviceControllerParameters.class]) { + MTR_LOG_ERROR("Unsupported type of MTRDeviceControllerAbstractParameters: %@", parameters); + if (error) { + *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_ARGUMENT]; + } + return nil; + } + auto * controllerParameters = static_cast(parameters); - MTRDeviceStorageBehaviorConfiguration * _storageBehaviorConfiguration; + // or, if necessary, MTRDeviceControllerFactory will auto-start in per-controller-storage mode if necessary + MTRDeviceControllerFactory * factory = MTRDeviceControllerFactory.sharedInstance; + id controller = [factory initializeController:self + withParameters:controllerParameters + error:error]; + return controller; } -- (nullable instancetype)initWithParameters:(MTRDeviceControllerAbstractParameters *)parameters error:(NSError * __autoreleasing *)error +- (nullable MTRDeviceController *)bogusWithParameters:(MTRDeviceControllerAbstractParameters *)parameters + error:(NSError * __autoreleasing *)error { if (![parameters isKindOfClass:MTRDeviceControllerParameters.class]) { MTR_LOG_ERROR("Unsupported type of MTRDeviceControllerAbstractParameters: %@", parameters); @@ -145,7 +167,11 @@ - (nullable instancetype)initWithParameters:(MTRDeviceControllerAbstractParamete auto * controllerParameters = static_cast(parameters); // MTRDeviceControllerFactory will auto-start in per-controller-storage mode if necessary - return [MTRDeviceControllerFactory.sharedInstance initializeController:self withParameters:controllerParameters error:error]; + MTRDeviceControllerFactory * factory = MTRDeviceControllerFactory.sharedInstance; + MTRDeviceController * controller = [factory initializeController:self + withParameters:controllerParameters + error:error]; + return controller; } - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory @@ -158,7 +184,7 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory concurrentSubscriptionPoolSize:(NSUInteger)concurrentSubscriptionPoolSize storageBehaviorConfiguration:(MTRDeviceStorageBehaviorConfiguration *)storageBehaviorConfiguration { - if (self = [super init]) { + if (self = [super initForSubclasses]) { // Make sure our storage is all set up to work as early as possible, // before we start doing anything else with the controller. _uniqueIdentifier = uniqueIdentifier; @@ -242,17 +268,17 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory _commissionableBrowser = nil; _deviceControllerDelegateBridge = new MTRDeviceControllerDelegateBridge(); - if ([self checkForInitError:(_deviceControllerDelegateBridge != nullptr) logMsg:kErrorPairingInit]) { + if ([self checkForInitError:(_deviceControllerDelegateBridge != nullptr) logMsg:kDeviceControllerErrorPairingInit]) { return nil; } _partialDACVerifier = new chip::Credentials::PartialDACVerifier(); - if ([self checkForInitError:(_partialDACVerifier != nullptr) logMsg:kErrorPartialDacVerifierInit]) { + if ([self checkForInitError:(_partialDACVerifier != nullptr) logMsg:kDeviceControllerErrorPartialDacVerifierInit]) { return nil; } _operationalCredentialsDelegate = new MTROperationalCredentialsDelegate(self); - if ([self checkForInitError:(_operationalCredentialsDelegate != nullptr) logMsg:kErrorOperationalCredentialsInit]) { + if ([self checkForInitError:(_operationalCredentialsDelegate != nullptr) logMsg:kDeviceControllerErrorOperationalCredentialsInit]) { return nil; } @@ -438,14 +464,14 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams chip::Crypto::P256Keypair * signingKeypair = nullptr; if (startupParams.nocSigner) { errorCode = _signingKeypairBridge.Init(startupParams.nocSigner); - if ([self checkForStartError:errorCode logMsg:kErrorSigningKeypairInit]) { + if ([self checkForStartError:errorCode logMsg:kDeviceControllerErrorSigningKeypairInit]) { return; } signingKeypair = &_signingKeypairBridge; } errorCode = _operationalCredentialsDelegate->Init( signingKeypair, startupParams.ipk, startupParams.rootCertificate, startupParams.intermediateCertificate); - if ([self checkForStartError:errorCode logMsg:kErrorOperationalCredentialsInit]) { + if ([self checkForStartError:errorCode logMsg:kDeviceControllerErrorOperationalCredentialsInit]) { return; } @@ -469,7 +495,7 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams if (startupParams.operationalKeypair != nil) { errorCode = _operationalKeypairBridge.Init(startupParams.operationalKeypair); - if ([self checkForStartError:errorCode logMsg:kErrorOperationalKeypairInit]) { + if ([self checkForStartError:errorCode logMsg:kDeviceControllerErrorOperationalKeypairInit]) { return; } commissionerParams.operationalKeypair = &_operationalKeypairBridge; @@ -494,7 +520,7 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams errorCode = _operationalCredentialsDelegate->GenerateNOC(startupParams.nodeID.unsignedLongLongValue, startupParams.fabricID.unsignedLongLongValue, cats, commissionerParams.operationalKeypair->Pubkey(), noc); - if ([self checkForStartError:errorCode logMsg:kErrorGenerateNOC]) { + if ([self checkForStartError:errorCode logMsg:kDeviceControllerErrorGenerateNOC]) { return; } } else { @@ -502,20 +528,20 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams uint8_t csrBuffer[chip::Crypto::kMIN_CSR_Buffer_Size]; chip::MutableByteSpan csr(csrBuffer); errorCode = startupParams.fabricTable->AllocatePendingOperationalKey(startupParams.fabricIndex, csr); - if ([self checkForStartError:errorCode logMsg:kErrorKeyAllocation]) { + if ([self checkForStartError:errorCode logMsg:kDeviceControllerErrorKeyAllocation]) { return; } chip::Crypto::P256PublicKey pubKey; errorCode = VerifyCertificateSigningRequest(csr.data(), csr.size(), pubKey); - if ([self checkForStartError:errorCode logMsg:kErrorCSRValidation]) { + if ([self checkForStartError:errorCode logMsg:kDeviceControllerErrorCSRValidation]) { return; } errorCode = _operationalCredentialsDelegate->GenerateNOC( startupParams.nodeID.unsignedLongLongValue, startupParams.fabricID.unsignedLongLongValue, cats, pubKey, noc); - if ([self checkForStartError:errorCode logMsg:kErrorGenerateNOC]) { + if ([self checkForStartError:errorCode logMsg:kDeviceControllerErrorGenerateNOC]) { return; } } @@ -553,13 +579,13 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams if (cdTrustStore == nullptr) { errorCode = CHIP_ERROR_INCORRECT_STATE; } - if ([self checkForStartError:errorCode logMsg:kErrorCDCertStoreInit]) { + if ([self checkForStartError:errorCode logMsg:kDeviceControllerErrorCDCertStoreInit]) { return; } for (NSData * cdSigningCert in startupParams.certificationDeclarationCertificates) { errorCode = cdTrustStore->AddTrustedKey(AsByteSpan(cdSigningCert)); - if ([self checkForStartError:errorCode logMsg:kErrorCDCertStoreInit]) { + if ([self checkForStartError:errorCode logMsg:kDeviceControllerErrorCDCertStoreInit]) { return; } } @@ -570,7 +596,7 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams auto & factory = chip::Controller::DeviceControllerFactory::GetInstance(); errorCode = factory.SetupCommissioner(commissionerParams, *_cppCommissioner); - if ([self checkForStartError:errorCode logMsg:kErrorCommissionerInit]) { + if ([self checkForStartError:errorCode logMsg:kDeviceControllerErrorCommissionerInit]) { return; } @@ -579,13 +605,13 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams uint8_t compressedIdBuffer[sizeof(uint64_t)]; chip::MutableByteSpan compressedId(compressedIdBuffer); errorCode = _cppCommissioner->GetCompressedFabricIdBytes(compressedId); - if ([self checkForStartError:errorCode logMsg:kErrorIPKInit]) { + if ([self checkForStartError:errorCode logMsg:kDeviceControllerErrorIPKInit]) { return; } errorCode = chip::Credentials::SetSingleIpkEpochKey( _factory.groupDataProvider, fabricIdx, _operationalCredentialsDelegate->GetIPK(), compressedId); - if ([self checkForStartError:errorCode logMsg:kErrorIPKInit]) { + if ([self checkForStartError:errorCode logMsg:kDeviceControllerErrorIPKInit]) { return; } @@ -688,7 +714,7 @@ - (BOOL)setupCommissioningSessionWithPayload:(MTRSetupPayload *)payload } if (pairingCode == nil) { errorCode = CHIP_ERROR_INVALID_ARGUMENT; - return ![MTRDeviceController checkForError:errorCode logMsg:kErrorSetupCodeGen error:error]; + return ![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorSetupCodeGen error:error]; } chip::NodeId nodeId = [newNodeID unsignedLongLongValue]; @@ -702,7 +728,7 @@ - (BOOL)setupCommissioningSessionWithPayload:(MTRSetupPayload *)payload MATTER_LOG_METRIC_END(kMetricSetupPASESession, errorCode); } - return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error]; + return ![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorPairDevice error:error]; }; auto success = [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; @@ -758,7 +784,7 @@ - (BOOL)setupCommissioningSessionWithDiscoveredDevice:(MTRCommissionableBrowserR } if (pairingCode == nil) { errorCode = CHIP_ERROR_INVALID_ARGUMENT; - return ![MTRDeviceController checkForError:errorCode logMsg:kErrorSetupCodeGen error:error]; + return ![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorSetupCodeGen error:error]; } for (id key in discoveredDevice.interfaces) { @@ -779,7 +805,7 @@ - (BOOL)setupCommissioningSessionWithDiscoveredDevice:(MTRCommissionableBrowserR } } - return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error]; + return ![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorPairDevice error:error]; }; auto success = [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; @@ -886,7 +912,7 @@ - (BOOL)commissionNodeWithID:(NSNumber *)nodeID self->_operationalCredentialsDelegate->SetDeviceID(deviceId); auto errorCode = self->_cppCommissioner->Commission(deviceId, params); MATTER_LOG_METRIC(kMetricCommissionNode, errorCode); - return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error]; + return ![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorPairDevice error:error]; }; return [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; @@ -906,7 +932,7 @@ - (BOOL)continueCommissioningDevice:(void *)device ignoreAttestationFailure ? chip::Credentials::AttestationVerificationResult::kSuccess : lastAttestationResult); // Emit metric on stage after continuing post attestation MATTER_LOG_METRIC(kMetricContinueCommissioningAfterAttestation, errorCode); - return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error]; + return ![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorPairDevice error:error]; }; return [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; @@ -919,7 +945,7 @@ - (BOOL)cancelCommissioningForNodeID:(NSNumber *)nodeID error:(NSError * __autor auto errorCode = self->_cppCommissioner->StopPairing([nodeID unsignedLongLongValue]); // Emit metric on status of cancel MATTER_LOG_METRIC(kMetricCancelCommissioning, errorCode); - return ![MTRDeviceController checkForError:errorCode logMsg:kErrorStopPairing error:error]; + return ![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorStopPairing error:error]; }; return [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; @@ -969,7 +995,7 @@ - (MTRBaseDevice *)deviceBeingCommissionedWithNodeID:(NSNumber *)nodeID error:(N auto errorCode = self->_cppCommissioner->GetDeviceBeingCommissioned(nodeID.unsignedLongLongValue, &deviceProxy); MATTER_LOG_METRIC(kMetricDeviceBeingCommissioned, errorCode); - VerifyOrReturnValue(![MTRDeviceController checkForError:errorCode logMsg:kErrorGetCommissionee error:error], nil); + VerifyOrReturnValue(![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorGetCommissionee error:error], nil); return [[MTRBaseDevice alloc] initWithPASEDevice:deviceProxy controller:self]; }; @@ -989,7 +1015,7 @@ - (MTRDevice *)_setupDeviceForNodeID:(NSNumber *)nodeID prefetchedClusterData:(N { os_unfair_lock_assert_owner(&_deviceMapLock); - MTRDevice * deviceToReturn = [[MTRDevice_Concrete alloc] initWithNodeID:nodeID controller:self]; + MTRDevice * deviceToReturn = [[MTRDevice alloc] initWithNodeID:nodeID controller:self]; // If we're not running, don't add the device to our map. That would // create a cycle that nothing would break. Just return the device, // which will be in exactly the state it would be in if it were created @@ -1105,14 +1131,14 @@ + (nullable NSData *)computePASEVerifierForSetupPasscode:(NSNumber *)setupPassco MATTER_LOG_METRIC_SCOPE(kMetricPASEVerifierForSetupCode, err); - if ([MTRDeviceController checkForError:err logMsg:kErrorSpake2pVerifierGenerationFailed error:error]) { + if ([MTRDeviceController_Concrete checkForError:err logMsg:kDeviceControllerErrorSpake2pVerifierGenerationFailed error:error]) { return nil; } uint8_t serializedBuffer[chip::Crypto::kSpake2p_VerifierSerialized_Length]; chip::MutableByteSpan serializedBytes(serializedBuffer); err = verifier.Serialize(serializedBytes); - if ([MTRDeviceController checkForError:err logMsg:kErrorSpake2pVerifierSerializationFailed error:error]) { + if ([MTRDeviceController_Concrete checkForError:err logMsg:kDeviceControllerErrorSpake2pVerifierSerializationFailed error:error]) { return nil; } @@ -1129,13 +1155,13 @@ - (NSData * _Nullable)attestationChallengeForDeviceID:(NSNumber *)deviceID MATTER_LOG_METRIC_SCOPE(kMetricAttestationChallengeForDevice, errorCode); errorCode = self->_cppCommissioner->GetDeviceBeingCommissioned([deviceID unsignedLongLongValue], &deviceProxy); - VerifyOrReturnValue(![MTRDeviceController checkForError:errorCode logMsg:kErrorGetCommissionee error:nil], nil); + VerifyOrReturnValue(![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorGetCommissionee error:nil], nil); uint8_t challengeBuffer[chip::Crypto::kAES_CCM128_Key_Length]; chip::ByteSpan challenge(challengeBuffer); errorCode = deviceProxy->GetAttestationChallenge(challenge); - VerifyOrReturnValue(![MTRDeviceController checkForError:errorCode logMsg:kErrorGetAttestationChallenge error:nil], nil); + VerifyOrReturnValue(![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorGetAttestationChallenge error:nil], nil); return AsData(challenge); }; @@ -1272,7 +1298,7 @@ - (BOOL)checkIsRunning:(NSError * __autoreleasing *)error return YES; } - MTR_LOG_ERROR("MTRDeviceController: %@ Error: %s", self, [kErrorNotRunning UTF8String]); + MTR_LOG_ERROR("MTRDeviceController: %@ Error: %s", self, [kDeviceControllerErrorNotRunning UTF8String]); if (error) { *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]; } @@ -1582,63 +1608,6 @@ + (void)forceLocalhostAdvertisingOnly @end -/** - * Shim to allow us to treat an MTRDevicePairingDelegate as an - * MTRDeviceControllerDelegate. - */ -@interface MTRDevicePairingDelegateShim : NSObject -@property (nonatomic, readonly) id delegate; -- (instancetype)initWithDelegate:(id)delegate; -@end - -@implementation MTRDevicePairingDelegateShim -- (instancetype)initWithDelegate:(id)delegate -{ - if (self = [super init]) { - _delegate = delegate; - } - return self; -} - -- (BOOL)respondsToSelector:(SEL)selector -{ - if (selector == @selector(controller:statusUpdate:)) { - return [self.delegate respondsToSelector:@selector(onStatusUpdate:)]; - } - - if (selector == @selector(controller:commissioningSessionEstablishmentDone:)) { - return [self.delegate respondsToSelector:@selector(onPairingComplete:)]; - } - - if (selector == @selector(controller:commissioningComplete:)) { - return [self.delegate respondsToSelector:@selector(onCommissioningComplete:)]; - } - - return [super respondsToSelector:selector]; -} - -- (void)controller:(MTRDeviceController *)controller statusUpdate:(MTRCommissioningStatus)status -{ - [self.delegate onStatusUpdate:static_cast(status)]; -} - -- (void)controller:(MTRDeviceController *)controller commissioningSessionEstablishmentDone:(NSError * _Nullable)error -{ - [self.delegate onPairingComplete:error]; -} - -- (void)controller:(MTRDeviceController *)controller commissioningComplete:(NSError * _Nullable)error -{ - [self.delegate onCommissioningComplete:error]; -} - -- (void)onPairingDeleted:(NSError * _Nullable)error -{ - [self.delegate onPairingDeleted:error]; -} - -@end - /** * Shim to allow us to treat an MTRNOCChainIssuer as an * MTROperationalCertificateIssuer. @@ -1649,58 +1618,7 @@ @interface MTROperationalCertificateChainIssuerShim : NSObject )nocChainIssuer; @end -@implementation MTROperationalCertificateChainIssuerShim -- (instancetype)initWithIssuer:(id)nocChainIssuer -{ - if (self = [super init]) { - _nocChainIssuer = nocChainIssuer; - _shouldSkipAttestationCertificateValidation = YES; - } - return self; -} - -- (void)issueOperationalCertificateForRequest:(MTROperationalCSRInfo *)csrInfo - attestationInfo:(MTRDeviceAttestationInfo *)attestationInfo - controller:(MTRDeviceController *)controller - completion:(void (^)(MTROperationalCertificateChain * _Nullable info, - NSError * _Nullable error))completion -{ - CSRInfo * oldCSRInfo = [[CSRInfo alloc] initWithNonce:csrInfo.csrNonce - elements:csrInfo.csrElementsTLV - elementsSignature:csrInfo.attestationSignature - csr:csrInfo.csr]; - NSData * _Nullable firmwareInfo = attestationInfo.firmwareInfo; - if (firmwareInfo == nil) { - firmwareInfo = [NSData data]; - } - AttestationInfo * oldAttestationInfo = - [[AttestationInfo alloc] initWithChallenge:attestationInfo.challenge - nonce:attestationInfo.nonce - elements:attestationInfo.elementsTLV - elementsSignature:attestationInfo.elementsSignature - dac:attestationInfo.deviceAttestationCertificate - pai:attestationInfo.productAttestationIntermediateCertificate - certificationDeclaration:attestationInfo.certificationDeclaration - firmwareInfo:firmwareInfo]; - [self.nocChainIssuer - onNOCChainGenerationNeeded:oldCSRInfo - attestationInfo:oldAttestationInfo - onNOCChainGenerationComplete:^(NSData * operationalCertificate, NSData * intermediateCertificate, NSData * rootCertificate, - NSData * _Nullable ipk, NSNumber * _Nullable adminSubject, NSError * __autoreleasing * error) { - auto * chain = [[MTROperationalCertificateChain alloc] initWithOperationalCertificate:operationalCertificate - intermediateCertificate:intermediateCertificate - rootCertificate:rootCertificate - adminSubject:adminSubject]; - completion(chain, nil); - if (error != nil) { - *error = nil; - } - }]; -} - -@end - -@implementation MTRDeviceController (Deprecated) +@implementation MTRDeviceController_Concrete (Deprecated) - (NSNumber *)controllerNodeId { @@ -1768,7 +1686,7 @@ - (BOOL)pairDevice:(uint64_t)deviceID payload.setUpPINCode = setupPINCode; errorCode = chip::ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualPairingCode); - VerifyOrReturnValue(![MTRDeviceController checkForError:errorCode logMsg:kErrorSetupCodeGen error:error], NO); + VerifyOrReturnValue(![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorSetupCodeGen error:error], NO); self->_operationalCredentialsDelegate->SetDeviceID(deviceID); @@ -1780,7 +1698,7 @@ - (BOOL)pairDevice:(uint64_t)deviceID MATTER_LOG_METRIC_END(kMetricSetupPASESession, errorCode); } - return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error]; + return ![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorPairDevice error:error]; }; auto success = [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; @@ -1825,7 +1743,7 @@ - (BOOL)pairDevice:(uint64_t)deviceID MATTER_LOG_METRIC_END(kMetricSetupPASESession, errorCode); } - return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error]; + return ![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorPairDevice error:error]; }; auto success = [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; @@ -1861,7 +1779,7 @@ - (BOOL)pairDevice:(uint64_t)deviceID onboardingPayload:(NSString *)onboardingPa MATTER_LOG_METRIC_END(kMetricSetupPASESession, errorCode); } - return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error]; + return ![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorPairDevice error:error]; }; auto success = [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; @@ -1904,7 +1822,7 @@ - (BOOL)openPairingWindow:(uint64_t)deviceID duration:(NSUInteger)duration error errorCode = chip::Controller::AutoCommissioningWindowOpener::OpenBasicCommissioningWindow( self->_cppCommissioner, deviceID, chip::System::Clock::Seconds16(static_cast(duration))); - return ![MTRDeviceController checkForError:errorCode logMsg:kErrorOpenPairingWindow error:error]; + return ![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorOpenPairingWindow error:error]; }; return [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; @@ -1952,7 +1870,7 @@ - (NSString *)openPairingWindowWithPIN:(uint64_t)deviceID static_cast(discriminator), chip::MakeOptional(static_cast(setupPIN)), chip::NullOptional, setupPayload); - VerifyOrReturnValue(![MTRDeviceController checkForError:errorCode logMsg:kErrorOpenPairingWindow error:error], nil); + VerifyOrReturnValue(![MTRDeviceController_Concrete checkForError:errorCode logMsg:kDeviceControllerErrorOpenPairingWindow error:error], nil); chip::ManualSetupPayloadGenerator generator(setupPayload); std::string outCode; diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h b/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h index 479dd8518d069f..d943775d43475d 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h +++ b/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h @@ -32,8 +32,11 @@ #import "MTRBaseDevice.h" #import "MTRDeviceController.h" #import "MTRDeviceControllerDataStore.h" +#import "MTRDeviceControllerDelegate.h" #import "MTRDeviceStorageBehaviorConfiguration.h" +#import + #import #import #import @@ -44,6 +47,9 @@ @class MTRDeviceControllerFactory; @class MTRDevice; @class MTRAsyncWorkQueue; +@protocol MTRDevicePairingDelegate; +@protocol MTRDeviceControllerDelegate; +@class MTRDevice_Concrete; namespace chip { class FabricTable; @@ -57,6 +63,8 @@ NS_ASSUME_NONNULL_BEGIN @interface MTRDeviceController () +- (instancetype)initForSubclasses; + #pragma mark - MTRDeviceControllerFactory methods /** @@ -273,4 +281,34 @@ NS_ASSUME_NONNULL_BEGIN @end +/** + * Shim to allow us to treat an MTRDevicePairingDelegate as an + * MTRDeviceControllerDelegate. + */ +@interface MTRDevicePairingDelegateShim : NSObject +@property (nonatomic, readonly) id delegate; +- (instancetype)initWithDelegate:(id)delegate; +@end + +static NSString * const kDeviceControllerErrorCommissionerInit = @"Init failure while initializing a commissioner"; +static NSString * const kDeviceControllerErrorIPKInit = @"Init failure while initializing IPK"; +static NSString * const kDeviceControllerErrorSigningKeypairInit = @"Init failure while creating signing keypair bridge"; +static NSString * const kDeviceControllerErrorOperationalCredentialsInit = @"Init failure while creating operational credentials delegate"; +static NSString * const kDeviceControllerErrorOperationalKeypairInit = @"Init failure while creating operational keypair bridge"; +static NSString * const kDeviceControllerErrorPairingInit = @"Init failure while creating a pairing delegate"; +static NSString * const kDeviceControllerErrorPartialDacVerifierInit = @"Init failure while creating a partial DAC verifier"; +static NSString * const kDeviceControllerErrorPairDevice = @"Failure while pairing the device"; +static NSString * const kDeviceControllerErrorStopPairing = @"Failure while trying to stop the pairing process"; +static NSString * const kDeviceControllerErrorOpenPairingWindow = @"Open Pairing Window failed"; +static NSString * const kDeviceControllerErrorNotRunning = @"Controller is not running. Call startup first."; +static NSString * const kDeviceControllerErrorSetupCodeGen = @"Generating Manual Pairing Code failed"; +static NSString * const kDeviceControllerErrorGenerateNOC = @"Generating operational certificate failed"; +static NSString * const kDeviceControllerErrorKeyAllocation = @"Generating new operational key failed"; +static NSString * const kDeviceControllerErrorCSRValidation = @"Extracting public key from CSR failed"; +static NSString * const kDeviceControllerErrorGetCommissionee = @"Failure obtaining device being commissioned"; +static NSString * const kDeviceControllerErrorGetAttestationChallenge = @"Failure getting attestation challenge"; +static NSString * const kDeviceControllerErrorSpake2pVerifierGenerationFailed = @"PASE verifier generation failed"; +static NSString * const kDeviceControllerErrorSpake2pVerifierSerializationFailed = @"PASE verifier serialization failed"; +static NSString * const kDeviceControllerErrorCDCertStoreInit = @"Init failure while initializing Certificate Declaration Signing Keys store"; + NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/Matter.h b/src/darwin/Framework/CHIP/Matter.h index 3c0ec41443303c..109f4a20a9a5f1 100644 --- a/src/darwin/Framework/CHIP/Matter.h +++ b/src/darwin/Framework/CHIP/Matter.h @@ -69,4 +69,7 @@ #import #import +#import +#import + #undef MTR_INCLUDED_FROM_UMBRELLA_HEADER diff --git a/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCClientProtocol.h b/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCClientProtocol.h new file mode 100644 index 00000000000000..0d518f525f7118 --- /dev/null +++ b/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCClientProtocol.h @@ -0,0 +1,39 @@ +// +/** + * Copyright (c) 2023 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. + */ +NS_ASSUME_NONNULL_BEGIN + +@protocol MTRXPCClientProtocol_MTRDevice +- (oneway void)device:(NSNumber *)nodeID stateChanged:(MTRDeviceState)state; +- (oneway void)device:(NSNumber *)nodeID receivedAttributeReport:(NSArray *> *)attributeReport; +- (oneway void)device:(NSNumber *)nodeID receivedEventReport:(NSArray *> *)eventReport; +- (oneway void)deviceBecameActive:(NSNumber *)nodeID; +- (oneway void)deviceCachePrimed:(NSNumber *)nodeID; +- (oneway void)deviceConfigurationChanged:(NSNumber *)nodeID; +@end + +@protocol MTRXPCClientProtocol_MTRDeviceController +// Not Supported via XPC +//- (oneway void)controller:(NSUUID *)controller statusUpdate:(MTRCommissioningStatus)status; +//- (oneway void)controller:(NSUUID *)controller commissioningSessionEstablishmentDone:(NSError * _Nullable)error; +//- (oneway void)controller:(NSUUID *)controller commissioningComplete:(NSError * _Nullable)error nodeID:(NSNumber * _Nullable)nodeID metrics:(MTRMetrics * _Nullable)metrics; +//- (oneway void)controller:(NSUUID *)controller readCommissioningInfo:(MTRProductIdentity *)info; +@end + +@protocol MTRXPCClientProtocol +@end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCServerProtocol.h b/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCServerProtocol.h new file mode 100644 index 00000000000000..56077897a9e45a --- /dev/null +++ b/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCServerProtocol.h @@ -0,0 +1,76 @@ +// +/** + * Copyright (c) 2023 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. + */ + +NS_ASSUME_NONNULL_BEGIN + +@protocol MTRXPCServerProtocol_MTRDevice + +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID getStateWithReply:(void (^)(MTRDeviceState state))reply; +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID getDeviceCachePrimedWithReply:(void (^)(BOOL primed))reply; +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID getEstimatedStartTimeWithReply:(void (^)(NSDate * _Nullable estimatedStartTime))reply; +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID getEstimatedSubscriptionLatencyWithReply:(void (^)(NSNumber * _Nullable estimatedSubscriptionLatency))reply; + +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID readAttributeWithEndpointID:(NSNumber *)endpointID clusterID:(NSNumber *)clusterID attributeID:(NSNumber *)attributeID params:(MTRReadParams * _Nullable)params withReply:(void (^)(NSDictionary * _Nullable))reply; +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID writeAttributeWithEndpointID:(NSNumber *)endpointID clusterID:(NSNumber *)clusterID attributeID:(NSNumber *)attributeID value:(id _Nullable)value expectedValueInterval:(NSNumber * _Nullable)expectedValueInterval timedWriteTimeout:(NSNumber * _Nullable)timeout; + +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID invokeCommandWithEndpointID:(NSNumber *)endpointID clusterID:(NSNumber *)clusterID commandID:(NSNumber *)commandID commandFields:(id)commandFields expectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueInterval timedInvokeTimeout:(NSNumber * _Nullable)timeout completion:(MTRDeviceResponseHandler)completion; + +// Not Supported via XPC +//- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID openCommissioningWindowWithSetupPasscode:(NSNumber *)setupPasscode discriminator:(NSNumber *)discriminator duration:(NSNumber *)duration completion:(MTRDeviceOpenCommissioningWindowHandler)completion; + +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID getClientDataKeysWithReply:(void (^)(NSArray * _Nullable))reply; +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID clientDataForKey:(NSString *)key withReply:(void (^)(id _Nullable))reply; +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID setClientDataForKey:(NSString *)key value:(id)value; +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID removeClientDataForKey:(NSString *)key; +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID clientDataKeysForEndpointID:(NSNumber *)endpointID withReply:(void (^)(NSArray * _Nullable))reply; +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID clientDataForKey:(NSString *)key endpointID:(NSNumber *)endpointID withReply:(void (^)(id _Nullable))reply; +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID setClientDataForKey:(NSString *)key endpointID:(NSNumber *)endpointID value:(id _Nullable)value; +- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID removeClientDataForKey:(NSString *)key endpointID:(NSNumber *)endpointID; + +// Not Supported via XPC +// - (oneway void)downloadLogOfType:(MTRDiagnosticLogType)type nodeID:(NSNumber *)nodeID timeout:(NSTimeInterval)timeout completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion; +@end + +@protocol MTRXPCServerProtocol_MTRDeviceController + +- (oneway void)deviceController:(NSUUID *)controller getIsRunningWithReply:(void (^)(BOOL response))reply; +- (oneway void)deviceController:(NSUUID *)controller getUniqueIdentifierWithReply:(void (^)(NSUUID *))reply; +- (oneway void)deviceController:(NSUUID *)controller controllerNodeIDWithReply:(void (^)(NSNumber * nodeID))reply; + +// Not Supported via XPC +// - (oneway void)deviceController:(NSUUID *)controller setupCommissioningSessionWithPayload:(MTRSetupPayload *)payload newNodeID:(NSNumber *)newNodeID withReply:(void(^)(BOOL success, NSError * _Nullable error))reply; +// - (oneway void)deviceController:(NSUUID *)controller setupCommissioningSessionWithDiscoveredDevice:(MTRCommissionableBrowserResult *)discoveredDevice payload:(MTRSetupPayload *)payload newNodeID:(NSNumber *)newNodeID withReply:(void(^)(BOOL success, NSError * _Nullable error))reply; +// - (oneway void)deviceController:(NSUUID *)controller commissionNodeWithID:(NSNumber *)nodeID commissioningParams:(MTRCommissioningParameters *)commissioningParams withReply:(void(^)(BOOL success, NSError * _Nullable error))reply; +// - (oneway void)deviceController:(NSUUID *)controller continueCommissioningDevice:(void *)opaqueDeviceHandle ignoreAttestationFailure:(BOOL)ignoreAttestationFailure withReply:(void(^)(BOOL success, NSError * _Nullable error))reply; +// - (oneway void)deviceController:(NSUUID *)controller cancelCommissioningForNodeID:(NSNumber *)nodeID withReply:(void(^)(BOOL success, NSError * _Nullable error))reply; +// - (nullable MTRBaseDevice *)deviceController:(NSUUID *)controller deviceBeingCommissionedWithNodeID:(NSNumber *)nodeID error:(NSError * __autoreleasing *)error; +// - (oneway void)deviceController:(NSUUID *)controller startBrowseForCommissionables:(id)delegate withReply:(void(^)(BOOL success))reply; +// - (oneway void)deviceController:(NSUUID *)controller stopBrowseForCommissionablesWithReply:(void(^)(BOOL success))reply; +// - (oneway void)deviceController:(NSUUID *)controller attestationChallengeForDeviceID:(NSNumber *)deviceID withReply:(void(^)(NSData * _Nullable))reply; + +//- (oneway void)deviceController:(NSUUID *)controller addServerEndpoint:(MTRServerEndpoint *)endpoint withReply:(void(^)(BOOL success))reply; +//- (oneway void)deviceController:(NSUUID *)controller removeServerEndpoint:(MTRServerEndpoint *)endpoint; + +- (oneway void)shutdownDeviceController:(NSUUID *)controller; + +@end + +@protocol MTRXPCServerProtocol +- (oneway void)deviceController:(NSUUID *)controller checkInWithContext:(NSDictionary *)context; +@end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index bb5a8ce1801631..69ef3bdc71d81b 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -302,6 +302,8 @@ 99AECC802798A57F00B6355B /* MTRCommissioningParameters.mm in Sources */ = {isa = PBXBuildFile; fileRef = 99AECC7F2798A57E00B6355B /* MTRCommissioningParameters.mm */; }; 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, ); }; }; + 9B231B042C62EF650030EB37 /* MTRDeviceController_Concrete.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B231B022C62EF650030EB37 /* MTRDeviceController_Concrete.h */; }; + 9B231B052C62EF650030EB37 /* MTRDeviceController_Concrete.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B231B032C62EF650030EB37 /* MTRDeviceController_Concrete.mm */; }; 9BDA2A062C5D9AF800A32BDD /* MTRDevice_Concrete.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BDA2A052C5D9AF800A32BDD /* MTRDevice_Concrete.mm */; }; 9BDA2A082C5D9AFB00A32BDD /* MTRDevice_Concrete.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BDA2A072C5D9AFB00A32BDD /* MTRDevice_Concrete.h */; }; AF1CB86E2874B03B00865A96 /* MTROTAProviderDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = AF1CB86D2874B03B00865A96 /* MTROTAProviderDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -369,6 +371,8 @@ B4FCD5722B603A6300832859 /* DownloadLogCommand.mm in Sources */ = {isa = PBXBuildFile; fileRef = B4FCD56F2B603A6300832859 /* DownloadLogCommand.mm */; }; B4FCD5732B611EB300832859 /* MTRDiagnosticLogsDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = B4C8E6B32B3453AD00FCD54D /* MTRDiagnosticLogsDownloader.h */; }; BA09EB43247477BA00605257 /* libCHIP.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BA09EB3F2474762900605257 /* libCHIP.a */; }; + D444F9A72C6E8F9D007761E5 /* MTRXPCServerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D444F9A62C6E8F9D007761E5 /* MTRXPCServerProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D444F9AA2C6E9A08007761E5 /* MTRXPCClientProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D444F9A82C6E99CA007761E5 /* MTRXPCClientProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D4772A46285AE98400383630 /* MTRClusterConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = D4772A45285AE98300383630 /* MTRClusterConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; E04AC67D2BEEA17F00BA409B /* ember-io-storage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E04AC67B2BEEA17F00BA409B /* ember-io-storage.cpp */; }; E04AC67E2BEEA17F00BA409B /* ember-io-storage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E04AC67B2BEEA17F00BA409B /* ember-io-storage.cpp */; }; @@ -731,6 +735,8 @@ 99AECC7F2798A57E00B6355B /* MTRCommissioningParameters.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRCommissioningParameters.mm; sourceTree = ""; }; 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 = ""; }; + 9B231B022C62EF650030EB37 /* MTRDeviceController_Concrete.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDeviceController_Concrete.h; sourceTree = ""; }; + 9B231B032C62EF650030EB37 /* MTRDeviceController_Concrete.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRDeviceController_Concrete.mm; sourceTree = ""; }; 9BDA2A052C5D9AF800A32BDD /* MTRDevice_Concrete.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRDevice_Concrete.mm; sourceTree = ""; }; 9BDA2A072C5D9AFB00A32BDD /* MTRDevice_Concrete.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDevice_Concrete.h; sourceTree = ""; }; AF1CB86D2874B03B00865A96 /* MTROTAProviderDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTROTAProviderDelegate.h; sourceTree = ""; }; @@ -805,6 +811,8 @@ D437613E285BDC0D0051FEA2 /* MTRErrorTestUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRErrorTestUtils.h; sourceTree = ""; }; D437613F285BDC0D0051FEA2 /* MTRTestKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRTestKeys.h; sourceTree = ""; }; D4376140285BDC0D0051FEA2 /* MTRTestStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRTestStorage.h; sourceTree = ""; }; + D444F9A62C6E8F9D007761E5 /* MTRXPCServerProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRXPCServerProtocol.h; sourceTree = ""; }; + D444F9A82C6E99CA007761E5 /* MTRXPCClientProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRXPCClientProtocol.h; sourceTree = ""; }; D4772A45285AE98300383630 /* MTRClusterConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRClusterConstants.h; sourceTree = ""; }; E04AC67B2BEEA17F00BA409B /* ember-io-storage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "ember-io-storage.cpp"; path = "util/ember-io-storage.cpp"; sourceTree = ""; }; E04AC67C2BEEA17F00BA409B /* ember-global-attribute-access-interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "ember-global-attribute-access-interface.cpp"; path = "util/ember-global-attribute-access-interface.cpp"; sourceTree = ""; }; @@ -1242,6 +1250,9 @@ B202528F2459E34F00F97062 /* CHIP */ = { isa = PBXGroup; children = ( + D444F9A12C6E8058007761E5 /* XPC Protocol */, + 9B231B022C62EF650030EB37 /* MTRDeviceController_Concrete.h */, + 9B231B032C62EF650030EB37 /* MTRDeviceController_Concrete.mm */, 88E07D602B9A89A4005FD53E /* MTRMetricKeys.h */, 88FA798B2B7B257100CD4B6F /* MTRMetricsCollector.h */, 88FA798C2B7B257100CD4B6F /* MTRMetricsCollector.mm */, @@ -1533,6 +1544,15 @@ name = Frameworks; sourceTree = ""; }; + D444F9A12C6E8058007761E5 /* XPC Protocol */ = { + isa = PBXGroup; + children = ( + D444F9A82C6E99CA007761E5 /* MTRXPCClientProtocol.h */, + D444F9A62C6E8F9D007761E5 /* MTRXPCServerProtocol.h */, + ); + path = "XPC Protocol"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -1603,6 +1623,7 @@ 75B765C12A1D71BC0014719B /* MTRAttributeSpecifiedCheck.h in Headers */, 5ACDDD7A27CD129700EFD68A /* MTRClusterStateCacheContainer.h in Headers */, 5A6FEC9227B5669C00F25F42 /* MTRDeviceControllerOverXPC.h in Headers */, + D444F9AA2C6E9A08007761E5 /* MTRXPCClientProtocol.h in Headers */, 5117DD3929A931AE00FFA1AA /* MTROperationalBrowser.h in Headers */, 2C1B027B2641DB4E00780EF1 /* MTROperationalCredentialsDelegate.h in Headers */, 5173A47529C0E2ED00F67F48 /* MTRFabricInfo_Internal.h in Headers */, @@ -1676,6 +1697,7 @@ 51E51FC0282AD37A00FC978D /* MTRDeviceControllerStartupParams_Internal.h in Headers */, 3DECCB702934AECD00585AEC /* MTRLogging.h in Headers */, 1E4D654E29C208DD00BC3478 /* MTRCommissionableBrowserResult.h in Headers */, + 9B231B042C62EF650030EB37 /* MTRDeviceController_Concrete.h in Headers */, 515BE4ED2B72C0C5000BC1FD /* MTRUnfairLock.h in Headers */, 998F286F26D55EC5001846C6 /* MTRP256KeypairBridge.h in Headers */, 2C222ADF255C811800E446B9 /* MTRBaseDevice_Internal.h in Headers */, @@ -1691,6 +1713,7 @@ 5A7947E527C0129F00434CF2 /* MTRDeviceController+XPC.h in Headers */, 51E95DFB2A78443C00A434F0 /* MTRSessionResumptionStorageBridge.h in Headers */, B2E0D7B4245B0B5C003C5B48 /* MTRError_Internal.h in Headers */, + D444F9A72C6E8F9D007761E5 /* MTRXPCServerProtocol.h in Headers */, 51F5226A2AE70761000C4050 /* MTRDeviceTypeMetadata.h in Headers */, 5146544B2A72F9F500904E61 /* MTRDemuxingStorage.h in Headers */, 1EDCE545289049A100E41EC9 /* MTROTAHeader.h in Headers */, @@ -1986,6 +2009,7 @@ 511913FB28C100EF009235E9 /* MTRBaseSubscriptionCallback.mm in Sources */, 510470FB2A2F7DF60053EA7E /* MTRBackwardsCompatShims.mm in Sources */, 5173A47629C0E2ED00F67F48 /* MTRFabricInfo.mm in Sources */, + 9B231B052C62EF650030EB37 /* MTRDeviceController_Concrete.mm in Sources */, 5ACDDD7D27CD16D200EFD68A /* MTRClusterStateCacheContainer.mm in Sources */, 75B3269E2BCDB9EA00E17C4E /* MTRDeviceConnectivityMonitor.mm in Sources */, 513DDB8A2761F6F900DAA01A /* MTRAttributeTLVValueDecoder.mm in Sources */, diff --git a/src/platform/android/java/chip/platform/NsdManagerServiceBrowser.java b/src/platform/android/java/chip/platform/NsdManagerServiceBrowser.java index e4ac8a673b5db2..1df91c6830e171 100644 --- a/src/platform/android/java/chip/platform/NsdManagerServiceBrowser.java +++ b/src/platform/android/java/chip/platform/NsdManagerServiceBrowser.java @@ -161,7 +161,11 @@ public void onServiceFound(NsdServiceInfo serviceInfo) { @Override public void onServiceLost(NsdServiceInfo serviceInfo) { - Log.i(TAG, "Lost service '" + serviceType + "'"); + Log.i( + TAG, + "Lost service '" + (serviceInfo != null ? serviceInfo.getServiceName() : "null") + "'"); + boolean ret = serviceNameList.remove(serviceInfo.getServiceName()); + Log.i(TAG, "Remove List: " + ret); } @Override diff --git a/src/platform/android/java/chip/platform/NsdManagerServiceResolver.java b/src/platform/android/java/chip/platform/NsdManagerServiceResolver.java index 11b53537bf7d71..40595263cb8214 100644 --- a/src/platform/android/java/chip/platform/NsdManagerServiceResolver.java +++ b/src/platform/android/java/chip/platform/NsdManagerServiceResolver.java @@ -98,10 +98,6 @@ public void resolve( + serviceType + "'"); - if (nsdManagerResolverAvailState != null) { - nsdManagerResolverAvailState.acquireResolver(); - } - Runnable timeoutRunnable = new Runnable() { @Override @@ -120,21 +116,29 @@ public void run() { } }; - ScheduledFuture resolveTimeoutExecutor = - Executors.newSingleThreadScheduledExecutor() - .schedule(timeoutRunnable, timeout, TimeUnit.MILLISECONDS); + new Thread( + () -> { + if (nsdManagerResolverAvailState != null) { + nsdManagerResolverAvailState.acquireResolver(); + } + + ScheduledFuture resolveTimeoutExecutor = + Executors.newSingleThreadScheduledExecutor() + .schedule(timeoutRunnable, timeout, TimeUnit.MILLISECONDS); - NsdServiceFinderAndResolver serviceFinderResolver = - new NsdServiceFinderAndResolver( - this.nsdManager, - serviceInfo, - callbackHandle, - contextHandle, - chipMdnsCallback, - multicastLock, - resolveTimeoutExecutor, - nsdManagerResolverAvailState); - serviceFinderResolver.start(); + NsdServiceFinderAndResolver serviceFinderResolver = + new NsdServiceFinderAndResolver( + this.nsdManager, + serviceInfo, + callbackHandle, + contextHandle, + chipMdnsCallback, + multicastLock, + resolveTimeoutExecutor, + nsdManagerResolverAvailState); + serviceFinderResolver.start(); + }) + .start(); } @Override diff --git a/src/python_testing/TC_BRBINFO_4_1.py b/src/python_testing/TC_BRBINFO_4_1.py index 18e478c872fe2f..922a6cb555448c 100644 --- a/src/python_testing/TC_BRBINFO_4_1.py +++ b/src/python_testing/TC_BRBINFO_4_1.py @@ -57,7 +57,8 @@ def desc_TC_BRBINFO_4_1(self) -> str: def steps_TC_BRBINFO_4_1(self) -> list[TestStep]: steps = [ - TestStep("0", "Preconditions"), + TestStep("0", "DUT commissioned", is_commissioning=True), + TestStep("0a", "Preconditions"), TestStep("1a", "TH reads from the ICD the A_IDLE_MODE_DURATION, A_ACTIVE_MODE_DURATION, and ACTIVE_MODE_THRESHOLD attributes"), TestStep("1b", "Simple KeepActive command w/ subscription. ActiveChanged event received by TH contains PromisedActiveDuration"), TestStep("2", "Sends 3x KeepActive commands w/ subscription. ActiveChanged event received ONCE and contains PromisedActiveDuration"), @@ -73,7 +74,7 @@ def _ask_for_vendor_commissioniong_ux_operation(self, discriminator, setupPinCod f"- setupQRCode: {setupQRCode}\n" f"- setupManualcode: {setupManualCode}\n" f"If using FabricSync Admin test app, you may type:\n" - f">>> pairing onnetwork 111 {setupPinCode}") + f">>> pairing onnetwork 111 {setupPinCode} --icd-registration true") async def _send_keep_active_command(self, duration, endpoint_id) -> int: logging.info("Sending keep active command") @@ -164,9 +165,11 @@ async def test_TC_BRBINFO_4_1(self): dynamic_endpoint_id = await self._get_dynamic_endpoint() logging.info(f"Dynamic endpoint is {dynamic_endpoint_id}") - # Preconditions self.step("0") + # Preconditions + self.step("0a") + logging.info("Ensuring DUT is commissioned to TH") # Confirms commissioning of DUT on TH as it reads its fature map diff --git a/src/python_testing/TC_CCTRL_2_2.py b/src/python_testing/TC_CCTRL_2_2.py index 5204352b8b66a5..53c196113d36bc 100644 --- a/src/python_testing/TC_CCTRL_2_2.py +++ b/src/python_testing/TC_CCTRL_2_2.py @@ -123,7 +123,7 @@ async def test_TC_CCTRL_2_2(self): self.is_ci = self.check_pics('PICS_SDK_CI_ONLY') self.step(1) - th_server_fabrics = await self.read_single_attribute_check_success(cluster=Clusters.OperationalCredentials, attribute=Clusters.OperationalCredentials.Attributes.Fabrics, dev_ctrl=self.TH_server_controller, node_id=self.server_nodeid, endpoint=0) + th_server_fabrics = await self.read_single_attribute_check_success(cluster=Clusters.OperationalCredentials, attribute=Clusters.OperationalCredentials.Attributes.Fabrics, dev_ctrl=self.TH_server_controller, node_id=self.server_nodeid, endpoint=0, fabric_filtered=False) self.step(2) th_server_vid = await self.read_single_attribute_check_success(cluster=Clusters.BasicInformation, attribute=Clusters.BasicInformation.Attributes.VendorID, dev_ctrl=self.TH_server_controller, node_id=self.server_nodeid, endpoint=0) self.step(3) @@ -248,7 +248,7 @@ async def test_TC_CCTRL_2_2(self): self.step(20) print(f'server node id {self.server_nodeid}') - th_server_fabrics_new = await self.read_single_attribute_check_success(cluster=Clusters.OperationalCredentials, attribute=Clusters.OperationalCredentials.Attributes.Fabrics, dev_ctrl=self.TH_server_controller, node_id=self.server_nodeid, endpoint=0) + th_server_fabrics_new = await self.read_single_attribute_check_success(cluster=Clusters.OperationalCredentials, attribute=Clusters.OperationalCredentials.Attributes.Fabrics, dev_ctrl=self.TH_server_controller, node_id=self.server_nodeid, endpoint=0, fabric_filtered=False) asserts.assert_equal(len(th_server_fabrics), len(th_server_fabrics_new), "Unexpected number of fabrics on TH_SERVER") self.step(21) @@ -294,7 +294,7 @@ async def test_TC_CCTRL_2_2(self): time.sleep(30) self.step(28) - th_server_fabrics_new = await self.read_single_attribute_check_success(cluster=Clusters.OperationalCredentials, attribute=Clusters.OperationalCredentials.Attributes.Fabrics, dev_ctrl=self.TH_server_controller, node_id=self.server_nodeid, endpoint=0) + th_server_fabrics_new = await self.read_single_attribute_check_success(cluster=Clusters.OperationalCredentials, attribute=Clusters.OperationalCredentials.Attributes.Fabrics, dev_ctrl=self.TH_server_controller, node_id=self.server_nodeid, endpoint=0, fabric_filtered=False) # TODO: this should be mocked too. if not self.is_ci: asserts.assert_equal(len(th_server_fabrics) + 1, len(th_server_fabrics_new), diff --git a/src/python_testing/TC_MCORE_FS_1_1.py b/src/python_testing/TC_MCORE_FS_1_1.py index 0680210babd191..6753db81a3a4cf 100755 --- a/src/python_testing/TC_MCORE_FS_1_1.py +++ b/src/python_testing/TC_MCORE_FS_1_1.py @@ -93,7 +93,7 @@ async def test_TC_MCORE_FS_1_1(self): self.step(1) self.step(2) self.step(3) - th_fsa_server_fabrics = await self.read_single_attribute_check_success(cluster=Clusters.OperationalCredentials, attribute=Clusters.OperationalCredentials.Attributes.Fabrics, dev_ctrl=self.TH_server_controller, node_id=self.server_nodeid, endpoint=0) + th_fsa_server_fabrics = await self.read_single_attribute_check_success(cluster=Clusters.OperationalCredentials, attribute=Clusters.OperationalCredentials.Attributes.Fabrics, dev_ctrl=self.TH_server_controller, node_id=self.server_nodeid, endpoint=0, fabric_filtered=False) th_fsa_server_vid = await self.read_single_attribute_check_success(cluster=Clusters.BasicInformation, attribute=Clusters.BasicInformation.Attributes.VendorID, dev_ctrl=self.TH_server_controller, node_id=self.server_nodeid, endpoint=0) th_fsa_server_pid = await self.read_single_attribute_check_success(cluster=Clusters.BasicInformation, attribute=Clusters.BasicInformation.Attributes.ProductID, dev_ctrl=self.TH_server_controller, node_id=self.server_nodeid, endpoint=0) @@ -138,7 +138,7 @@ async def test_TC_MCORE_FS_1_1(self): if not self.is_ci: time.sleep(30) - th_fsa_server_fabrics_new = await self.read_single_attribute_check_success(cluster=Clusters.OperationalCredentials, attribute=Clusters.OperationalCredentials.Attributes.Fabrics, dev_ctrl=self.TH_server_controller, node_id=self.server_nodeid, endpoint=0) + th_fsa_server_fabrics_new = await self.read_single_attribute_check_success(cluster=Clusters.OperationalCredentials, attribute=Clusters.OperationalCredentials.Attributes.Fabrics, dev_ctrl=self.TH_server_controller, node_id=self.server_nodeid, endpoint=0, fabric_filtered=False) # TODO: this should be mocked too. if not self.is_ci: asserts.assert_equal(len(th_fsa_server_fabrics) + 1, len(th_fsa_server_fabrics_new),