| {{> 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> |
| |
| {{> clusters_header}} |
| |
| {{#chip_client_clusters includeAll=true}} |
| {{> cluster_header}} |
| |
| {{#chip_cluster_commands}} |
| /* |
| * Command {{asUpperCamelCase name}} |
| */ |
| class {{asUpperCamelCase clusterName}}{{asUpperCamelCase name}}: public ClusterCommand |
| { |
| public: |
| {{asUpperCamelCase clusterName}}{{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}} |
| { |
| {{#chip_cluster_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}} |
| {{/chip_cluster_command_arguments}} |
| ClusterCommand::AddArguments(); |
| } |
| |
| CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override |
| { |
| ChipLogProgress(chipTool, "Sending cluster ({{asHex parent.code 8}}) command ({{asHex code 8}}) on endpoint %u", endpointId); |
| |
| dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); |
| MTRBaseCluster{{asUpperCamelCase clusterName}} * cluster = [[MTRBaseCluster{{asUpperCamelCase clusterName}} alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; |
| __auto_type * params = [[MTR{{asUpperCamelCase clusterName}}Cluster{{asUpperCamelCase name}}Params alloc] init]; |
| params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; |
| {{#chip_cluster_command_arguments}} |
| {{>decodable_value target=(concat "params." (asStructPropertyName label)) source=(concat "mRequest." (asLowerCamelCase label)) cluster=parent.clusterName type=type depth=0}} |
| {{/chip_cluster_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 clusterName}}Cluster{{asUpperCamelCase responseName}}Params * _Nullable values, NSError * _Nullable error) { |
| NSLog(@"Values: %@", values); |
| {{else}} |
| ^(NSError * _Nullable error) { |
| {{/if}} |
| responsesNeeded--; |
| if (error != nil) { |
| mError = error; |
| LogNSError("Error", error); |
| } |
| if (responsesNeeded == 0) { |
| SetCommandExitStatus(mError); |
| } |
| }]; |
| } |
| return CHIP_NO_ERROR; |
| } |
| |
| private: |
| {{#if (hasArguments)}} |
| chip::app::Clusters::{{asUpperCamelCase clusterName}}::Commands::{{asUpperCamelCase name}}::Type mRequest; |
| {{/if}} |
| {{#chip_cluster_command_arguments}} |
| {{#if_chip_complex}} |
| TypedComplexArgument<{{zapTypeToEncodableClusterObjectType type ns=parent.parent.name}}> mComplex_{{asUpperCamelCase label}}; |
| {{/if_chip_complex}} |
| {{/chip_cluster_command_arguments}} |
| }; |
| |
| {{/chip_cluster_commands}} |
| |
| {{#chip_server_cluster_attributes}} |
| {{#*inline "attribute"}}Attribute{{asUpperCamelCase name}}{{/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 |
| { |
| ChipLogProgress(chipTool, "Sending cluster ({{asHex parent.code 8}}) ReadAttribute ({{asHex code 8}}) on endpoint %u", endpointId); |
| |
| dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); |
| MTRBaseCluster{{asUpperCamelCase parent.name}} * cluster = [[MTRBaseCluster{{asUpperCamelCase parent.name}} alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; |
| {{#if_is_fabric_scoped_struct type}} |
| MTRReadParams * params = [[MTRReadParams alloc] init]; |
| if (mFabricFiltered.HasValue()) { |
| params.filterByFabric = mFabricFiltered.Value(); |
| } |
| {{/if_is_fabric_scoped_struct}} |
| [cluster readAttribute{{asUpperCamelCase name}}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}}.{{asUpperCamelCase name}} response %@", [value description]); |
| if (error != nil) { |
| LogNSError("{{asUpperCamelCase parent.name}} {{asUpperCamelCase name}} read Error", 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 |
| { |
| ChipLogProgress(chipTool, "Sending cluster ({{asHex parent.code 8}}) WriteAttribute ({{asHex code 8}}) on endpoint %u", endpointId); |
| dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); |
| MTRBaseCluster{{asUpperCamelCase parent.name}} * cluster = [[MTRBaseCluster{{asUpperCamelCase parent.name}} alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; |
| MTRWriteParams * 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 (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_chip_complex}} |
| |
| [cluster writeAttribute{{asUpperCamelCase name}}WithValue:value params:params completion:^(NSError * _Nullable error) { |
| if (error != nil) { |
| LogNSError("{{asUpperCamelCase parent.name}} {{asUpperCamelCase name}} write Error", 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)}} |
| chip::ByteSpan mValue; |
| {{else if (isCharString type)}} |
| chip::ByteSpan mValue; |
| {{else}} |
| {{chipType}} 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 |
| { |
| ChipLogProgress(chipTool, "Sending cluster ({{asHex parent.code 8}}) ReportAttribute ({{asHex code 8}}) on endpoint %u", endpointId); |
| dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); |
| MTRBaseCluster{{asUpperCamelCase parent.name}} * cluster = [[MTRBaseCluster{{asUpperCamelCase parent.name}} alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; |
| MTRSubscribeParams * 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.resubscribeIfLost = mAutoResubscribe.Value(); |
| } |
| [cluster subscribe{{>attribute}}WithParams:params |
| subscriptionEstablished:^(){ mSubscriptionEstablished=YES; } |
| reportHandler:^({{asObjectiveCClass type parent.name}} * _Nullable value, NSError * _Nullable error) { |
| NSLog(@"{{asUpperCamelCase parent.name}}.{{asUpperCamelCase name}} response %@", [value description]); |
| SetCommandExitStatus(error); |
| }]; |
| |
| return CHIP_NO_ERROR; |
| } |
| }; |
| |
| {{/if}} |
| {{/chip_server_cluster_attributes}} |
| {{/chip_client_clusters}} |
| |
| /*----------------------------------------------------------------------------*\ |
| | Register all Clusters commands | |
| \*----------------------------------------------------------------------------*/ |
| {{#chip_client_clusters includeAll=true}} |
| void registerCluster{{asUpperCamelCase name}}(Commands & commands) |
| { |
| using namespace chip::app::Clusters::{{asUpperCamelCase name}}; |
| |
| const char * clusterName = "{{asUpperCamelCase name}}"; |
| |
| commands_list clusterCommands = { |
| make_unique<ClusterCommand>(Id), // |
| {{#chip_cluster_commands}} |
| make_unique<{{asUpperCamelCase clusterName}}{{asUpperCamelCase name}}>(), // |
| {{/chip_cluster_commands}} |
| {{#chip_server_cluster_attributes}} |
| {{#first}} |
| make_unique<ReadAttribute>(Id), // |
| {{/first}} |
| make_unique<Read{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}>(), // |
| {{#first}} |
| make_unique<WriteAttribute>(Id), // |
| {{/first}} |
| {{#if isWritableAttribute}} |
| make_unique<Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}>(), // |
| {{/if}} |
| {{#first}} |
| make_unique<SubscribeAttribute>(Id), // |
| {{/first}} |
| {{#if isReportableAttribute}} |
| make_unique<SubscribeAttribute{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}>(), // |
| {{/if}} |
| {{/chip_server_cluster_attributes}} |
| }; |
| |
| commands.Register(clusterName, clusterCommands); |
| } |
| {{/chip_client_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<SubscribeEvent>(), // |
| }; |
| |
| commands.Register(clusterName, clusterCommands); |
| } |
| |
| void registerClusters(Commands & commands) |
| { |
| registerClusterAny(commands); |
| {{#chip_client_clusters includeAll=true}} |
| registerCluster{{asUpperCamelCase name}}(commands); |
| {{/chip_client_clusters}} |
| } |