From ce96697456d3b77a383ae8a980267f5ffa223553 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Fri, 1 Oct 2021 11:33:32 +0200 Subject: [PATCH] [ChipTool] Add a command to enumerate the paired devices and show ip/port/interface informations for them --- examples/chip-tool/BUILD.gn | 2 + .../commands/clusters/ModelCommand.cpp | 4 +- .../chip-tool/commands/pairing/Commands.h | 2 + .../commands/pairing/PairingListCommand.cpp | 97 +++++++++++++++++++ .../commands/pairing/PairingListCommand.h | 35 +++++++ 5 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 examples/chip-tool/commands/pairing/PairingListCommand.cpp create mode 100644 examples/chip-tool/commands/pairing/PairingListCommand.h diff --git a/examples/chip-tool/BUILD.gn b/examples/chip-tool/BUILD.gn index 990b3947c7fa9f..13b9970dd65e71 100644 --- a/examples/chip-tool/BUILD.gn +++ b/examples/chip-tool/BUILD.gn @@ -40,6 +40,8 @@ executable("chip-tool") { "commands/discover/DiscoverCommissionablesCommand.cpp", "commands/discover/DiscoverCommissionersCommand.cpp", "commands/pairing/PairingCommand.cpp", + "commands/pairing/PairingListCommand.cpp", + "commands/pairing/PairingListCommand.h", "commands/payload/AdditionalDataParseCommand.cpp", "commands/payload/SetupPayloadParseCommand.cpp", "commands/reporting/ReportingCommand.cpp", diff --git a/examples/chip-tool/commands/clusters/ModelCommand.cpp b/examples/chip-tool/commands/clusters/ModelCommand.cpp index 818db0862d7a6c..f10fc2d843c887 100644 --- a/examples/chip-tool/commands/clusters/ModelCommand.cpp +++ b/examples/chip-tool/commands/clusters/ModelCommand.cpp @@ -25,9 +25,9 @@ using namespace ::chip; CHIP_ERROR ModelCommand::Run(NodeId remoteId) { - CHIP_ERROR err = CHIP_NO_ERROR; + ChipLogProgress(chipTool, "Sending command to node 0x%" PRIx64, remoteId); - err = mController.GetConnectedDevice(remoteId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); + CHIP_ERROR err = mController.GetConnectedDevice(remoteId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(chipTool, "Failed in initiating connection to the device: %" PRIu64 ", error %" CHIP_ERROR_FORMAT, remoteId, err.Format())); diff --git a/examples/chip-tool/commands/pairing/Commands.h b/examples/chip-tool/commands/pairing/Commands.h index 13ef11d30c096c..f1d174a6fb6e4e 100644 --- a/examples/chip-tool/commands/pairing/Commands.h +++ b/examples/chip-tool/commands/pairing/Commands.h @@ -19,6 +19,7 @@ #pragma once #include "PairingCommand.h" +#include "PairingListCommand.h" class Unpair : public PairingCommand { @@ -176,6 +177,7 @@ void registerCommandsPairing(Commands & commands) make_unique(), make_unique(), make_unique(), + make_unique(), }; commands.Register(clusterName, clusterCommands); diff --git a/examples/chip-tool/commands/pairing/PairingListCommand.cpp b/examples/chip-tool/commands/pairing/PairingListCommand.cpp new file mode 100644 index 00000000000000..c774195efc32b8 --- /dev/null +++ b/examples/chip-tool/commands/pairing/PairingListCommand.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021 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 "PairingListCommand.h" + +#include +#include +#include +#include + +CHIP_ERROR PairingListCommand::Run() +{ + ReturnLogErrorOnFailure(mStorage.Init()); + return PrintInformations(); +} + +CHIP_ERROR PairingListCommand::PrintInformations() +{ + uint64_t buffer[chip::Controller::kNumMaxPairedDevices]; + uint16_t bufferSize = sizeof(buffer); + memset(buffer, 0, bufferSize); + + PERSISTENT_KEY_OP(static_cast(0), chip::kPairedDeviceListKeyPrefix, key, + ReturnLogErrorOnFailure(mStorage.SyncGetKeyValue(key, buffer, bufferSize))); + + chip::SerializableU64Set devices; + devices.Deserialize(chip::ByteSpan((uint8_t *) buffer, bufferSize)); + + uint16_t devicesCount = 0; + while (buffer[devicesCount] != 0x0 && devicesCount < chip::Controller::kNumMaxPairedDevices) + { + devicesCount++; + } + + if (devicesCount == 0) + { + ChipLogProgress(chipTool, "No paired devices."); + } + else + { + fprintf(stderr, "+---------------------------------------------------------------------------------------------+\n"); + fprintf(stderr, "| NodeId | Address | Port | Interface |\n"); + fprintf(stderr, "+---------------------------------------------------------------------------------------------+\n"); + for (uint16_t i = 0; i < devicesCount; i++) + { + ReturnLogErrorOnFailure(PrintDeviceInformations(buffer[i])); + } + fprintf(stderr, "+---------------------------------------------------------------------------------------------+\n"); + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR PairingListCommand::PrintDeviceInformations(chip::NodeId deviceId) +{ + chip::Controller::SerializedDevice deviceInfo; + uint16_t size = sizeof(deviceInfo.inner); + + PERSISTENT_KEY_OP(deviceId, chip::kPairedDeviceKeyPrefix, key, + ReturnLogErrorOnFailure(mStorage.SyncGetKeyValue(key, deviceInfo.inner, size))); + VerifyOrReturnError(size <= sizeof(deviceInfo.inner), CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); + + chip::Controller::SerializableDevice serializable; + constexpr size_t maxlen = BASE64_ENCODED_LEN(sizeof(serializable)); + const size_t len = strnlen(chip::Uint8::to_const_char(&deviceInfo.inner[0]), maxlen); + + VerifyOrReturnError(len < sizeof(chip::Controller::SerializedDevice), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(chip::CanCastTo(len), CHIP_ERROR_INVALID_ARGUMENT); + + CHIP_ZERO_AT(serializable); + const uint16_t deserializedLen = chip::Base64Decode(chip::Uint8::to_const_char(deviceInfo.inner), static_cast(len), + chip::Uint8::to_uchar(reinterpret_cast(&serializable))); + + VerifyOrReturnError(deserializedLen > 0, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(deserializedLen <= sizeof(serializable), CHIP_ERROR_INVALID_ARGUMENT); + + const uint16_t port = chip::Encoding::LittleEndian::HostSwap16(serializable.mDevicePort); + fprintf(stderr, "| 0x%-16" PRIx64 " | %-45s | %-5u| %-15s |\n", deviceId, serializable.mDeviceAddr, port, + serializable.mInterfaceName); + + return CHIP_NO_ERROR; +} diff --git a/examples/chip-tool/commands/pairing/PairingListCommand.h b/examples/chip-tool/commands/pairing/PairingListCommand.h new file mode 100644 index 00000000000000..4e3bb8b1e4a841 --- /dev/null +++ b/examples/chip-tool/commands/pairing/PairingListCommand.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 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. + * + */ + +#pragma once + +#include "../../config/PersistentStorage.h" +#include "../common/Command.h" + +class PairingListCommand : public Command +{ +public: + PairingListCommand() : Command("list") {} + CHIP_ERROR Run() override; + +private: + CHIP_ERROR PrintInformations(); + CHIP_ERROR PrintDeviceInformations(chip::NodeId deviceId); + + PersistentStorage mStorage; +};