Skip to content

Commit fe441f0

Browse files
committed
Start with an implementation of accepted commands (no testing yet)
1 parent ccd52a1 commit fe441f0

File tree

7 files changed

+182
-2
lines changed

7 files changed

+182
-2
lines changed

src/app/data-model-provider/MetadataTypes.h

+10
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ struct CommandEntry
148148
static const CommandEntry kInvalid;
149149
};
150150

151+
struct AcceptedCommandEntry {
152+
CommandId commandId;
153+
154+
// TODO: this can be more compact (use some flags for privilege)
155+
// to make this compact, add a compact enum and make flags/invokePrivilege getters (to still be type safe)
156+
BitFlags<CommandQualityFlags> flags;
157+
Access::Privilege invokePrivilege = Access::Privilege::kOperate;
158+
};
159+
151160
/// Represents a device type that resides on an endpoint
152161
struct DeviceTypeEntry
153162
{
@@ -222,6 +231,7 @@ class ProviderMetadataTree
222231

223232
/// List all the generated commands for the given path
224233
virtual MetadataList<CommandId> GeneratedCommands(const ConcreteClusterPath &path) = 0;
234+
virtual MetadataList<AcceptedCommandEntry> AcceptedCommands(const ConcreteClusterPath &path) = 0;
225235

226236

227237
/// Workaround function to report attribute change.

src/app/tests/test-interaction-model-api.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,11 @@ std::optional<CommandInfo> TestImCustomDataModel::GetAcceptedCommandInfo(const C
241241
return CodegenDataModelProviderInstance(nullptr /* delegate */)->GetAcceptedCommandInfo(path);
242242
}
243243

244+
MetadataList<DataModel::AcceptedCommandEntry> TestImCustomDataModel::AcceptedCommands(const ConcreteClusterPath & path)
245+
{
246+
return CodegenDataModelProviderInstance(nullptr /* delegate */)->AcceptedCommands(path);
247+
}
248+
244249
MetadataList<CommandId> TestImCustomDataModel::GeneratedCommands(const ConcreteClusterPath & path)
245250
{
246251
return CodegenDataModelProviderInstance(nullptr /* delegate */)->GeneratedCommands(path);

src/app/tests/test-interaction-model-api.h

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ class TestImCustomDataModel : public DataModel::Provider
111111
chip::TLV::TLVReader & input_arguments, CommandHandler * handler) override;
112112

113113
MetadataList<CommandId> GeneratedCommands(const ConcreteClusterPath &path) override;
114+
MetadataList<DataModel::AcceptedCommandEntry> AcceptedCommands(const ConcreteClusterPath &path) override;
114115

115116
DataModel::EndpointEntry FirstEndpoint() override;
116117
DataModel::EndpointEntry NextEndpoint(EndpointId before) override;

src/controller/tests/data_model/DataModelFixtures.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,11 @@ std::optional<CommandInfo> CustomDataModel::GetAcceptedCommandInfo(const Concret
569569
return CodegenDataModelProviderInstance(nullptr /* delegate */)->GetAcceptedCommandInfo(path);
570570
}
571571

572+
MetadataList<DataModel::AcceptedCommandEntry> CustomDataModel::AcceptedCommands(const ConcreteClusterPath & path)
573+
{
574+
return CodegenDataModelProviderInstance(nullptr /* delegate */)->AcceptedCommands(path);
575+
}
576+
572577
MetadataList<CommandId> CustomDataModel::GeneratedCommands(const ConcreteClusterPath & path)
573578
{
574579
return CodegenDataModelProviderInstance(nullptr /* delegate */)->GeneratedCommands(path);

src/controller/tests/data_model/DataModelFixtures.h

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ class CustomDataModel : public DataModel::Provider
123123
chip::TLV::TLVReader & input_arguments, CommandHandler * handler) override;
124124

125125
MetadataList<CommandId> GeneratedCommands(const ConcreteClusterPath &path) override;
126+
MetadataList<DataModel::AcceptedCommandEntry> AcceptedCommands(const ConcreteClusterPath &path) override;
126127

127128
DataModel::EndpointEntry FirstEndpoint() override;
128129
DataModel::EndpointEntry NextEndpoint(EndpointId before) override;

src/data-model-providers/codegen/CodegenDataModelProvider.cpp

+159-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <lib/support/CodeUtils.h>
4141
#include <lib/support/SpanSearchValue.h>
4242

43+
#include <memory>
4344
#include <optional>
4445
#include <variant>
4546

@@ -837,6 +838,154 @@ std::optional<DataModel::CommandInfo> CodegenDataModelProvider::GetAcceptedComma
837838
return CommandEntryFrom(path, commandId).info;
838839
}
839840

841+
MetadataList<DataModel::AcceptedCommandEntry> CodegenDataModelProvider::AcceptedCommands(const ConcreteClusterPath & path)
842+
{
843+
CommandHandlerInterface * interface =
844+
CommandHandlerInterfaceRegistry::Instance().GetCommandHandler(path.mEndpointId, path.mClusterId);
845+
if (interface != nullptr)
846+
{
847+
size_t commandCount = 0;
848+
849+
CHIP_ERROR err = interface->EnumerateAcceptedCommands(
850+
path,
851+
[](CommandId id, void * context) -> Loop {
852+
*reinterpret_cast<size_t *>(context) += 1;
853+
return Loop::Continue;
854+
},
855+
reinterpret_cast<void *>(&commandCount));
856+
857+
if (err == CHIP_NO_ERROR)
858+
{
859+
typedef struct
860+
{
861+
ConcreteCommandPath commandPath;
862+
MetadataList<DataModel::AcceptedCommandEntry> acceptedCommandList;
863+
} EnumerationData;
864+
865+
EnumerationData enumerationData;
866+
enumerationData.commandPath = ConcreteCommandPath(path.mEndpointId, path.mClusterId, kInvalidCommandId);
867+
868+
err = enumerationData.acceptedCommandList.reserve(commandCount);
869+
if (err != CHIP_NO_ERROR)
870+
{
871+
#if CHIP_CONFIG_DATA_MODEL_EXTRA_LOGGING
872+
ChipLogError(DataManagement, "Failed to reserve space for %u generated commands: %" CHIP_ERROR_FORMAT,
873+
(unsigned) commandCount, err.Format());
874+
#endif
875+
return {};
876+
}
877+
878+
err = interface->EnumerateAcceptedCommands(
879+
path,
880+
[](CommandId commandId, void * context) -> Loop {
881+
auto input = reinterpret_cast<EnumerationData *>(context);
882+
883+
input->commandPath.mCommandId = commandId;
884+
885+
DataModel::AcceptedCommandEntry entry;
886+
887+
entry.commandId = commandId;
888+
entry.invokePrivilege = RequiredPrivilege::ForInvokeCommand(input->commandPath);
889+
entry.flags.Set(DataModel::CommandQualityFlags::kTimed,
890+
CommandNeedsTimedInvoke(input->commandPath.mClusterId, commandId));
891+
892+
entry.flags.Set(DataModel::CommandQualityFlags::kFabricScoped,
893+
CommandIsFabricScoped(input->commandPath.mClusterId, commandId));
894+
895+
entry.flags.Set(DataModel::CommandQualityFlags::kLargeMessage,
896+
897+
CommandHasLargePayload(input->commandPath.mClusterId, commandId));
898+
899+
CHIP_ERROR appendError = input->acceptedCommandList.Append(entry);
900+
if (appendError != CHIP_NO_ERROR)
901+
{
902+
#if CHIP_CONFIG_DATA_MODEL_EXTRA_LOGGING
903+
ChipLogError(DataManagement, "Failed to append generated command: %" CHIP_ERROR_FORMAT,
904+
appendError.Format());
905+
#endif
906+
return Loop::Break;
907+
}
908+
return Loop::Continue;
909+
},
910+
reinterpret_cast<void *>(&enumerationData));
911+
912+
#if CHIP_CONFIG_DATA_MODEL_EXTRA_LOGGING
913+
if (err != CHIP_NO_ERROR)
914+
{
915+
ChipLogError(DataManagement, "Failed to run generated command appending: %" CHIP_ERROR_FORMAT, err.Format());
916+
}
917+
if (enumerationData.acceptedCommandList.size() != commandCount)
918+
{
919+
ChipLogError(DataManagement, "Unexpected (likely short) number of generated commands fetched");
920+
}
921+
#endif
922+
return std::move(enumerationData.acceptedCommandList);
923+
}
924+
925+
if (err != CHIP_ERROR_NOT_IMPLEMENTED)
926+
{
927+
#if CHIP_CONFIG_DATA_MODEL_EXTRA_LOGGING
928+
ChipLogError(DataManagement, "Failed to enumerate generated commands: %" CHIP_ERROR_FORMAT, err.Format());
929+
#endif
930+
return {};
931+
}
932+
}
933+
934+
const EmberAfCluster * cluster = FindServerCluster(path);
935+
if ((cluster == nullptr) || (cluster->acceptedCommandList == nullptr))
936+
{
937+
return {};
938+
}
939+
const chip::CommandId * endOfList = cluster->acceptedCommandList;
940+
while (*endOfList != kInvalidCommandId)
941+
{
942+
endOfList++;
943+
}
944+
const size_t commandCount = static_cast<size_t>(endOfList - cluster->acceptedCommandList);
945+
946+
MetadataList<DataModel::AcceptedCommandEntry> result;
947+
CHIP_ERROR err = result.reserve(commandCount);
948+
949+
if (err != CHIP_NO_ERROR)
950+
{
951+
#if CHIP_CONFIG_DATA_MODEL_EXTRA_LOGGING
952+
ChipLogError(DataManagement, "Failed to reserve space for %u accepted commands: %" CHIP_ERROR_FORMAT,
953+
(unsigned) commandCount, err.Format());
954+
#endif
955+
return {};
956+
}
957+
958+
ConcreteCommandPath commandPath = ConcreteCommandPath(path.mEndpointId, path.mClusterId, kInvalidCommandId);
959+
960+
for (const chip::CommandId * p = cluster->acceptedCommandList; p != endOfList; p++)
961+
{
962+
commandPath.mCommandId = *p;
963+
964+
DataModel::AcceptedCommandEntry entry;
965+
966+
entry.commandId = commandPath.mCommandId;
967+
entry.invokePrivilege = RequiredPrivilege::ForInvokeCommand(commandPath);
968+
entry.flags.Set(DataModel::CommandQualityFlags::kTimed, CommandNeedsTimedInvoke(path.mClusterId, commandPath.mCommandId));
969+
970+
entry.flags.Set(DataModel::CommandQualityFlags::kFabricScoped,
971+
CommandIsFabricScoped(path.mClusterId, commandPath.mCommandId));
972+
973+
entry.flags.Set(DataModel::CommandQualityFlags::kLargeMessage,
974+
CommandHasLargePayload(path.mClusterId, commandPath.mCommandId));
975+
976+
err = result.Append(entry);
977+
if (err != CHIP_NO_ERROR)
978+
{
979+
#if CHIP_CONFIG_DATA_MODEL_EXTRA_LOGGING
980+
ChipLogError(DataManagement, "Failed to append accepted command value: %" CHIP_ERROR_FORMAT, err.Format());
981+
#endif
982+
break;
983+
}
984+
}
985+
986+
return result;
987+
}
988+
840989
MetadataList<CommandId> CodegenDataModelProvider::GeneratedCommands(const ConcreteClusterPath & path)
841990
{
842991
CommandHandlerInterface * interface =
@@ -856,7 +1005,15 @@ MetadataList<CommandId> CodegenDataModelProvider::GeneratedCommands(const Concre
8561005
if (err == CHIP_NO_ERROR)
8571006
{
8581007
MetadataList<CommandId> result;
859-
result.reserve(commandCount);
1008+
err = result.reserve(commandCount);
1009+
if (err != CHIP_NO_ERROR)
1010+
{
1011+
#if CHIP_CONFIG_DATA_MODEL_EXTRA_LOGGING
1012+
ChipLogError(DataManagement, "Failed to reserve space for %u generated commands: %" CHIP_ERROR_FORMAT,
1013+
(unsigned) commandCount, err.Format());
1014+
#endif
1015+
return {};
1016+
}
8601017

8611018
err = interface->EnumerateGeneratedCommands(
8621019
path,
@@ -906,7 +1063,7 @@ MetadataList<CommandId> CodegenDataModelProvider::GeneratedCommands(const Concre
9061063
{
9071064
endOfList++;
9081065
}
909-
size_t commandCount = static_cast<size_t>(endOfList - cluster->generatedCommandList);
1066+
const size_t commandCount = static_cast<size_t>(endOfList - cluster->generatedCommandList);
9101067
return MetadataList<CommandId>::FromConstSpan({ cluster->generatedCommandList, commandCount });
9111068
}
9121069

src/data-model-providers/codegen/CodegenDataModelProvider.h

+1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ class CodegenDataModelProvider : public DataModel::Provider
156156

157157
/// attribute tree iteration
158158
MetadataList<CommandId> GeneratedCommands(const ConcreteClusterPath &path) override;
159+
MetadataList<DataModel::AcceptedCommandEntry> AcceptedCommands(const ConcreteClusterPath &path) override;
159160

160161
DataModel::EndpointEntry FirstEndpoint() override;
161162
DataModel::EndpointEntry NextEndpoint(EndpointId before) override;

0 commit comments

Comments
 (0)