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

Add and Enable IM subscription support #9510

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
21 changes: 11 additions & 10 deletions examples/bridge-app/esp32/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,25 +314,25 @@ void HandleDeviceStatusChanged(Device * dev, Device::Changed_t itemChangedMask)
if (itemChangedMask & Device::kChanged_Reachable)
{
uint8_t reachable = dev->IsReachable() ? 1 : 0;
emberAfReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID,
ZCL_REACHABLE_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, 0, ZCL_BOOLEAN_ATTRIBUTE_TYPE,
&reachable);
InteractionModelReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID,
ZCL_REACHABLE_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, 0,
ZCL_BOOLEAN_ATTRIBUTE_TYPE, &reachable);
}

if (itemChangedMask & Device::kChanged_State)
{
uint8_t isOn = dev->IsOn() ? 1 : 0;
emberAfReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID,
CLUSTER_MASK_SERVER, 0, ZCL_BOOLEAN_ATTRIBUTE_TYPE, &isOn);
InteractionModelReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID,
CLUSTER_MASK_SERVER, 0, ZCL_BOOLEAN_ATTRIBUTE_TYPE, &isOn);
}

if (itemChangedMask & Device::kChanged_Name)
{
uint8_t zclName[kUserLabelSize];
ToZclCharString(zclName, dev->GetName(), kUserLabelSize - 1);
emberAfReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID,
ZCL_USER_LABEL_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, 0, ZCL_CHAR_STRING_ATTRIBUTE_TYPE,
zclName);
InteractionModelReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID,
ZCL_USER_LABEL_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, 0,
ZCL_CHAR_STRING_ATTRIBUTE_TYPE, zclName);
}
if (itemChangedMask & Device::kChanged_Location)
{
Expand All @@ -343,8 +343,9 @@ void HandleDeviceStatusChanged(Device * dev, Device::Changed_t itemChangedMask)

EncodeFixedLabel("room", dev->GetLocation(), buffer, sizeof(buffer), &am);

emberAfReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_FIXED_LABEL_CLUSTER_ID, ZCL_LABEL_LIST_ATTRIBUTE_ID,
CLUSTER_MASK_SERVER, 0, ZCL_ARRAY_ATTRIBUTE_TYPE, buffer);
InteractionModelReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_FIXED_LABEL_CLUSTER_ID,
ZCL_LABEL_LIST_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, 0,
ZCL_ARRAY_ATTRIBUTE_TYPE, buffer);
}
}

Expand Down
21 changes: 11 additions & 10 deletions examples/bridge-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,26 +207,26 @@ void HandleDeviceStatusChanged(Device * dev, Device::Changed_t itemChangedMask)
if (itemChangedMask & Device::kChanged_Reachable)
{
uint8_t reachable = dev->IsReachable() ? 1 : 0;
emberAfReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID,
ZCL_REACHABLE_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, 0, ZCL_BOOLEAN_ATTRIBUTE_TYPE,
&reachable);
InteractionModelReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID,
ZCL_REACHABLE_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, 0,
ZCL_BOOLEAN_ATTRIBUTE_TYPE, &reachable);
}

if (itemChangedMask & Device::kChanged_State)
{
uint8_t isOn = dev->IsOn() ? 1 : 0;
emberAfReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID,
CLUSTER_MASK_SERVER, 0, ZCL_BOOLEAN_ATTRIBUTE_TYPE, &isOn);
InteractionModelReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID,
CLUSTER_MASK_SERVER, 0, ZCL_BOOLEAN_ATTRIBUTE_TYPE, &isOn);
}

if (itemChangedMask & Device::kChanged_Name)
{
uint8_t zclName[kUserLabelSize];
MutableByteSpan zclNameSpan(zclName);
MakeZclCharString(zclNameSpan, dev->GetName());
emberAfReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID,
ZCL_USER_LABEL_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, 0, ZCL_CHAR_STRING_ATTRIBUTE_TYPE,
zclNameSpan.data());
InteractionModelReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID,
ZCL_USER_LABEL_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, 0,
ZCL_CHAR_STRING_ATTRIBUTE_TYPE, zclNameSpan.data());
}

if (itemChangedMask & Device::kChanged_Location)
Expand All @@ -238,8 +238,9 @@ void HandleDeviceStatusChanged(Device * dev, Device::Changed_t itemChangedMask)

EncodeFixedLabel("room", dev->GetLocation(), buffer, sizeof(buffer), &am);

emberAfReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_FIXED_LABEL_CLUSTER_ID, ZCL_LABEL_LIST_ATTRIBUTE_ID,
CLUSTER_MASK_SERVER, 0, ZCL_ARRAY_ATTRIBUTE_TYPE, buffer);
InteractionModelReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_FIXED_LABEL_CLUSTER_ID,
ZCL_LABEL_LIST_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, 0,
ZCL_ARRAY_ATTRIBUTE_TYPE, buffer);
}
}

Expand Down
78 changes: 78 additions & 0 deletions examples/chip-tool/templates/partials/process_response_value.zapt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{{#chip_tests_item_response_parameters}}
{{#if hasExpectedValue}}
{{#if isList}}
if (count != {{expectedValue.length}})
{
ChipLogError(chipTool, "Error: Value mismatch. Expected: '%s'", "{{expectedValue}}");
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{else}}
{{#if (isString type)}}
{{chipType}} {{asLowerCamelCase name}}Argument = chip::ByteSpan(chip::Uint8::from_const_char("{{expectedValue}}"), strlen("{{expectedValue}}"));
if (!{{asLowerCamelCase name}}.data_equal({{asLowerCamelCase name}}Argument))
{{else}}
if ({{asLowerCamelCase name}} != {{expectedValue}}{{asTypeLiteralSuffix chipType}})
{{/if}}
{
ChipLogError(chipTool, "Error: Value mismatch. Expected: '%s'", "{{expectedValue}}");
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{/if}}
{{/if}}
{{#if hasExpectedConstraints}}
{{#if expectedConstraints.type}}
ChipLogError(chipTool, "Warning: {{asLowerCamelCase name}} type checking is not implemented yet. Expected type: '%s'", "{{expectedConstraints.type}}");
{{/if}}

{{#if expectedConstraints.format}}
ChipLogError(chipTool, "Warning: {{asLowerCamelCase name}} format checking is not implemented yet. Expected format: '%s'", "{{expectedConstraints.format}}");
{{/if}}

{{#if expectedConstraints.minLength}}
if ({{asLowerCamelCase name}}.size() < {{expectedConstraints.minLength}})
{
ChipLogError(chipTool, "Error: {{asLowerCamelCase name}} is too short. Min size is {{expectedConstraints.minLength}} but got '%zu'", {{asLowerCamelCase name}}.size());
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{/if}}

{{#if expectedConstraints.maxLength}}
if ({{asLowerCamelCase name}}.size() > {{expectedConstraints.maxLength}})
{
ChipLogError(chipTool, "Error: {{asLowerCamelCase name}} is too long. Max size is {{expectedConstraints.maxLength}} but got '%zu'", {{asLowerCamelCase name}}.size());
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{/if}}

{{#if expectedConstraints.minValue}}
if ({{asLowerCamelCase name}} < {{expectedConstraints.minValue}})
{
ChipLogError(chipTool, "Error: {{asLowerCamelCase name}} is lower than expected. Min value is {{expectedConstraints.minValue}} but got '%d'", {{asLowerCamelCase name}});
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{/if}}

{{#if expectedConstraints.maxValue}}
if ({{asLowerCamelCase name}} > {{expectedConstraints.maxValue}})
{
ChipLogError(chipTool, "Error: {{asLowerCamelCase name}} is higher than expected. Max value is {{expectedConstraints.maxValue}} but got '%d'", {{asLowerCamelCase name}});
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{/if}}

{{#if expectedConstraints.notValue}}
if ({{asLowerCamelCase name}} == {{expectedConstraints.notValue}})
{
ChipLogError(chipTool, "Error: {{asLowerCamelCase name}} was not expected to be '{{expectedConstraints.notValue}}' due to notValue constraint");
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{/if}}
{{/if}}
{{/chip_tests_item_response_parameters}}
114 changes: 30 additions & 84 deletions examples/chip-tool/templates/partials/test_cluster.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,22 @@ class {{filename}}: public TestCommand

{{#chip_tests_items}}
{{#if (isTestOnlyCluster cluster)}}
CHIP_ERROR TestSendCluster{{asUpperCamelCase cluster}}Command{{asUpperCamelCase command}}_{{index}}()
{
ChipLogProgress(chipTool, "{{cluster}} - {{label}}");

return {{command}}({{#chip_tests_item_parameters}}{{#not_first}}, {{/not_first}}{{definedValue}}{{/chip_tests_item_parameters}});
}
{{> (asTestSuiteSimulatedClusterCommandPartial command) }}
{{else}}
// Test {{label}}
using SuccessCallback_{{index}} = void (*)(void * context{{#chip_tests_item_response_parameters}}, {{#if isList}}uint16_t count, {{/if}}{{chipType}} {{#if isList}}* {{/if}}{{asLowerCamelCase name}}{{/chip_tests_item_response_parameters}});
chip::Callback::Callback<SuccessCallback_{{index}}> mOnSuccessCallback_{{index}} { OnTestSendCluster{{asUpperCamelCase cluster}}Command{{asUpperCamelCase command}}_{{index}}_SuccessResponse, this };
chip::Callback::Callback<DefaultFailureCallback> mOnFailureCallback_{{index}} { OnTestSendCluster{{asUpperCamelCase cluster}}Command{{asUpperCamelCase command}}_{{index}}_FailureResponse, this };
{{#if isSubscribeAttribute}}
chip::Callback::Callback<DefaultSuccessCallback> mOnSubscriptionEstablishedCallback_{{index}} { SubscribeAttribute_{{ index }}_OnSubscriptionEstablishedCallback, this };
{{/if}}

bool mIsFailureExpected_{{index}} = {{response.error}};

{{#if isSubscribeAttribute}}
bool mReceivedReport_{{index}} = false;
{{/if}}

CHIP_ERROR TestSendCluster{{asUpperCamelCase cluster}}Command{{asUpperCamelCase command}}_{{index}}()
{
ChipLogProgress(chipTool, "{{cluster}} - {{label}}: Sending command...");
Expand All @@ -77,6 +80,9 @@ class {{filename}}: public TestCommand
{{/if}}
{{/chip_tests_item_parameters}}
err = cluster.{{asUpperCamelCase command}}(mOnSuccessCallback_{{index}}.Cancel(), mOnFailureCallback_{{index}}.Cancel(){{#chip_tests_item_parameters}}, {{asLowerCamelCase name}}Argument{{/chip_tests_item_parameters}});
{{else if isSubscribeAttribute}}
cluster.ReportAttribute{{asUpperCamelCase attribute}}(mOnSuccessCallback_{{index}}.Cancel());
err = cluster.ConfigureAttribute{{asUpperCamelCase attribute}}(mOnSubscriptionEstablishedCallback_{{index}}.Cancel(), mOnFailureCallback_{{index}}.Cancel(), {{minInterval}}, {{maxInterval}});
{{else if isReadAttribute}}
err = cluster.ReadAttribute{{asUpperCamelCase attribute}}(mOnSuccessCallback_{{index}}.Cancel(), mOnFailureCallback_{{index}}.Cancel());
{{else if isWriteAttribute}}
Expand All @@ -95,6 +101,19 @@ class {{filename}}: public TestCommand
return err;
}

{{#if isSubscribeAttribute }}
static void SubscribeAttribute_{{ index }}_OnSubscriptionEstablishedCallback(void * context)
{
{{parent.filename}} * runner = reinterpret_cast<{{parent.filename}} *>(context);
if (!runner->mReceivedReport_{{index}}) {
ChipLogError(chipTool, "Error: Initial report not received!");
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
runner->NextTest();
}
{{/if}}

static void OnTestSendCluster{{asUpperCamelCase cluster}}Command{{asUpperCamelCase command}}_{{index}}_FailureResponse(void * context, uint8_t status)
{
ChipLogProgress(chipTool, "{{cluster}} - {{label}}: Failure Response");
Expand Down Expand Up @@ -130,86 +149,13 @@ class {{filename}}: public TestCommand
return;
}

{{#chip_tests_item_response_parameters}}
{{#if hasExpectedValue}}
{{#if isList}}
if (count != {{expectedValue.length}})
{
ChipLogError(chipTool, "Error: Value mismatch. Expected: '%s'", "{{expectedValue}}");
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{else}}
{{#if (isString type)}}
{{chipType}} {{asLowerCamelCase name}}Argument = chip::ByteSpan(chip::Uint8::from_const_char("{{expectedValue}}"), strlen("{{expectedValue}}"));
if (!{{asLowerCamelCase name}}.data_equal({{asLowerCamelCase name}}Argument))
{{else}}
if ({{asLowerCamelCase name}} != {{expectedValue}}{{asTypeLiteralSuffix chipType}})
{{/if}}
{
ChipLogError(chipTool, "Error: Value mismatch. Expected: '%s'", "{{expectedValue}}");
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{/if}}
{{/if}}
{{#if hasExpectedConstraints}}
{{#if expectedConstraints.type}}
ChipLogError(chipTool, "Warning: {{asLowerCamelCase name}} type checking is not implemented yet. Expected type: '%s'", "{{expectedConstraints.type}}");
{{/if}}

{{#if expectedConstraints.format}}
ChipLogError(chipTool, "Warning: {{asLowerCamelCase name}} format checking is not implemented yet. Expected format: '%s'", "{{expectedConstraints.format}}");
{{/if}}

{{#if expectedConstraints.minLength}}
if ({{asLowerCamelCase name}}.size() < {{expectedConstraints.minLength}})
{
ChipLogError(chipTool, "Error: {{asLowerCamelCase name}} is too short. Min size is {{expectedConstraints.minLength}} but got '%zu'", {{asLowerCamelCase name}}.size());
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{/if}}

{{#if expectedConstraints.maxLength}}
if ({{asLowerCamelCase name}}.size() > {{expectedConstraints.maxLength}})
{
ChipLogError(chipTool, "Error: {{asLowerCamelCase name}} is too long. Max size is {{expectedConstraints.maxLength}} but got '%zu'", {{asLowerCamelCase name}}.size());
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{/if}}

{{#if expectedConstraints.minValue}}
if ({{asLowerCamelCase name}} < {{expectedConstraints.minValue}})
{
ChipLogError(chipTool, "Error: {{asLowerCamelCase name}} is lower than expected. Min value is {{expectedConstraints.minValue}} but got '%d'", {{asLowerCamelCase name}});
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{/if}}
{{> process_response_value}}

{{#if expectedConstraints.maxValue}}
if ({{asLowerCamelCase name}} > {{expectedConstraints.maxValue}})
{
ChipLogError(chipTool, "Error: {{asLowerCamelCase name}} is higher than expected. Max value is {{expectedConstraints.maxValue}} but got '%d'", {{asLowerCamelCase name}});
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{/if}}

{{#if expectedConstraints.notValue}}
if ({{asLowerCamelCase name}} == {{expectedConstraints.notValue}})
{
ChipLogError(chipTool, "Error: {{asLowerCamelCase name}} was not expected to be '{{expectedConstraints.notValue}}' due to notValue constraint");
runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL);
return;
}
{{/if}}
{{#if isSubscribeAttribute}}
runner->mReceivedReport_{{index}} = true;
{{else}}
runner->NextTest();
{{/if}}
{{/chip_tests_item_response_parameters}}

runner->NextTest();
}

{{/if}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// The callback should be called atleast once
{{#chip_tests_WaitForAttributeReport_attribute_info}}
using OnReportCallback_{{parent.index}} = void (*)(void * context{{#chip_tests_item_response_parameters}}, {{#if isList}}uint16_t count, {{/if}}{{chipType}} {{#if isList}}* {{/if}}{{asLowerCamelCase name}}{{/chip_tests_item_response_parameters}});
chip::Callback::Callback<OnReportCallback_{{ parent.index }}> mOnReportCallback_{{parent.index}} { SubscribeAttribute_{{ parent.index }}_OnReportCallback, this };
{{/chip_tests_WaitForAttributeReport_attribute_info}}

bool mReceivedReport_{{index}} = false;

CHIP_ERROR TestSendCluster{{asUpperCamelCase cluster}}Command{{asUpperCamelCase command}}_{{index}}()
{
ChipLogProgress(chipTool, "{{cluster}} - {{asUpperCamelCase command}} - {{label}}");
{{#chip_tests_WaitForAttributeReport_attribute_info}}
chip::Controller::{{asUpperCamelCase cluster}}Cluster cluster;
cluster.Associate(mDevice, {{endpoint}});
return cluster.ReportAttribute{{asUpperCamelCase attribute}}(mOnReportCallback_{{parent.index}}.Cancel());
{{/chip_tests_WaitForAttributeReport_attribute_info}}
}

{{#chip_tests_WaitForAttributeReport_attribute_info}}
static void SubscribeAttribute_{{ parent.index }}_OnReportCallback(void * context{{#chip_tests_item_response_parameters}}, {{#if isList}}uint16_t count, {{/if}}{{chipType}} {{#if isList}}* {{/if}}{{asLowerCamelCase name}}{{/chip_tests_item_response_parameters}})
{
ChipLogProgress(chipTool, "On/Off - Subscribe {{asUpperCamelCase attribute}} Attribute: Report Data");
{{parent.parent.filename}} * runner = reinterpret_cast<{{parent.parent.filename}} *>(context);

if (runner->mReceivedReport_{{parent.index}})
{
// Receiving attribute more than once is not an issue, since the following handler will override previous handlers.
return;
}

{{> process_response_value}}

runner->mReceivedReport_{{parent.index}} = true;
ChipLogProgress(chipTool, "On/Off - report received.");
runner->NextTest();
}

{{/chip_tests_WaitForAttributeReport_attribute_info}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CHIP_ERROR TestSendCluster{{asUpperCamelCase cluster}}Command{{asUpperCamelCase command}}_{{index}}()
{
ChipLogProgress(chipTool, "{{cluster}} - {{asUpperCamelCase command}} - {{label}}");

return {{command}}({{#chip_tests_item_parameters}}{{#not_first}}, {{/not_first}}{{definedValue}}{{/chip_tests_item_parameters}});
}
2 changes: 1 addition & 1 deletion examples/chip-tool/templates/reporting-commands.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public:
{{#chip_client_clusters}}
{{#chip_server_cluster_attributes}}
{{#if isReportableAttribute}}
callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, {{asHex parent.code 4}}, {{asHex code 4}}, onReport{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}Callback->Cancel());
callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, {{asHex parent.code 4}}, {{asHex code 4}}, onReport{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}Callback->Cancel(), BasicAttributeFilter<{{chipCallback.name}}AttributeCallback>);
yunhanw-google marked this conversation as resolved.
Show resolved Hide resolved
{{/if}}
{{/chip_server_cluster_attributes}}
{{/chip_client_clusters}}
Expand Down
Loading