| {{> header}} |
| |
| #include <app/CommandSender.h> |
| #include <app/InteractionModelEngine.h> |
| #include <app/data-model/DecodableList.h> |
| #include <app-common/zap-generated/cluster-objects.h> |
| #include <lib/core/CHIPCore.h> |
| #include <lib/support/Span.h> |
| |
| #include <app/DeviceProxy.h> |
| |
| #include <zap-generated/CHIPClientCallbacks.h> |
| #include <zap-generated/CHIPClusters.h> |
| |
| using namespace chip; |
| using namespace chip::app; |
| |
| namespace { |
| |
| // Define pointers for external ZCL response delegates. |
| |
| using SuccessResponseDelegate = void(*)(); |
| using FailureResponseDelegate = void(*)(uint8_t); |
| SuccessResponseDelegate gSuccessResponseDelegate; |
| FailureResponseDelegate gFailureResponseDelegate; |
| |
| // Define callbacks for ZCL commands and attribute requests. |
| |
| #if CHIP_PROGRESS_LOGGING |
| std::string ByteSpanToString(chip::ByteSpan value) |
| { |
| std::string strValue = ""; |
| for (size_t i = 0; i < value.size(); i++) |
| { |
| strValue += ' '; |
| strValue += std::to_string(value.data()[i]); |
| } |
| return strValue; |
| } |
| #endif |
| |
| void OnDefaultSuccessResponse(void * /* context */) |
| { |
| if (gSuccessResponseDelegate != nullptr) |
| gSuccessResponseDelegate(); |
| } |
| |
| void OnDefaultFailureResponse(void * /* context */, uint8_t status) |
| { |
| if (gFailureResponseDelegate != nullptr) |
| gFailureResponseDelegate(status); |
| } |
| |
| |
| template <class AttributeType> |
| void OnAttributeResponse(void * /* context */, AttributeType value) |
| { |
| std::string strValue = std::to_string(value); |
| ChipLogProgress(Zcl, " attributeValue: %s", strValue.c_str()); |
| if (gSuccessResponseDelegate != nullptr) |
| gSuccessResponseDelegate(); |
| } |
| |
| template <> |
| void OnAttributeResponse<chip::ByteSpan>(void * /* context */, chip::ByteSpan value) |
| { |
| ChipLogProgress(Zcl, " attributeValue: (span of length %zd) %s", value.size(), ByteSpanToString(value).c_str()); |
| if (gSuccessResponseDelegate != nullptr) |
| gSuccessResponseDelegate(); |
| } |
| |
| template <> |
| void OnAttributeResponse<chip::CharSpan>(void * /* context */, chip::CharSpan value) |
| { |
| ChipLogProgress(Zcl, " attributeValue: '%.*s'", static_cast<int>(value.size()), value.data()); |
| if (gSuccessResponseDelegate != nullptr) |
| gSuccessResponseDelegate(); |
| } |
| |
| template <> |
| void OnAttributeResponse<bool>(void * /* context */, bool value) |
| { |
| ChipLogProgress(Zcl, " attributeValue: %s", value ? "true" : "false"); |
| if (gSuccessResponseDelegate != nullptr) |
| gSuccessResponseDelegate(); |
| } |
| |
| {{#chip_client_clusters}} |
| {{#chip_server_cluster_attributes}} |
| {{#if isList}} |
| static void On{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}ListAttributeResponse(void * context, {{zapTypeToDecodableClusterObjectType type ns=parent.name isArgument=true}} list) |
| { |
| size_t count = 0; |
| CHIP_ERROR err = list.ComputeSize(&count); |
| if (err != CHIP_NO_ERROR) |
| { |
| if (gFailureResponseDelegate != nullptr) |
| { |
| gFailureResponseDelegate(EMBER_ZCL_STATUS_INVALID_VALUE); |
| } |
| return; |
| } |
| |
| ChipLogProgress(Zcl, " attributeValue:%s", count > 0 ? "" : " []"); |
| |
| if (count > 0) |
| ChipLogProgress(Zcl, " ["); |
| |
| auto iter = list.begin(); |
| while (iter.Next()) |
| { |
| #if CHIP_PROGRESS_LOGGING |
| auto & entry = iter.GetValue(); |
| {{#if isStruct}} |
| ChipLogProgress(Zcl, " {"); |
| {{#chip_attribute_list_entryTypes}} |
| {{~#*inline "field"}}entry.{{asLowerCamelCase name}}{{#if isOptional}}.Value(){{/if}}{{/inline~}} |
| {{~#*inline "fieldValue"}}{{>field}}{{#if isNullable}}.Value(){{/if}}{{/inline~}} |
| {{#if isOptional}} |
| if (entry.{{asLowerCamelCase name}}.HasValue()) { |
| {{/if}} |
| {{#if isNullable}} |
| if ({{>field}}.IsNull()) { |
| ChipLogProgress(chipTool, " {{asSymbol label}}: null"); |
| } else { |
| {{/if}} |
| {{#if isArray}} |
| {{! TODO: Add support for printing list member of struct element of list attribute }} |
| ChipLogProgress(chipTool, " {{asSymbol label}}: list member of struct element of list attribute printing not supported yet"); |
| {{else if (isOctetString type)}} |
| ChipLogProgress(Zcl, " {{asSymbol label}}: %s,", ByteSpanToString({{>fieldValue}}).c_str()); |
| {{else if (isCharString type)}} |
| ChipLogProgress(Zcl, " {{asSymbol label}}: %.*s,", static_cast<int>({{>fieldValue}}.size()), {{>fieldValue}}.data()); |
| {{else if isStruct}} |
| {{! TODO: Add support for printing struct member of struct element of list attribute }} |
| ChipLogProgress(chipTool, " {{asSymbol label}}: struct member of struct element of list attribute printing not supported yet"); |
| {{else}} |
| ChipLogProgress(Zcl, " {{asSymbol label}}: {{asPrintFormat type}},", {{>fieldValue}}); |
| {{/if}} |
| {{#if isNullable}} |
| } |
| {{/if}} |
| {{#if isOptional}} |
| } |
| {{/if}} |
| {{/chip_attribute_list_entryTypes}} |
| ChipLogProgress(Zcl, " },"); |
| {{else if (isOctetString type)}} |
| ChipLogProgress(Zcl, " %s,", ByteSpanToString(entry).c_str()); |
| {{else if (isCharString type)}} |
| ChipLogProgress(Zcl, " %.*s,", static_cast<int>(entry.size()), entry.data()); |
| {{else}} |
| {{~! NOTE: asPrintFormat does not handle the isArray case at |
| all right, but we want the print format for our _entries_ |
| anyway. Indirect through a partial that will let us set |
| isArray to false. ~}} |
| {{~#*inline "asPrintFormatForElement"}}{{asPrintFormat type}}{{/inline~}} |
| ChipLogProgress(Zcl, " {{>asPrintFormatForElement isArray=false}},", entry); |
| {{/if}} |
| #endif // CHIP_PROGRESS_LOGGING |
| } |
| if (iter.GetStatus() != CHIP_NO_ERROR) |
| { |
| if (gFailureResponseDelegate != nullptr) |
| { |
| gFailureResponseDelegate(EMBER_ZCL_STATUS_INVALID_VALUE); |
| } |
| return; |
| } |
| |
| if (count > 0) |
| ChipLogProgress(Zcl, " ]"); |
| |
| if (gSuccessResponseDelegate != nullptr) |
| gSuccessResponseDelegate(); |
| } |
| chip::Callback::Callback<{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}ListAttributeCallback> g{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}ListAttributeCallback{On{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}ListAttributeResponse, nullptr}; |
| {{/if}} |
| {{/chip_server_cluster_attributes}} |
| {{/chip_client_clusters}} |
| |
| chip::Callback::Callback<DefaultSuccessCallback> gDefaultSuccessCallback{OnDefaultSuccessResponse, nullptr}; |
| chip::Callback::Callback<DefaultFailureCallback> gDefaultFailureCallback{OnDefaultFailureResponse, nullptr}; |
| chip::Callback::Callback<BooleanAttributeCallback> gBooleanAttributeCallback{OnAttributeResponse<bool>, nullptr}; |
| chip::Callback::Callback<Int8uAttributeCallback> gInt8uAttributeCallback{OnAttributeResponse<uint8_t>, nullptr}; |
| chip::Callback::Callback<Int8sAttributeCallback> gInt8sAttributeCallback{OnAttributeResponse<int8_t>, nullptr}; |
| chip::Callback::Callback<Int16uAttributeCallback> gInt16uAttributeCallback{OnAttributeResponse<uint16_t>, nullptr}; |
| chip::Callback::Callback<Int16sAttributeCallback> gInt16sAttributeCallback{OnAttributeResponse<int16_t>, nullptr}; |
| chip::Callback::Callback<Int32uAttributeCallback> gInt32uAttributeCallback{OnAttributeResponse<uint32_t>, nullptr}; |
| chip::Callback::Callback<Int32sAttributeCallback> gInt32sAttributeCallback{OnAttributeResponse<int32_t>, nullptr}; |
| chip::Callback::Callback<Int64uAttributeCallback> gInt64uAttributeCallback{OnAttributeResponse<uint64_t>, nullptr}; |
| chip::Callback::Callback<Int64sAttributeCallback> gInt64sAttributeCallback{OnAttributeResponse<int64_t>, nullptr}; |
| chip::Callback::Callback<OctetStringAttributeCallback> gOctetStringAttributeCallback{OnAttributeResponse<ByteSpan>, nullptr}; |
| chip::Callback::Callback<CharStringAttributeCallback> gCharStringAttributeCallback{OnAttributeResponse<CharSpan>, nullptr}; |
| |
| } // namespace |
| |
| extern "C" { |
| |
| void chip_ime_SetSuccessResponseDelegate(SuccessResponseDelegate delegate) |
| { |
| gSuccessResponseDelegate = delegate; |
| } |
| |
| void chip_ime_SetFailureResponseDelegate(FailureResponseDelegate delegate) |
| { |
| gFailureResponseDelegate = delegate; |
| } |
| |
| {{#chip_client_clusters}} |
| // Cluster {{asUpperCamelCase name}} |
| |
| {{#chip_server_cluster_attributes}} |
| chip::ChipError::StorageType chip_ime_ReadAttribute_{{asUpperCamelCase parent.name}}_{{asUpperCamelCase name}}(chip::DeviceProxy * device, chip::EndpointId ZCLendpointId, chip::GroupId /* ZCLgroupId */) |
| { |
| VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT.AsInteger()); |
| chip::Controller::{{asUpperCamelCase parent.name}}Cluster cluster; |
| cluster.Associate(device, ZCLendpointId); |
| {{#if isList}} |
| return cluster.ReadAttribute{{asUpperCamelCase name}}(g{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}ListAttributeCallback.Cancel(), gDefaultFailureCallback.Cancel()).AsInteger(); |
| {{else}} |
| return cluster.ReadAttribute{{asUpperCamelCase name}}(g{{chipCallback.name}}AttributeCallback.Cancel(), gDefaultFailureCallback.Cancel()).AsInteger(); |
| {{/if}} |
| } |
| |
| {{#if isReportableAttribute}} |
| chip::ChipError::StorageType chip_ime_SubscribeAttribute_{{asUpperCamelCase parent.name}}_{{asUpperCamelCase name}}(chip::DeviceProxy * device, chip::EndpointId ZCLendpointId, uint16_t minInterval, uint16_t maxInterval) |
| { |
| VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT.AsInteger()); |
| chip::Controller::{{asUpperCamelCase parent.name}}Cluster cluster; |
| cluster.Associate(device, ZCLendpointId); |
| {{#if isList}} |
| chip::Callback::Callback<{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}ListAttributeCallback> * onSuccessCallback = new chip::Callback::Callback<{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}ListAttributeCallback>(On{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}ListAttributeResponse, nullptr); |
| return cluster.SubscribeAttribute{{asUpperCamelCase name}}(onSuccessCallback->Cancel(), gDefaultFailureCallback.Cancel(), minInterval, maxInterval).AsInteger(); |
| {{else}} |
| return cluster.SubscribeAttribute{{asUpperCamelCase name}}(g{{chipCallback.name}}AttributeCallback.Cancel(), gDefaultFailureCallback.Cancel(), minInterval, maxInterval).AsInteger(); |
| {{/if}} |
| } |
| {{/if}} |
| |
| {{/chip_server_cluster_attributes}} |
| |
| // End of Cluster {{asUpperCamelCase name}} |
| {{/chip_client_clusters}} |
| |
| } |