blob: 9d1c98e1d1d06f0d97c84591f28e4d6f2c269c79 [file] [log] [blame]
{{> header}}
#pragma once
#import <Matter/Matter.h>
#include <cstdint>
#include <string>
#include <type_traits>
#include <commands/clusters/ComplexArgument.h>
#include <app/data-model/DecodableList.h>
#include <commands/clusters/ClusterCommandBridge.h>
#include <commands/clusters/ReportCommandBridge.h>
#include <commands/clusters/WriteAttributeCommandBridge.h>
#include <app-common/zap-generated/cluster-objects.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app-common/zap-generated/ids/Commands.h>
{{> clusters_header}}
{{#zcl_clusters}}
{{#if (isSupported (asUpperCamelCase name preserveAcronyms=true))}}
{{#if (isProvisional (asUpperCamelCase name preserveAcronyms=true))}}
#if MTR_ENABLE_PROVISIONAL
{{/if}}
{{> cluster_header}}
{{#zcl_commands}}
{{#if (is_str_equal source 'client')}}
{{#if (isSupported (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true))}}
{{#if (isProvisional (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true))}}
#if MTR_ENABLE_PROVISIONAL
{{/if}}
/*
* Command {{asUpperCamelCase name}}
*/
class {{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}: public ClusterCommand
{
public:
{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}(): ClusterCommand("{{cleanse_label_as_kebab_case name}}"){{#zcl_command_arguments}}{{#if_chip_complex}}, mComplex_{{asUpperCamelCase label}}(&mRequest.{{asLowerCamelCase label}}){{/if_chip_complex}}{{/zcl_command_arguments}}
{
{{#zcl_command_arguments}}
{{#if_chip_complex}}
AddArgument("{{asUpperCamelCase label}}", &mComplex_{{asUpperCamelCase label}});
{{else if (isString type)}}
AddArgument("{{asUpperCamelCase label}}", &mRequest.{{asLowerCamelCase label}});
{{else}}
AddArgument("{{asUpperCamelCase label}}", {{as_type_min_value type language='c++'}}, {{as_type_max_value type language='c++'}}, &mRequest.{{asLowerCamelCase label}});
{{/if_chip_complex}}
{{/zcl_command_arguments}}
ClusterCommand::AddArguments();
}
CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
{
constexpr chip::ClusterId clusterId = chip::app::Clusters::{{asUpperCamelCase parent.name}}::Id;
constexpr chip::CommandId commandId = chip::app::Clusters::{{asUpperCamelCase parent.name}}::Commands::{{asUpperCamelCase name}}::Id;
ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on endpoint %u", clusterId, commandId, endpointId);
dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
__auto_type * cluster = [[MTRBaseCluster{{asUpperCamelCase parent.name preserveAcronyms=true}} alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
__auto_type * params = [[MTR{{asUpperCamelCase parent.name preserveAcronyms=true}}Cluster{{asUpperCamelCase name preserveAcronyms=true}}Params alloc] init];
params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
{{#zcl_command_arguments}}
{{>decodable_value target=(concat "params." (asStructPropertyName label)) source=(concat "mRequest." (asLowerCamelCase label)) cluster=parent.parent.name type=type depth=0}}
{{/zcl_command_arguments}}
uint16_t repeatCount = mRepeatCount.ValueOr(1);
uint16_t __block responsesNeeded = repeatCount;
while (repeatCount--)
{
[cluster {{asLowerCamelCase name}}WithParams:params completion:
{{#if hasSpecificResponse}}
^(MTR{{asUpperCamelCase parent.name preserveAcronyms=true}}Cluster{{asUpperCamelCase responseName}}Params * _Nullable values, NSError * _Nullable error) {
NSLog(@"Values: %@", values);
if (error == nil) {
constexpr chip::CommandId responseId = chip::app::Clusters::{{asUpperCamelCase parent.name}}::Commands::{{asUpperCamelCase responseName}}::Id;
RemoteDataModelLogger::LogCommandAsJSON(@(endpointId), @(clusterId), @(responseId), values);
}
{{else}}
^(NSError * _Nullable error) {
{{/if}}
responsesNeeded--;
if (error != nil) {
mError = error;
LogNSError("Error", error);
{{#if hasSpecificResponse}}
constexpr chip::CommandId responseId = chip::app::Clusters::{{asUpperCamelCase parent.name}}::Commands::{{asUpperCamelCase responseName}}::Id;
RemoteDataModelLogger::LogCommandErrorAsJSON(@(endpointId), @(clusterId), @(responseId), error);
{{else}}
RemoteDataModelLogger::LogCommandErrorAsJSON(@(endpointId), @(clusterId), @(commandId), error);
{{/if}}
}
if (responsesNeeded == 0) {
SetCommandExitStatus(mError);
}
}];
}
return CHIP_NO_ERROR;
}
private:
{{#if hasArguments}}
chip::app::Clusters::{{asUpperCamelCase parent.name}}::Commands::{{asUpperCamelCase name}}::Type mRequest;
{{/if}}
{{#zcl_command_arguments}}
{{#if_chip_complex}}
TypedComplexArgument<{{zapTypeToEncodableClusterObjectType type ns=parent.parent.name}}> mComplex_{{asUpperCamelCase label}};
{{/if_chip_complex}}
{{/zcl_command_arguments}}
};
{{#if (isProvisional (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true))}}
#endif // MTR_ENABLE_PROVISIONAL
{{/if}}
{{/if}}
{{/if}}
{{/zcl_commands}}
{{#zcl_attributes_server removeKeys='isOptional'}}
{{#if (isSupported (asUpperCamelCase parent.name preserveAcronyms=true) attribute=(asUpperCamelCase name preserveAcronyms=true))}}
{{#if (isProvisional (asUpperCamelCase parent.name preserveAcronyms=true) attribute=(asUpperCamelCase name preserveAcronyms=true))}}
#if MTR_ENABLE_PROVISIONAL
{{/if}}
{{#*inline "cluster"}}Cluster{{asUpperCamelCase parent.name preserveAcronyms=true}}{{/inline}}
{{#*inline "attribute"}}Attribute{{asUpperCamelCase name preserveAcronyms=true}}{{/inline}}
/*
* Attribute {{asUpperCamelCase name}}
*/
class Read{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}: public ReadAttribute
{
public:
Read{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}(): ReadAttribute("{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}")
{
}
~Read{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}()
{
}
CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
{
constexpr chip::ClusterId clusterId = chip::app::Clusters::{{asUpperCamelCase parent.name}}::Id;
constexpr chip::AttributeId attributeId = chip::app::Clusters::{{asUpperCamelCase parent.name}}::Attributes::{{asUpperCamelCase name}}::Id;
ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId);
dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
__auto_type * cluster = [[MTRBase{{>cluster}} alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
{{#if_is_fabric_scoped_struct type}}
__auto_type * params = [[MTRReadParams alloc] init];
if (mFabricFiltered.HasValue()) {
params.filterByFabric = mFabricFiltered.Value();
}
{{/if_is_fabric_scoped_struct}}
[cluster read{{>attribute}}With
{{~#if_is_fabric_scoped_struct type~}}
Params:params completion:
{{~else~}}
Completion:
{{~/if_is_fabric_scoped_struct~}}
^({{asObjectiveCClass type parent.name}} * _Nullable value, NSError * _Nullable error) {
NSLog(@"{{asUpperCamelCase parent.name preserveAcronyms=true}}.{{asUpperCamelCase name preserveAcronyms=true}} response %@", [value description]);
if (error == nil) {
RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value);
} else {
LogNSError("{{asUpperCamelCase parent.name preserveAcronyms=true}} {{asUpperCamelCase name preserveAcronyms=true}} read Error", error);
RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error);
}
SetCommandExitStatus(error);
}];
return CHIP_NO_ERROR;
}
};
{{#if isWritableAttribute}}
{{! No list support for writing yet. Need to figure out how to represent the
values. }}
class Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}: public WriteAttribute
{
public:
Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}(): WriteAttribute("{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}"){{#if_chip_complex}}, mComplex(&mValue){{/if_chip_complex}}
{
AddArgument("attr-name", "{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}");
{{#if_chip_complex}}
AddArgument("attr-value", &mComplex);
{{else if (isString type)}}
AddArgument("attr-value", &mValue);
{{else}}
AddArgument("attr-value", {{as_type_min_value type language='c++'}}, {{as_type_max_value type language='c++'}}, &mValue);
{{/if_chip_complex}}
WriteAttribute::AddArguments();
}
~Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}()
{
}
CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
{
constexpr chip::ClusterId clusterId = chip::app::Clusters::{{asUpperCamelCase parent.name}}::Id;
constexpr chip::AttributeId attributeId = chip::app::Clusters::{{asUpperCamelCase parent.name}}::Attributes::{{asUpperCamelCase name}}::Id;
ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") WriteAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId);
dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
__auto_type * cluster = [[MTRBase{{>cluster}} alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
__auto_type * params = [[MTRWriteParams alloc] init];
params.timedWriteTimeout = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
{{#if_chip_complex}}
{{asObjectiveCType type parent.name}} value;
{{>decodable_value target="value" source="mValue" cluster=parent.name errorCode="return err;" depth=0}}
{{else}}
{{#if isNullable}}
{{asObjectiveCType type parent.name}} value = nil;
if (!mValue.IsNull()) {
{{#if (isOctetString type)}}
value = [[NSData alloc] initWithBytes:mValue.Value().data() length:mValue.Value().size()];
{{else if (isString type)}}
value = [[NSString alloc] initWithBytes:mValue.Value().data() length:mValue.Value().size() encoding:NSUTF8StringEncoding];
{{else}}
value = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:mValue.Value()];
{{/if}}
}
{{else}}
{{#if (isOctetString type)}}
{{asObjectiveCType type parent.name}} value = [[NSData alloc] initWithBytes:mValue.data() length:mValue.size()];
{{else if (isString type)}}
{{asObjectiveCType type parent.name}} value = [[NSString alloc] initWithBytes:mValue.data() length:mValue.size() encoding:NSUTF8StringEncoding];
{{else}}
{{asObjectiveCType type parent.name}} value = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:mValue{{#if isNullable}}.Value(){{/if}}];
{{/if}}
{{/if}}
{{/if_chip_complex}}
[cluster write{{>attribute}}WithValue:value params:params completion:^(NSError * _Nullable error) {
if (error != nil) {
LogNSError("{{asUpperCamelCase parent.name preserveAcronyms=true}} {{asUpperCamelCase name preserveAcronyms=true}} write Error", error);
RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error);
}
SetCommandExitStatus(error);
}];
return CHIP_NO_ERROR;
}
private:
{{#if_chip_complex}}
{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}} mValue;
TypedComplexArgument<{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}}> mComplex;
{{else if (isOctetString type)}}
{{#if isNullable}}chip::app::DataModel::Nullable<chip::ByteSpan>{{else}}chip::ByteSpan{{/if}} mValue;
{{else if (isCharString type)}}
{{#if isNullable}}chip::app::DataModel::Nullable<chip::ByteSpan>{{else}}chip::ByteSpan{{/if}} mValue;
{{else}}
{{#if isNullable}}chip::app::DataModel::Nullable<{{as_underlying_zcl_type type}}>{{else}}{{as_underlying_zcl_type type}}{{/if}} mValue;
{{/if_chip_complex}}
};
{{/if}}
{{#if isReportableAttribute}}
class SubscribeAttribute{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}: public SubscribeAttribute
{
public:
SubscribeAttribute{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}(): SubscribeAttribute("{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}")
{
}
~SubscribeAttribute{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}()
{
}
CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
{
constexpr chip::ClusterId clusterId = chip::app::Clusters::{{asUpperCamelCase parent.name}}::Id;
constexpr chip::CommandId attributeId = chip::app::Clusters::{{asUpperCamelCase parent.name}}::Attributes::{{asUpperCamelCase name}}::Id;
ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId);
dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
__auto_type * cluster = [[MTRBase{{>cluster}} alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
__auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
if (mKeepSubscriptions.HasValue()) {
params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
}
if (mFabricFiltered.HasValue()) {
params.filterByFabric = mFabricFiltered.Value();
}
if (mAutoResubscribe.HasValue()) {
params.resubscribeAutomatically = mAutoResubscribe.Value();
}
[cluster subscribe{{>attribute}}WithParams:params
subscriptionEstablished:^(){ mSubscriptionEstablished=YES; }
reportHandler:^({{asObjectiveCClass type parent.name}} * _Nullable value, NSError * _Nullable error) {
NSLog(@"{{asUpperCamelCase parent.name preserveAcronyms=true}}.{{asUpperCamelCase name preserveAcronyms=true}} response %@", [value description]);
if (error == nil) {
RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value);
} else {
RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error);
}
SetCommandExitStatus(error);
}];
return CHIP_NO_ERROR;
}
};
{{/if}}
{{#if (isProvisional (asUpperCamelCase parent.name preserveAcronyms=true) attribute=(asUpperCamelCase name preserveAcronyms=true))}}
#endif // MTR_ENABLE_PROVISIONAL
{{/if}}
{{/if}}
{{/zcl_attributes_server}}
{{/if}}
{{#if (isProvisional (asUpperCamelCase name preserveAcronyms=true))}}
#endif // MTR_ENABLE_PROVISIONAL
{{/if}}
{{/zcl_clusters}}
/*----------------------------------------------------------------------------*\
| Register all Clusters commands |
\*----------------------------------------------------------------------------*/
{{#zcl_clusters}}
{{#if (isSupported (asUpperCamelCase name preserveAcronyms=true))}}
void registerCluster{{asUpperCamelCase name}}(Commands & commands)
{
{{#if (isProvisional (asUpperCamelCase name preserveAcronyms=true))}}
#if MTR_ENABLE_PROVISIONAL
{{/if}}
using namespace chip::app::Clusters::{{asUpperCamelCase name}};
const char * clusterName = "{{asUpperCamelCase name}}";
commands_list clusterCommands = {
make_unique<ClusterCommand>(Id), //
{{#zcl_commands}}
{{#if (is_str_equal source 'client')}}
{{#if (isSupported (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true))}}
{{#if (isProvisional (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true))}}
#if MTR_ENABLE_PROVISIONAL
{{/if}}
make_unique<{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}>(), //
{{#if (isProvisional (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true))}}
#endif // MTR_ENABLE_PROVISIONAL
{{/if}}
{{/if}}
{{/if}}
{{/zcl_commands}}
{{#zcl_attributes_server removeKeys='isOptional'}}
{{#first}}
make_unique<ReadAttribute>(Id), //
make_unique<WriteAttribute>(Id), //
make_unique<SubscribeAttribute>(Id), //
{{/first}}
{{#if (isSupported (asUpperCamelCase parent.name preserveAcronyms=true) attribute=(asUpperCamelCase name preserveAcronyms=true))}}
{{#if (isProvisional (asUpperCamelCase parent.name preserveAcronyms=true) attribute=(asUpperCamelCase name preserveAcronyms=true))}}
#if MTR_ENABLE_PROVISIONAL
{{/if}}
make_unique<Read{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}>(), //
{{#if isWritableAttribute}}
make_unique<Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}>(), //
{{/if}}
{{#if isReportableAttribute}}
make_unique<SubscribeAttribute{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}>(), //
{{/if}}
{{#if (isProvisional (asUpperCamelCase parent.name preserveAcronyms=true) attribute=(asUpperCamelCase name preserveAcronyms=true))}}
#endif // MTR_ENABLE_PROVISIONAL
{{/if}}
{{/if}}
{{/zcl_attributes_server}}
{{#zcl_events}}
{{#first}}
make_unique<ReadEvent>(Id), //
make_unique<SubscribeEvent>(Id), //
{{/first}}
{{/zcl_events}}
};
commands.RegisterCluster(clusterName, clusterCommands);
{{#if (isProvisional (asUpperCamelCase name preserveAcronyms=true))}}
#endif // MTR_ENABLE_PROVISIONAL
{{/if}}
}
{{/if}}
{{/zcl_clusters}}
void registerClusterAny(Commands & commands)
{
const char * clusterName = "Any";
commands_list clusterCommands = {
make_unique<ClusterCommand>(), //
make_unique<ReadAttribute>(), //
make_unique<WriteAttribute>(), //
make_unique<SubscribeAttribute>(), //
make_unique<ReadEvent>(), //
make_unique<SubscribeEvent>(chip::kInvalidClusterId, true), //
make_unique<SubscribeEvent>(), //
};
commands.RegisterCommandSet(clusterName, clusterCommands, "Commands for sending IM messages based on cluster id, not cluster name.");
}
void registerClusters(Commands & commands)
{
registerClusterAny(commands);
{{#zcl_clusters}}
{{#if (isSupported (asUpperCamelCase name preserveAcronyms=true))}}
registerCluster{{asUpperCamelCase name}}(commands);
{{/if}}
{{/zcl_clusters}}
}