Skip to content

Commit

Permalink
Merge d94e8d7 into ec9cdbb
Browse files Browse the repository at this point in the history
  • Loading branch information
erjiaqing authored Feb 9, 2024
2 parents ec9cdbb + d94e8d7 commit 1101335
Show file tree
Hide file tree
Showing 12 changed files with 322 additions and 7 deletions.
2 changes: 2 additions & 0 deletions examples/chip-tool/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ static_library("chip-tool-utils") {
"commands/discover/DiscoverCommand.cpp",
"commands/discover/DiscoverCommissionablesCommand.cpp",
"commands/discover/DiscoverCommissionersCommand.cpp",
"commands/icd/CheckInDelegate.cpp",
"commands/icd/CheckInDelegate.h",
"commands/icd/ICDCommand.cpp",
"commands/icd/ICDCommand.h",
"commands/pairing/OpenCommissioningWindowCommand.cpp",
Expand Down
11 changes: 8 additions & 3 deletions examples/chip-tool/commands/clusters/ModelCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,17 @@ void ModelCommand::CheckPeerICDType()
return;
}

mIsPeerLIT.SetValue(IsDestinationRegisteredLIT());
}

bool ModelCommand::IsDestinationRegisteredLIT()
{
app::ICDClientInfo info;
auto destinationPeerId = chip::ScopedNodeId(mDestinationId, CurrentCommissioner().GetFabricIndex());
auto iter = CHIPCommand::sICDClientStorage.IterateICDClientInfo();
if (iter == nullptr)
{
return;
return false;
}
app::DefaultICDClientStorage::ICDClientInfoIteratorWrapper clientInfoIteratorWrapper(iter);

Expand All @@ -98,8 +103,8 @@ void ModelCommand::CheckPeerICDType()
if (ScopedNodeId(info.peer_node.GetNodeId(), info.peer_node.GetFabricIndex()) == destinationPeerId)
{
ChipLogProgress(chipTool, "Peer is a registered LIT ICD.");
mIsPeerLIT.SetValue(true);
return;
return true;
}
}
return false;
}
7 changes: 7 additions & 0 deletions examples/chip-tool/commands/clusters/ModelCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ class ModelCommand : public CHIPCommand

void Shutdown() override;

chip::ScopedNodeId GetDestination() override
{
return chip::ScopedNodeId(mDestinationId, CurrentCommissioner().GetFabricIndex());
}

bool IsDestinationRegisteredLIT() override;

protected:
bool IsPeerLIT() { return mIsPeerLIT.ValueOr(false); }

Expand Down
2 changes: 1 addition & 1 deletion examples/chip-tool/commands/common/CHIPCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ chip::Credentials::GroupDataProviderImpl CHIPCommand::sGroupDataProvider{ kMaxGr
// All fabrics share the same ICD client storage.
chip::app::DefaultICDClientStorage CHIPCommand::sICDClientStorage;
chip::Crypto::RawKeySessionKeystore CHIPCommand::sSessionKeystore;
chip::app::DefaultCheckInDelegate CHIPCommand::sCheckInDelegate;
CheckInDelegate CHIPCommand::sCheckInDelegate;
chip::app::CheckInHandler CHIPCommand::sCheckInHandler;

namespace {
Expand Down
7 changes: 6 additions & 1 deletion examples/chip-tool/commands/common/CHIPCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <app/icd/client/DefaultICDClientStorage.h>
#include <commands/common/CredentialIssuerCommands.h>
#include <commands/example/ExampleCredentialIssuerCommands.h>
#include <commands/icd/CheckInDelegate.h>
#include <credentials/GroupDataProviderImpl.h>
#include <credentials/PersistentStorageOpCertStore.h>
#include <crypto/PersistentStorageOperationalKeystore.h>
Expand Down Expand Up @@ -117,6 +118,10 @@ class CHIPCommand : public Command
StopWaiting();
}

void AddExtraCheckInDelegate(chip::app::CheckInDelegate * delegate) { sCheckInDelegate.AddExtraDelegate(delegate); }

void RemoveExtraCheckInDelegate(chip::app::CheckInDelegate * delegate) { sCheckInDelegate.RemoveExtraDelegate(delegate); }

protected:
// Will be called in a setting in which it's safe to touch the CHIP
// stack. The rules for Run() are as follows:
Expand Down Expand Up @@ -164,7 +169,7 @@ class CHIPCommand : public Command

static chip::Credentials::GroupDataProviderImpl sGroupDataProvider;
static chip::app::DefaultICDClientStorage sICDClientStorage;
static chip::app::DefaultCheckInDelegate sCheckInDelegate;
static CheckInDelegate sCheckInDelegate;
static chip::app::CheckInHandler sCheckInHandler;
CredentialIssuerCommands * mCredIssuerCmds;

Expand Down
5 changes: 5 additions & 0 deletions examples/chip-tool/commands/common/Command.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <commands/clusters/CustomArgument.h>
#include <inet/InetInterface.h>
#include <lib/core/Optional.h>
#include <lib/core/ScopedNodeId.h>
#include <lib/support/Span.h>
#include <lib/support/logging/CHIPLogging.h>

Expand Down Expand Up @@ -277,6 +278,10 @@ class Command

const chip::Optional<char *> & GetStorageDirectory() const { return mStorageDirectory; }

virtual chip::ScopedNodeId GetDestination() { return chip::ScopedNodeId(); }

virtual bool IsDestinationRegisteredLIT() { return false; }

protected:
// mStorageDirectory lives here so we can just set it in RunAsInteractive.
chip::Optional<char *> mStorageDirectory;
Expand Down
106 changes: 105 additions & 1 deletion examples/chip-tool/commands/common/Commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
namespace {

char kInteractiveModeName[] = "";
char kQueuedCommandModeName[] = "(queue)";
constexpr size_t kInteractiveModeArgumentsMaxLength = 32;
constexpr char kOptionalArgumentPrefix[] = "--";
constexpr char kJsonClusterKey[] = "cluster";
Expand Down Expand Up @@ -222,6 +223,7 @@ CHIP_ERROR Commands::RunCommand(int argc, char ** argv, bool interactive,
const chip::Optional<char *> & interactiveStorageDirectory, bool interactiveAdvertiseOperational)
{
Command * command = nullptr;
bool queueCommand = false;

if (argc <= 1)
{
Expand All @@ -230,6 +232,27 @@ CHIP_ERROR Commands::RunCommand(int argc, char ** argv, bool interactive,
return CHIP_ERROR_INVALID_ARGUMENT;
}

if (strncmp(argv[1], "dumpstate", 9) == 0)
{
DumpState();
return CHIP_NO_ERROR;
}
if (strncmp(argv[1], "queue", 5) == 0)
{
if (!interactive)
{
ChipLogError(chipTool, "Commands can be queued in interactive mode only.");
return CHIP_ERROR_INVALID_ARGUMENT;
}
queueCommand = true;
argc--;
argv++;
}
if (strncmp(argv[0], kQueuedCommandModeName, strlen(kQueuedCommandModeName)) == 0)
{
ChipLogProgress(chipTool, "Running previously queued command.");
}

auto commandSetIter = GetCommandSet(argv[1]);
if (commandSetIter == mCommandSets.end())
{
Expand Down Expand Up @@ -307,7 +330,32 @@ CHIP_ERROR Commands::RunCommand(int argc, char ** argv, bool interactive,

if (interactive)
{
return command->RunAsInteractive(interactiveStorageDirectory, interactiveAdvertiseOperational);
if (!queueCommand)
{
return command->RunAsInteractive(interactiveStorageDirectory, interactiveAdvertiseOperational);
}

chip::ScopedNodeId destination = command->GetDestination();
if (destination.GetNodeId() == chip::kUndefinedNodeId)
{
ChipLogError(chipTool, "The command cannot be queued!");
return CHIP_ERROR_INVALID_ARGUMENT;
}
if (!command->IsDestinationRegisteredLIT())
{
ChipLogError(chipTool, "The destination is not a registered LIT device.");
return CHIP_ERROR_INVALID_ARGUMENT;
}
std::vector<std::string> queuedCommand;
for (int i = 1; i < argc; i++)
{
queuedCommand.push_back(std::string(argv[i]));
}

mQueuedCommands[destination].emplace_back(queuedCommand);
ChipLogError(chipTool, "The command is queued for node %" PRIu32 ":" ChipLogFormatX64,
static_cast<uint32_t>(destination.GetFabricIndex()), ChipLogValueX64(destination.GetNodeId()));
return CHIP_NO_ERROR;
}

// Now that the command is initialized, get our storage from it as needed
Expand All @@ -331,6 +379,62 @@ CHIP_ERROR Commands::RunCommand(int argc, char ** argv, bool interactive,
return command->Run();
}

void Commands::DumpState() const
{
fprintf(stderr, ".mQueuedCommands = \n");
for (const auto & queue : mQueuedCommands)
{
auto peer = queue.first;
fprintf(stderr, " [%" PRIu32 ":" ChipLogFormatX64 "] = \n", static_cast<uint32_t>(peer.GetFabricIndex()),
ChipLogValueX64(peer.GetNodeId()));
for (const auto & command : queue.second)
{
std::string commandStr;
for (auto & arg : command)
{
commandStr += arg;
commandStr += " ";
}
fprintf(stderr, " %s\n", commandStr.c_str());
}
}
}

void Commands::RunAllQueuedCommandsForNode(chip::ScopedNodeId nodeId, const chip::Optional<char *> & interactiveStorageDirectory,
bool interactiveAdvertiseOperational)
{
auto commands = mQueuedCommands[nodeId];
mQueuedCommands[nodeId].clear();

for (auto && command : commands)
{
int argc = 0;
char * argv[kInteractiveModeArgumentsMaxLength] = {};
argv[argc++] = kQueuedCommandModeName;

std::string commandStr;
for (auto & arg : command)
{
argv[argc] = new char[arg.size() + 1];
strcpy(argv[argc++], arg.c_str());
commandStr += arg;
commandStr += " ";
}

ChipLogProgress(chipTool, "Execute previously queued command: %s", commandStr.c_str());
auto err = RunCommand(argc, argv, true, interactiveStorageDirectory, interactiveAdvertiseOperational);

// Do not delete arg[0]
for (auto i = 1; i < argc; i++)
{
delete[] argv[i];
}

ChipLogError(chipTool, "Command execution complete!");
ChipLogError(chipTool, "Execution result: %s", chip::ErrorStr(err));
}
}

Commands::CommandSetMap::iterator Commands::GetCommandSet(std::string commandSetName)
{
for (auto & commandSet : mCommandSets)
Expand Down
18 changes: 18 additions & 0 deletions examples/chip-tool/commands/common/Commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
#endif // CONFIG_USE_LOCAL_STORAGE

#include "Command.h"
#include <lib/core/CHIPEncoding.h>
#include <lib/core/ScopedNodeId.h>
#include <map>
#include <vector>

class Commands
{
Expand All @@ -44,7 +47,19 @@ class Commands
int Run(int argc, char ** argv);
int RunInteractive(const char * command, const chip::Optional<char *> & storageDirectory, bool advertiseOperational);

void RunAllQueuedCommandsForNode(chip::ScopedNodeId nodeId, const chip::Optional<char *> & interactiveStorageDirectory,
bool interactiveAdvertiseOperational);

private:
struct ScopedNodeIdComparer
{
bool operator()(const chip::ScopedNodeId & lhs, const chip::ScopedNodeId & rhs) const
{
return lhs.GetFabricIndex() == rhs.GetFabricIndex() ? lhs.GetNodeId() < rhs.GetNodeId()
: lhs.GetFabricIndex() < rhs.GetFabricIndex();
}
};

struct CommandSet
{
CommandsVector commands;
Expand All @@ -66,6 +81,8 @@ class Commands
bool IsEventCommand(std::string commandName) const;
bool IsGlobalCommand(std::string commandName) const;

void DumpState() const;

void ShowCommandSets(std::string executable);
static void ShowCommandSetOverview(std::string commandSetName, const CommandSet & commandSet);
void ShowCommandSet(std::string executable, std::string commandSetName, CommandsVector & commands, const char * helpText);
Expand All @@ -83,6 +100,7 @@ class Commands
void Register(const char * commandSetName, commands_list commandsList, const char * helpText, bool isCluster);

CommandSetMap mCommandSets;
std::map<chip::ScopedNodeId, std::vector<std::vector<std::string>>, ScopedNodeIdComparer> mQueuedCommands;
#ifdef CONFIG_USE_LOCAL_STORAGE
PersistentStorage mStorage;
#endif // CONFIG_USE_LOCAL_STORAGE
Expand Down
29 changes: 29 additions & 0 deletions examples/chip-tool/commands/icd/CheckInDelegate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 "CheckInDelegate.h"

void CheckInDelegate::OnCheckInComplete(const chip::app::ICDClientInfo & clientInfo)
{
chip::app::DefaultCheckInDelegate::OnCheckInComplete(clientInfo);

if (mExtraDelegate != nullptr)
{
mExtraDelegate->OnCheckInComplete(clientInfo);
}
}
35 changes: 35 additions & 0 deletions examples/chip-tool/commands/icd/CheckInDelegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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.
*
*/

#pragma once

#include <app/icd/client/CheckInHandler.h>
#include <app/icd/client/DefaultCheckInDelegate.h>

class CheckInDelegate : public chip::app::DefaultCheckInDelegate
{
public:
void OnCheckInComplete(const chip::app::ICDClientInfo & clientInfo) override;

void AddExtraDelegate(chip::app::CheckInDelegate * delegate) { mExtraDelegate = delegate; }

void RemoveExtraDelegate(chip::app::CheckInDelegate * delegate) { mExtraDelegate = nullptr; }

private:
chip::app::CheckInDelegate * mExtraDelegate;
};
Loading

0 comments on commit 1101335

Please sign in to comment.