Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[chip-tool] Add subscribe-all command #20868

Merged
merged 3 commits into from
Jul 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 68 additions & 2 deletions examples/chip-tool/commands/clusters/ReportCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,20 @@ class ReadAll : public ReadCommand
public:
ReadAll(CredentialIssuerCommands * credsIssuerConfig) : ReadCommand("read-all", credsIssuerConfig)
{
AddArgument("fabric-filtered", 0, 1, &mFabricFiltered);
AddArgument("cluster-ids", 0, UINT32_MAX, &mClusterIds,
vivien-apple marked this conversation as resolved.
Show resolved Hide resolved
"Comma-separated list of cluster ids to read from (e.g. \"6\" or \"8,0x201\").\n Allowed to be 0xFFFFFFFF to "
"indicate a wildcard cluster.");
AddArgument("attribute-ids", 0, UINT32_MAX, &mAttributeIds,
"Comma-separated list of attribute ids to read (e.g. \"0\" or \"1,0xFFFC,0xFFFD\").\n Allowed to be "
"0xFFFFFFFF to indicate a wildcard attribute.");
AddArgument("event-ids", 0, UINT32_MAX, &mEventIds,
"Comma-separated list of event ids to read (e.g. \"0\" or \"1,2,3\").\n Allowed to be "
"0xFFFFFFFF to indicate a wildcard event.");
AddArgument("fabric-filtered", 0, 1, &mFabricFiltered,
"Boolean indicating whether to do a fabric-filtered read. Defaults to true.");
AddArgument("data-versions", 0, UINT32_MAX, &mDataVersions,
"Comma-separated list of data versions for the clusters being read.");
AddArgument("event-min", 0, UINT64_MAX, &mEventNumber);
ReadCommand::AddArguments();
}

Expand All @@ -432,9 +445,62 @@ class ReadAll : public ReadCommand

CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds) override
{
return ReadCommand::ReadAll(device, endpointIds, mFabricFiltered);
return ReadCommand::ReadAll(device, endpointIds, mClusterIds, mAttributeIds, mEventIds, mFabricFiltered, mDataVersions,
mEventNumber);
}

private:
std::vector<chip::ClusterId> mClusterIds;
std::vector<chip::AttributeId> mAttributeIds;
std::vector<chip::EventId> mEventIds;

chip::Optional<bool> mFabricFiltered;
chip::Optional<std::vector<chip::DataVersion>> mDataVersions;
chip::Optional<chip::EventNumber> mEventNumber;
};

class SubscribeAll : public SubscribeCommand
{
public:
SubscribeAll(CredentialIssuerCommands * credsIssuerConfig) : SubscribeCommand("subscribe-all", credsIssuerConfig)
{
AddArgument("cluster-ids", 0, UINT32_MAX, &mClusterIds,
"Comma-separated list of cluster ids to read from (e.g. \"6\" or \"8,0x201\").\n Allowed to be 0xFFFFFFFF to "
"indicate a wildcard cluster.");
AddArgument("attribute-ids", 0, UINT32_MAX, &mAttributeIds,
"Comma-separated list of attribute ids to read (e.g. \"0\" or \"1,0xFFFC,0xFFFD\").\n Allowed to be "
"0xFFFFFFFF to indicate a wildcard attribute.");
AddArgument("event-ids", 0, UINT32_MAX, &mEventIds,
"Comma-separated list of event ids to read (e.g. \"0\" or \"1,2,3\").\n Allowed to be "
"0xFFFFFFFF to indicate a wildcard event.");
AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval,
"The requested minimum interval between reports. Sets MinIntervalFloor in the Subscribe Request.");
AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval,
"The requested maximum interval between reports. Sets MaxIntervalCeiling in the Subscribe Request.");
AddArgument("fabric-filtered", 0, 1, &mFabricFiltered,
"Boolean indicating whether to do a fabric-filtered read. Defaults to true.");
AddArgument("event-min", 0, UINT64_MAX, &mEventNumber);
AddArgument("keepSubscriptions", 0, 1, &mKeepSubscriptions,
"false - Terminate existing subscriptions from initiator.\n true - Leave existing subscriptions in place.");
SubscribeCommand::AddArguments();
}

~SubscribeAll() {}

CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds) override
{
return SubscribeCommand::SubscribeAll(device, endpointIds, mClusterIds, mAttributeIds, mEventIds, mMinInterval,
mMaxInterval, mFabricFiltered, mEventNumber, mKeepSubscriptions);
}

private:
std::vector<chip::ClusterId> mClusterIds;
std::vector<chip::AttributeId> mAttributeIds;
std::vector<chip::EventId> mEventIds;

uint16_t mMinInterval;
uint16_t mMaxInterval;
chip::Optional<bool> mFabricFiltered;
chip::Optional<chip::EventNumber> mEventNumber;
chip::Optional<bool> mKeepSubscriptions;
};
1 change: 1 addition & 0 deletions examples/chip-tool/templates/commands.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ void registerClusterAny(Commands & commands, CredentialIssuerCommands * credsIss
make_unique<ReadEvent>(credsIssuerConfig), //
make_unique<SubscribeEvent>(credsIssuerConfig), //
make_unique<ReadAll>(credsIssuerConfig), //
make_unique<SubscribeAll>(credsIssuerConfig), //
};

commands.Register(clusterName, clusterCommands);
Expand Down
116 changes: 105 additions & 11 deletions src/app/tests/suites/commands/interaction_model/InteractionModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,35 +449,129 @@ void InteractionModelReports::CleanupReadClient(ReadClient * aReadClient)
mReadClients.end());
}

CHIP_ERROR InteractionModelReports::ReadAll(DeviceProxy * device, std::vector<EndpointId> endpointIds,
const Optional<bool> & fabricFiltered)
CHIP_ERROR InteractionModelReports::ReportAll(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
std::vector<chip::ClusterId> clusterIds, std::vector<chip::AttributeId> attributeIds,
std::vector<chip::EventId> eventIds,
chip::app::ReadClient::InteractionType interactionType, uint16_t minInterval,
uint16_t maxInterval, const chip::Optional<bool> & fabricFiltered,
const chip::Optional<std::vector<chip::DataVersion>> & dataVersions,
const chip::Optional<chip::EventNumber> & eventNumber,
const chip::Optional<bool> & keepSubscriptions)
{
const size_t endpointCount = endpointIds.size();
const size_t clusterCount = clusterIds.size();
const size_t attributeCount = attributeIds.size();
const size_t eventCount = eventIds.size();

// TODO Add data version supports
// TODO Add isUrgents supports

VerifyOrReturnError(endpointCount > 0 && endpointCount <= kMaxAllowedPaths, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(clusterCount > 0 && clusterCount <= kMaxAllowedPaths, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(attributeCount > 0 && attributeCount <= kMaxAllowedPaths, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(eventCount > 0 && eventCount <= kMaxAllowedPaths, CHIP_ERROR_INVALID_ARGUMENT);

const bool hasSameIdsCount = (clusterCount == (attributeCount + eventCount)) && (clusterCount == endpointCount);
if (!hasSameIdsCount)
{
ChipLogError(chipTool,
"\nCommand targetting a combination of attribute and event paths needs to have has many clusters and "
"endpoints than the number of attribute and events combined.\n"
Comment on lines +478 to +479
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"... needs to have the same number of clusters and endpoints specified as there are attribute and event ids combined".

"For example if there are 2 attributes and 1 event, the command expects 3 clusters and 3 endpoints.\n"
"Clusters and endpoints ids will be consumed first to populate the attribute paths of the request, and then "
"to populate the event paths of the request.\n\n"
"For example the following arguments:\n"
"\tcluster-ids: 6,6,0X28\n"
"\tendpoint-ids: 1,1,0\n"
"\tattribute-ids: 0,0x4001\n"
"\tevent-ids: 0\n"
"\n"
"will create the following paths:\n"
"\t{cluster: 6, endpoint: 1, attribute: 0}\n"
"\t{cluster: 6, endpoint: 1, attribute: 0x4001}\n"
"\t{cluster: 0x28, endpoint: 0, event: 0}\n");
return CHIP_ERROR_INVALID_ARGUMENT;
}

AttributePathParams attributePathParams[kMaxAllowedPaths];
EventPathParams eventPathParams[kMaxAllowedPaths];

auto pathsCount = endpointIds.size();
VerifyOrReturnError(pathsCount > 0 && pathsCount <= kMaxAllowedPaths, CHIP_ERROR_INVALID_ARGUMENT);

size_t attributeIndex = 0;
size_t eventIndex = 0;
size_t pathsCount = clusterCount;
for (size_t i = 0; i < pathsCount; i++)
{
auto endpointId = endpointIds.at(i);
attributePathParams[i].mEndpointId = endpointId;
eventPathParams[i].mEndpointId = endpointId;
auto clusterId = clusterIds.at(i);
auto endpointId = endpointIds.at(i);

if (attributeIndex < attributeIds.size())
{
auto attributeId = attributeIds.at(attributeIndex);

if (endpointId != kInvalidEndpointId)
{
attributePathParams[attributeIndex].mEndpointId = endpointId;
}

if (clusterId != kInvalidClusterId)
{
attributePathParams[attributeIndex].mClusterId = clusterId;
}

if (attributeId != kInvalidAttributeId)
{
attributePathParams[attributeIndex].mAttributeId = attributeId;
}

attributeIndex++;
}
else if (eventIndex < eventIds.size())
{
auto eventId = eventIds.at(eventIndex);

if (endpointId != kInvalidEndpointId)
{
eventPathParams[eventIndex].mEndpointId = endpointId;
}

if (clusterId != kInvalidClusterId)
{
eventPathParams[eventIndex].mClusterId = clusterId;
}

if (eventId != kInvalidEventId)
{
eventPathParams[eventIndex].mEventId = eventId;
}

eventIndex++;
}
}

ReadPrepareParams params(device->GetSecureSession().Value());
params.mpEventPathParamsList = eventPathParams;
params.mEventPathParamsListSize = pathsCount;
params.mEventPathParamsListSize = eventCount;
params.mEventNumber = eventNumber;
params.mpAttributePathParamsList = attributePathParams;
params.mAttributePathParamsListSize = pathsCount;
params.mAttributePathParamsListSize = attributeCount;

if (fabricFiltered.HasValue())
{
params.mIsFabricFiltered = fabricFiltered.Value();
}

if (interactionType == ReadClient::InteractionType::Subscribe)
{
params.mMinIntervalFloorSeconds = minInterval;
params.mMaxIntervalCeilingSeconds = maxInterval;
if (keepSubscriptions.HasValue())
{
params.mKeepSubscriptions = keepSubscriptions.Value();
}
}

auto client = std::make_unique<ReadClient>(InteractionModelEngine::GetInstance(), device->GetExchangeManager(),
mBufferedReadAdapter, ReadClient::InteractionType::Read);
mBufferedReadAdapter, interactionType);
ReturnErrorOnFailure(client->SendRequest(params));
mReadClients.push_back(std::move(client));
return CHIP_NO_ERROR;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,35 @@ class InteractionModelReports
const chip::Optional<std::vector<bool>> & isUrgents = chip::NullOptional);

CHIP_ERROR ReadAll(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
const chip::Optional<bool> & fabricFiltered = chip::Optional<bool>(true));
std::vector<chip::ClusterId> clusterIds, std::vector<chip::AttributeId> attributeIds,
std::vector<chip::EventId> eventIds,
const chip::Optional<bool> & fabricFiltered = chip::Optional<bool>(true),
const chip::Optional<std::vector<chip::DataVersion>> & dataVersions = chip::NullOptional,
const chip::Optional<chip::EventNumber> & eventNumber = chip::NullOptional)
{
return ReportAll(device, endpointIds, clusterIds, attributeIds, eventIds, chip::app::ReadClient::InteractionType::Read, 0,
0, fabricFiltered, dataVersions, eventNumber);
}

CHIP_ERROR SubscribeAll(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
std::vector<chip::ClusterId> clusterIds, std::vector<chip::AttributeId> attributeIds,
std::vector<chip::EventId> eventIds, uint16_t minInterval = 0, uint16_t maxInterval = 0,
const chip::Optional<bool> & fabricFiltered = chip::Optional<bool>(true),
const chip::Optional<chip::EventNumber> & eventNumber = chip::NullOptional,
const chip::Optional<bool> & keepSubscriptions = chip::NullOptional)
{
return ReportAll(device, endpointIds, clusterIds, attributeIds, eventIds, chip::app::ReadClient::InteractionType::Subscribe,
minInterval, maxInterval, fabricFiltered, chip::NullOptional, eventNumber, keepSubscriptions);
}

CHIP_ERROR ReportAll(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
std::vector<chip::ClusterId> clusterIds, std::vector<chip::AttributeId> attributeIds,
std::vector<chip::EventId> eventIds, chip::app::ReadClient::InteractionType interactionType,
uint16_t minInterval = 0, uint16_t maxInterval = 0,
const chip::Optional<bool> & fabricFiltered = chip::Optional<bool>(true),
const chip::Optional<std::vector<chip::DataVersion>> & dataVersions = chip::NullOptional,
const chip::Optional<chip::EventNumber> & eventNumber = chip::NullOptional,
const chip::Optional<bool> & keepSubscriptions = chip::NullOptional);

void Shutdown() { mReadClients.clear(); }

Expand Down
1 change: 1 addition & 0 deletions zzz_generated/chip-tool/zap-generated/cluster/Commands.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.