| {{> 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}} |
| } |