-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Linux] Initial implementation of fabric-admin to facilitate Fabric S…
…ynchronization (#33393) * Initial implementation of fabric-admin app * Address review comments
- Loading branch information
1 parent
8199929
commit 3865669
Showing
45 changed files
with
8,540 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Copyright (c) 2024 Project CHIP Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import("//build_overrides/build.gni") | ||
|
||
# The location of the build configuration file. | ||
buildconfig = "${build_root}/config/BUILDCONFIG.gn" | ||
|
||
# CHIP uses angle bracket includes. | ||
check_system_includes = true | ||
|
||
default_args = { | ||
import("//args.gni") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
# Copyright (c) 2024 Project CHIP Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import("//build_overrides/build.gni") | ||
import("//build_overrides/chip.gni") | ||
|
||
import("//build_overrides/editline.gni") | ||
import("${chip_root}/build/chip/tools.gni") | ||
import("${chip_root}/examples/fabric-admin/fabric-admin.gni") | ||
import("${chip_root}/src/lib/core/core.gni") | ||
|
||
assert(chip_build_tools) | ||
|
||
config("config") { | ||
include_dirs = [ | ||
".", | ||
"${chip_root}/examples/common", | ||
"${chip_root}/zzz_generated/app-common/app-common", | ||
"${chip_root}/zzz_generated/chip-tool", | ||
"${chip_root}/src/lib", | ||
] | ||
|
||
defines = [ "CONFIG_USE_SEPARATE_EVENTLOOP=${config_use_separate_eventloop}" ] | ||
|
||
# Note: CONFIG_USE_LOCAL_STORAGE is tested for via #ifdef, not #if. | ||
if (config_use_local_storage) { | ||
defines += [ "CONFIG_USE_LOCAL_STORAGE" ] | ||
} | ||
|
||
cflags = [ "-Wconversion" ] | ||
} | ||
|
||
static_library("fabric-admin-utils") { | ||
sources = [ | ||
"${chip_root}/src/controller/ExamplePersistentStorage.cpp", | ||
"${chip_root}/src/controller/ExamplePersistentStorage.h", | ||
"${chip_root}/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp", | ||
"${chip_root}/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp", | ||
"commands/clusters/ModelCommand.cpp", | ||
"commands/clusters/ModelCommand.h", | ||
"commands/common/CHIPCommand.cpp", | ||
"commands/common/CHIPCommand.h", | ||
"commands/common/Command.cpp", | ||
"commands/common/Command.h", | ||
"commands/common/Commands.cpp", | ||
"commands/common/Commands.h", | ||
"commands/common/CredentialIssuerCommands.h", | ||
"commands/common/HexConversion.h", | ||
"commands/common/RemoteDataModelLogger.cpp", | ||
"commands/common/RemoteDataModelLogger.h", | ||
"commands/pairing/OpenCommissioningWindowCommand.cpp", | ||
"commands/pairing/OpenCommissioningWindowCommand.h", | ||
"commands/pairing/PairingCommand.cpp", | ||
"commands/pairing/ToTLVCert.cpp", | ||
] | ||
|
||
deps = [ "${chip_root}/src/app:events" ] | ||
|
||
sources += [ "commands/interactive/InteractiveCommands.cpp" ] | ||
deps += [ | ||
"${chip_root}/examples/common/websocket-server", | ||
"${chip_root}/src/platform/logging:headers", | ||
"${editline_root}:editline", | ||
] | ||
|
||
if (chip_device_platform == "darwin") { | ||
sources += [ "commands/common/DeviceScanner.cpp" ] | ||
} | ||
|
||
public_deps = [ | ||
"${chip_root}/examples/common/tracing:commandline", | ||
"${chip_root}/src/app/icd/client:handler", | ||
"${chip_root}/src/app/icd/client:manager", | ||
"${chip_root}/src/app/server", | ||
"${chip_root}/src/app/tests/suites/commands/interaction_model", | ||
"${chip_root}/src/controller/data_model", | ||
"${chip_root}/src/credentials:file_attestation_trust_store", | ||
"${chip_root}/src/lib", | ||
"${chip_root}/src/lib/core:types", | ||
"${chip_root}/src/lib/support/jsontlv", | ||
"${chip_root}/src/platform", | ||
"${chip_root}/third_party/inipp", | ||
"${chip_root}/third_party/jsoncpp", | ||
] | ||
|
||
public_configs = [ ":config" ] | ||
|
||
if (chip_enable_transport_trace) { | ||
public_deps += | ||
[ "${chip_root}/examples/common/tracing:trace_handlers_decoder" ] | ||
} | ||
|
||
output_dir = root_out_dir | ||
} | ||
|
||
executable("fabric-admin") { | ||
sources = [ "main.cpp" ] | ||
|
||
deps = [ | ||
":fabric-admin-utils", | ||
"${chip_root}/src/platform/logging:force_stdio", | ||
] | ||
|
||
output_dir = root_out_dir | ||
} | ||
|
||
group("default") { | ||
deps = [ ":fabric-admin" ] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Copyright (c) 2024 Project CHIP Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import("//build_overrides/chip.gni") | ||
|
||
import("${chip_root}/config/standalone/args.gni") | ||
|
||
chip_device_project_config_include = "<CHIPProjectAppConfig.h>" | ||
chip_project_config_include = "<CHIPProjectAppConfig.h>" | ||
chip_system_project_config_include = "<SystemProjectConfig.h>" | ||
|
||
chip_project_config_include_dirs = | ||
[ "${chip_root}/examples/fabric-admin/include" ] | ||
chip_project_config_include_dirs += [ "${chip_root}/config/standalone" ] | ||
|
||
matter_enable_tracing_support = true | ||
|
||
matter_log_json_payload_hex = true | ||
matter_log_json_payload_decode_full = true | ||
|
||
# make fabric-admin very strict by default | ||
chip_tlv_validate_char_string_on_read = true | ||
chip_tlv_validate_char_string_on_write = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../build_overrides |
196 changes: 196 additions & 0 deletions
196
examples/fabric-admin/commands/clusters/ClusterCommand.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
/* | ||
* 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/tests/suites/commands/interaction_model/InteractionModel.h> | ||
|
||
#include "DataModelLogger.h" | ||
#include "ModelCommand.h" | ||
|
||
class ClusterCommand : public InteractionModelCommands, public ModelCommand, public chip::app::CommandSender::Callback | ||
{ | ||
public: | ||
ClusterCommand(CredentialIssuerCommands * credsIssuerConfig) : | ||
InteractionModelCommands(this), ModelCommand("command-by-id", credsIssuerConfig) | ||
{ | ||
AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId); | ||
AddByIdArguments(); | ||
AddArguments(); | ||
} | ||
|
||
ClusterCommand(chip::ClusterId clusterId, CredentialIssuerCommands * credsIssuerConfig) : | ||
InteractionModelCommands(this), ModelCommand("command-by-id", credsIssuerConfig), mClusterId(clusterId) | ||
{ | ||
AddByIdArguments(); | ||
AddArguments(); | ||
} | ||
|
||
~ClusterCommand() {} | ||
|
||
CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds) override | ||
{ | ||
return InteractionModelCommands::SendCommand(device, endpointIds.at(0), mClusterId, mCommandId, mPayload); | ||
} | ||
|
||
template <class T> | ||
CHIP_ERROR SendCommand(chip::DeviceProxy * device, chip::EndpointId endpointId, chip::ClusterId clusterId, | ||
chip::CommandId commandId, const T & value) | ||
{ | ||
return InteractionModelCommands::SendCommand(device, endpointId, clusterId, commandId, value); | ||
} | ||
|
||
CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) override | ||
{ | ||
return InteractionModelCommands::SendGroupCommand(groupId, fabricIndex, mClusterId, mCommandId, mPayload); | ||
} | ||
|
||
template <class T> | ||
CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex, chip::ClusterId clusterId, | ||
chip::CommandId commandId, const T & value) | ||
{ | ||
return InteractionModelCommands::SendGroupCommand(groupId, fabricIndex, clusterId, commandId, value); | ||
} | ||
|
||
/////////// CommandSender Callback Interface ///////// | ||
virtual void OnResponse(chip::app::CommandSender * client, const chip::app::ConcreteCommandPath & path, | ||
const chip::app::StatusIB & status, chip::TLV::TLVReader * data) override | ||
{ | ||
CHIP_ERROR error = status.ToChipError(); | ||
if (CHIP_NO_ERROR != error) | ||
{ | ||
LogErrorOnFailure(RemoteDataModelLogger::LogErrorAsJSON(path, status)); | ||
|
||
ChipLogError(NotSpecified, "Response Failure: %s", chip::ErrorStr(error)); | ||
mError = error; | ||
return; | ||
} | ||
|
||
if (data != nullptr) | ||
{ | ||
LogErrorOnFailure(RemoteDataModelLogger::LogCommandAsJSON(path, data)); | ||
|
||
error = DataModelLogger::LogCommand(path, data); | ||
if (CHIP_NO_ERROR != error) | ||
{ | ||
ChipLogError(NotSpecified, "Response Failure: Can not decode Data"); | ||
mError = error; | ||
return; | ||
} | ||
} | ||
} | ||
|
||
virtual void OnError(const chip::app::CommandSender * client, CHIP_ERROR error) override | ||
{ | ||
LogErrorOnFailure(RemoteDataModelLogger::LogErrorAsJSON(error)); | ||
|
||
ChipLogProgress(NotSpecified, "Error: %s", chip::ErrorStr(error)); | ||
mError = error; | ||
} | ||
|
||
virtual void OnDone(chip::app::CommandSender * client) override | ||
{ | ||
if (mCommandSender.size()) | ||
{ | ||
mCommandSender.front().reset(); | ||
mCommandSender.erase(mCommandSender.begin()); | ||
} | ||
|
||
// If the command is repeated N times, wait for all the responses to comes in | ||
// before exiting. | ||
bool shouldStop = true; | ||
if (mRepeatCount.HasValue()) | ||
{ | ||
mRepeatCount.SetValue(static_cast<uint16_t>(mRepeatCount.Value() - 1)); | ||
shouldStop = mRepeatCount.Value() == 0; | ||
} | ||
|
||
if (shouldStop) | ||
{ | ||
SetCommandExitStatus(mError); | ||
} | ||
} | ||
|
||
void Shutdown() override | ||
{ | ||
mError = CHIP_NO_ERROR; | ||
ModelCommand::Shutdown(); | ||
} | ||
|
||
protected: | ||
ClusterCommand(const char * commandName, CredentialIssuerCommands * credsIssuerConfig) : | ||
InteractionModelCommands(this), ModelCommand(commandName, credsIssuerConfig) | ||
{ | ||
// Subclasses are responsible for calling AddArguments. | ||
} | ||
|
||
void AddByIdArguments() | ||
{ | ||
AddArgument("command-id", 0, UINT32_MAX, &mCommandId); | ||
AddArgument("payload", &mPayload, | ||
"The command payload. This should be a JSON-encoded object, with string representations of field ids as keys. " | ||
" The values for the keys are represented as follows, depending on the type:\n" | ||
" * struct: a JSON-encoded object, with field ids as keys.\n" | ||
" * list: a JSON-encoded array of values.\n" | ||
" * null: A literal null.\n" | ||
" * boolean: A literal true or false.\n" | ||
" * unsigned integer: One of:\n" | ||
" a) The number directly, as decimal.\n" | ||
" b) A string starting with \"u:\" followed by decimal digits\n" | ||
" * signed integer: One of:\n" | ||
" a) The number directly, if it's negative.\n" | ||
" b) A string starting with \"s:\" followed by decimal digits\n" | ||
" * single-precision float: A string starting with \"f:\" followed by the number.\n" | ||
" * double-precision float: One of:\n" | ||
" a) The number directly, if it's not an integer.\n" | ||
" b) A string starting with \"d:\" followed by the number.\n" | ||
" * octet string: A string starting with \"hex:\" followed by the hex encoding of the bytes.\n" | ||
" * string: A string with the characters.\n" | ||
"\n" | ||
" An example payload may look like this: '{ \"0x0\": { \"0\": null, \"1\": false }, \"1\": [17, \"u:17\"], " | ||
"\"0x2\": [ -17, \"s:17\", \"s:-17\" ], \"0x3\": \"f:2\", \"0x4\": [ \"d:3\", 4.5 ], \"0x5\": \"hex:ab12\", " | ||
"\"0x6\": \"ab12\" }' and represents:\n" | ||
" Field 0: a struct with two fields, one with value null and one with value false.\n" | ||
" Field 1: A list of unsigned integers.\n" | ||
" Field 2: A list of signed integers.\n" | ||
" Field 3: A single-precision float.\n" | ||
" Field 4: A list of double-precision floats.\n" | ||
" Field 5: A 2-byte octet string.\n" | ||
" Field 6: A 4-char character string."); | ||
} | ||
|
||
void AddArguments() | ||
{ | ||
AddArgument("timedInteractionTimeoutMs", 0, UINT16_MAX, &mTimedInteractionTimeoutMs, | ||
"If provided, do a timed invoke with the given timed interaction timeout. See \"7.6.10. Timed Interaction\" in " | ||
"the Matter specification."); | ||
AddArgument("busyWaitForMs", 0, UINT16_MAX, &mBusyWaitForMs, | ||
"If provided, block the main thread processing for the given time right after sending a command."); | ||
AddArgument("suppressResponse", 0, 1, &mSuppressResponse); | ||
AddArgument("repeat-count", 1, UINT16_MAX, &mRepeatCount); | ||
AddArgument("repeat-delay-ms", 0, UINT16_MAX, &mRepeatDelayInMs); | ||
ModelCommand::AddArguments(); | ||
} | ||
|
||
private: | ||
chip::ClusterId mClusterId; | ||
chip::CommandId mCommandId; | ||
|
||
CHIP_ERROR mError = CHIP_NO_ERROR; | ||
CustomArgument mPayload; | ||
}; |
Oops, something went wrong.