| /* |
| * Copyright (c) 2024 Project CHIP Authors |
| * All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| #include "SyncDeviceCommand.h" |
| |
| #include <admin/DeviceManager.h> |
| #include <lib/shell/streamer.h> |
| #include <setup_payload/ManualSetupPayloadGenerator.h> |
| |
| using namespace ::chip; |
| |
| namespace { |
| |
| // Constants |
| constexpr uint32_t kCommissionPrepareTimeMs = 500; |
| |
| } // namespace |
| |
| namespace commands { |
| |
| SyncDeviceCommand::SyncDeviceCommand(EndpointId remoteEndpointId) : mRemoteEndpointId(remoteEndpointId) {} |
| |
| void SyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ERROR err, SetupPayload payload) |
| { |
| ChipLogProgress(NotSpecified, "FabricSyncDeviceCommand::OnCommissioningWindowOpened"); |
| |
| if (err == CHIP_NO_ERROR) |
| { |
| char payloadBuffer[admin::kMaxManualCodeLength + 1]; |
| MutableCharSpan manualCode(payloadBuffer); |
| CHIP_ERROR error = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualCode); |
| if (error == CHIP_NO_ERROR) |
| { |
| NodeId nodeId = admin::DeviceManager::Instance().GetNextAvailableNodeId(); |
| |
| admin::PairingManager::Instance().SetPairingDelegate(this); |
| mAssignedNodeId = nodeId; |
| |
| usleep(kCommissionPrepareTimeMs * 1000); |
| |
| error = admin::PairingManager::Instance().PairDeviceWithCode(nodeId, payloadBuffer); |
| if (error != CHIP_NO_ERROR) |
| { |
| ChipLogError(NotSpecified, "Failed to sync device: Node ID " ChipLogFormatX64 " with error: %" CHIP_ERROR_FORMAT, |
| ChipLogValueX64(nodeId), err.Format()); |
| } |
| } |
| else |
| { |
| ChipLogError(NotSpecified, "Unable to generate manual code for setup payload: %" CHIP_ERROR_FORMAT, error.Format()); |
| } |
| } |
| else |
| { |
| ChipLogError(NotSpecified, |
| "Failed to open synced device (0x:" ChipLogFormatX64 ") commissioning window: %" CHIP_ERROR_FORMAT, |
| ChipLogValueX64(deviceId), err.Format()); |
| } |
| } |
| |
| void SyncDeviceCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) |
| { |
| if (mAssignedNodeId != deviceId) |
| { |
| // Ignore if the deviceId does not match the mAssignedNodeId. |
| // This scenario should not occur because no other device should be commissioned during the fabric sync process. |
| return; |
| } |
| |
| if (err == CHIP_NO_ERROR) |
| { |
| admin::DeviceManager::Instance().AddSyncedDevice(admin::SyncedDevice(mAssignedNodeId, mRemoteEndpointId)); |
| } |
| else |
| { |
| ChipLogError(NotSpecified, "Failed to pair synced device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, |
| ChipLogValueX64(deviceId), err.Format()); |
| } |
| |
| CommandRegistry::Instance().ResetActiveCommand(); |
| } |
| |
| CHIP_ERROR SyncDeviceCommand::RunCommand() |
| { |
| if (!admin::DeviceManager::Instance().IsFabricSyncReady()) |
| { |
| // print to console |
| Shell::streamer_t * sout = Shell::streamer_get(); |
| Shell::streamer_printf(sout, "Remote Fabric Bridge has already been configured.\n"); |
| |
| return CHIP_ERROR_INCORRECT_STATE; |
| } |
| |
| ChipLogProgress(NotSpecified, "Running SyncDeviceCommand with EndpointId: %u", mRemoteEndpointId); |
| |
| admin::PairingManager::Instance().SetOpenCommissioningWindowDelegate(this); |
| admin::DeviceManager::Instance().OpenRemoteDeviceCommissioningWindow(mRemoteEndpointId); |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| } // namespace commands |