diff --git a/examples/bridge-app/esp32/main/main.cpp b/examples/bridge-app/esp32/main/main.cpp index ad2420ded777ca..5d0dbbbb62aa4f 100644 --- a/examples/bridge-app/esp32/main/main.cpp +++ b/examples/bridge-app/esp32/main/main.cpp @@ -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) { @@ -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); } } diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index 9d4f08c1b07eb0..17af693bba8493 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -207,16 +207,16 @@ 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) @@ -224,9 +224,9 @@ void HandleDeviceStatusChanged(Device * dev, Device::Changed_t itemChangedMask) 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) @@ -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); } } diff --git a/examples/chip-tool/templates/partials/process_response_value.zapt b/examples/chip-tool/templates/partials/process_response_value.zapt new file mode 100644 index 00000000000000..e82ff965abcc7d --- /dev/null +++ b/examples/chip-tool/templates/partials/process_response_value.zapt @@ -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}} diff --git a/examples/chip-tool/templates/partials/test_cluster.zapt b/examples/chip-tool/templates/partials/test_cluster.zapt index 0be51994967840..6d7a4e3c352843 100644 --- a/examples/chip-tool/templates/partials/test_cluster.zapt +++ b/examples/chip-tool/templates/partials/test_cluster.zapt @@ -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 mOnSuccessCallback_{{index}} { OnTestSendCluster{{asUpperCamelCase cluster}}Command{{asUpperCamelCase command}}_{{index}}_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_{{index}} { OnTestSendCluster{{asUpperCamelCase cluster}}Command{{asUpperCamelCase command}}_{{index}}_FailureResponse, this }; + {{#if isSubscribeAttribute}} + chip::Callback::Callback 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..."); @@ -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}} @@ -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"); @@ -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}} diff --git a/examples/chip-tool/templates/partials/testsuite/WaitForAttributeReport.zapt b/examples/chip-tool/templates/partials/testsuite/WaitForAttributeReport.zapt new file mode 100644 index 00000000000000..b45162af201604 --- /dev/null +++ b/examples/chip-tool/templates/partials/testsuite/WaitForAttributeReport.zapt @@ -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 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}} diff --git a/examples/chip-tool/templates/partials/testsuite/WaitForMs.zapt b/examples/chip-tool/templates/partials/testsuite/WaitForMs.zapt new file mode 100644 index 00000000000000..771ae4227fe91b --- /dev/null +++ b/examples/chip-tool/templates/partials/testsuite/WaitForMs.zapt @@ -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}}); +} diff --git a/examples/chip-tool/templates/reporting-commands.zapt b/examples/chip-tool/templates/reporting-commands.zapt index a7b50578be5aa1..c9c05e691fb22f 100644 --- a/examples/chip-tool/templates/reporting-commands.zapt +++ b/examples/chip-tool/templates/reporting-commands.zapt @@ -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>); {{/if}} {{/chip_server_cluster_attributes}} {{/chip_client_clusters}} diff --git a/examples/chip-tool/templates/templates.json b/examples/chip-tool/templates/templates.json index 55b4702a55cdbd..e378232b78a82f 100644 --- a/examples/chip-tool/templates/templates.json +++ b/examples/chip-tool/templates/templates.json @@ -23,9 +23,21 @@ "name": "cluster_header", "path": "../../../src/app/zap-templates/partials/cluster_header.zapt" }, + { + "name": "process_response_value", + "path": "partials/process_response_value.zapt" + }, { "name": "test_cluster", "path": "partials/test_cluster.zapt" + }, + { + "name": "TestSuiteHelper_WaitForMs", + "path": "partials/testsuite/WaitForMs.zapt" + }, + { + "name": "TestSuiteHelper_WaitForAttributeReport", + "path": "partials/testsuite/WaitForAttributeReport.zapt" } ], "templates": [ diff --git a/examples/chip-tool/templates/tests-commands.zapt b/examples/chip-tool/templates/tests-commands.zapt index 85b73098b087e4..f667107cb8a2c9 100644 --- a/examples/chip-tool/templates/tests-commands.zapt +++ b/examples/chip-tool/templates/tests-commands.zapt @@ -4,4 +4,5 @@ #include -{{>test_cluster tests="TV_TargetNavigatorCluster, TV_AudioOutputCluster, TV_ApplicationLauncherCluster, TV_KeypadInputCluster, TV_AccountLoginCluster, TV_WakeOnLanCluster, TV_ApplicationBasicCluster, TV_MediaPlaybackCluster, TV_TvChannelCluster, TV_LowPowerCluster, TV_MediaInputCluster, TestCluster, TestConstraints, TestDelayCommands, Test_TC_OO_1_1, Test_TC_OO_2_1, Test_TC_OO_2_2, Test_TC_DM_1_1, Test_TC_DM_3_1, Test_TC_CC_3_4, Test_TC_CC_5, Test_TC_CC_6, Test_TC_CC_7, Test_TC_CC_8, Test_TC_WNCV_1_1, Test_TC_WNCV_2_1, Test_TC_BI_1_1, Test_TC_FLW_1_1, Test_TC_TM_1_1, Test_TC_OCC_1_1, OperationalCredentialsCluster"}} +{{>test_cluster tests="TV_TargetNavigatorCluster, TV_AudioOutputCluster, TV_ApplicationLauncherCluster, TV_KeypadInputCluster, TV_AccountLoginCluster, TV_WakeOnLanCluster, TV_ApplicationBasicCluster, TV_MediaPlaybackCluster, TV_TvChannelCluster, TV_LowPowerCluster, TV_MediaInputCluster, TestCluster, TestConstraints, TestDelayCommands, TestSubscribe_OnOff, Test_TC_OO_1_1, Test_TC_OO_2_1, Test_TC_OO_2_2, Test_TC_DM_1_1, Test_TC_DM_3_1, Test_TC_CC_3_4, Test_TC_CC_5, Test_TC_CC_6, Test_TC_CC_7, Test_TC_CC_8, Test_TC_WNCV_1_1, Test_TC_WNCV_2_1, Test_TC_BI_1_1, Test_TC_FLW_1_1, Test_TC_TM_1_1, Test_TC_OCC_1_1, OperationalCredentialsCluster"}} + diff --git a/src/app/ClusterInfo.h b/src/app/ClusterInfo.h index 9d22ad8514b8bd..f9179ab373db72 100644 --- a/src/app/ClusterInfo.h +++ b/src/app/ClusterInfo.h @@ -92,15 +92,11 @@ struct ClusterInfo } ClusterInfo() {} - bool IsDirty() { return mDirty; } - void SetDirty() { mDirty = true; } - void ClearDirty() { mDirty = false; } NodeId mNodeId = 0; ClusterId mClusterId = 0; ListIndex mListIndex = 0; AttributeId mFieldId = 0; EndpointId mEndpointId = 0; - bool mDirty = false; BitFlags mFlags; ClusterInfo * mpNext = nullptr; EventId mEventId = 0; diff --git a/src/app/InteractionModelDelegate.h b/src/app/InteractionModelDelegate.h index 2c1cccf2a93ba7..9068a5c2e3c15c 100644 --- a/src/app/InteractionModelDelegate.h +++ b/src/app/InteractionModelDelegate.h @@ -40,6 +40,7 @@ static constexpr uint32_t kImMessageTimeoutMsec = 12000; class ReadClient; class WriteClient; class CommandSender; +class ReadHandler; /** * @brief @@ -196,7 +197,17 @@ class InteractionModelDelegate } /** - * Notification that a read client has completed the current interaction. + * Notification that a Subscribe Response has been processed and application can do further work . + */ + virtual CHIP_ERROR SubscribeResponseProcessed(const ReadClient * apReadClient) { return CHIP_ERROR_NOT_IMPLEMENTED; } + + /** + * Notification that Subscription has been established successfully and application can do further work in handler. + */ + virtual CHIP_ERROR SubscriptionEstablished(const ReadHandler * apReadHandler) { return CHIP_ERROR_NOT_IMPLEMENTED; } + + /** + * Notification that a read interaction was completed on the client successfully. * @param[in] apReadClient A current read client which can identify the read client to the consumer, particularly * during multiple read interactions * @param[in] aError notify final error regarding the current read interaction diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index 893c279060bc0f..bda1188f806f47 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -106,10 +106,11 @@ void InteractionModelEngine::Shutdown() VerifyOrDie(writeHandler.IsFree()); } + mReportingEngine.Shutdown(); + for (uint32_t index = 0; index < CHIP_IM_SERVER_MAX_NUM_PATH_GROUPS; index++) { mClusterInfoPool[index].mpNext = nullptr; - mClusterInfoPool[index].ClearDirty(); } mpNextAvailableClusterInfo = nullptr; @@ -137,7 +138,8 @@ CHIP_ERROR InteractionModelEngine::NewCommandSender(CommandSender ** const apCom return CHIP_ERROR_NO_MEMORY; } -CHIP_ERROR InteractionModelEngine::NewReadClient(ReadClient ** const apReadClient, uint64_t aAppIdentifier) +CHIP_ERROR InteractionModelEngine::NewReadClient(ReadClient ** const apReadClient, ReadClient::InteractionType aInteractionType, + uint64_t aAppIdentifier) { CHIP_ERROR err = CHIP_ERROR_NO_MEMORY; @@ -146,7 +148,7 @@ CHIP_ERROR InteractionModelEngine::NewReadClient(ReadClient ** const apReadClien if (readClient.IsFree()) { *apReadClient = &readClient; - err = readClient.Init(mpExchangeMgr, mpDelegate, aAppIdentifier); + err = readClient.Init(mpExchangeMgr, mpDelegate, aInteractionType, aAppIdentifier); if (CHIP_NO_ERROR != err) { *apReadClient = nullptr; @@ -227,17 +229,19 @@ CHIP_ERROR InteractionModelEngine::OnInvokeCommandRequest(Messaging::ExchangeCon CHIP_ERROR InteractionModelEngine::OnReadInitialRequest(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader, - System::PacketBufferHandle && aPayload) + System::PacketBufferHandle && aPayload, + ReadHandler::InteractionType aInteractionType) { CHIP_ERROR err = CHIP_NO_ERROR; - ChipLogDetail(InteractionModel, "Receive Read request"); + ChipLogDetail(InteractionModel, "Receive %s request", + aInteractionType == ReadHandler::InteractionType::Subscribe ? "Subscribe" : "Read"); for (auto & readHandler : mReadHandlers) { if (readHandler.IsFree()) { - err = readHandler.Init(mpExchangeMgr, mpDelegate, apExchangeContext); + err = readHandler.Init(mpExchangeMgr, mpDelegate, apExchangeContext, aInteractionType); SuccessOrExit(err); err = readHandler.OnReadInitialRequest(std::move(aPayload)); apExchangeContext = nullptr; @@ -282,6 +286,36 @@ CHIP_ERROR InteractionModelEngine::OnWriteRequest(Messaging::ExchangeContext * a return err; } +CHIP_ERROR InteractionModelEngine::OnUnsolicitedReportData(Messaging::ExchangeContext * apExchangeContext, + const PayloadHeader & aPayloadHeader, + System::PacketBufferHandle && aPayload) +{ + System::PacketBufferTLVReader reader; + reader.Init(aPayload.Retain()); + ReturnLogErrorOnFailure(reader.Next()); + + ReportData::Parser report; + ReturnLogErrorOnFailure(report.Init(reader)); + + uint64_t subscriptionId = 0; + ReturnLogErrorOnFailure(report.GetSubscriptionId(&subscriptionId)); + + for (auto & readClient : mReadClients) + { + if (!readClient.IsSubscriptionTypeIdle()) + { + continue; + } + if (!readClient.IsMatchingClient(subscriptionId)) + { + continue; + } + + return readClient.OnUnsolicitedReportData(apExchangeContext, std::move(aPayload)); + } + return CHIP_NO_ERROR; +} + CHIP_ERROR InteractionModelEngine::OnMessageReceived(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader, System::PacketBufferHandle && aPayload) { @@ -291,12 +325,21 @@ CHIP_ERROR InteractionModelEngine::OnMessageReceived(Messaging::ExchangeContext } else if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::ReadRequest)) { - return OnReadInitialRequest(apExchangeContext, aPayloadHeader, std::move(aPayload)); + return OnReadInitialRequest(apExchangeContext, aPayloadHeader, std::move(aPayload), ReadHandler::InteractionType::Read); } else if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::WriteRequest)) { return OnWriteRequest(apExchangeContext, aPayloadHeader, std::move(aPayload)); } + else if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::SubscribeRequest)) + { + return OnReadInitialRequest(apExchangeContext, aPayloadHeader, std::move(aPayload), + ReadHandler::InteractionType::Subscribe); + } + else if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::ReportData)) + { + return OnUnsolicitedReportData(apExchangeContext, aPayloadHeader, std::move(aPayload)); + } else { return OnUnknownMsgType(apExchangeContext, aPayloadHeader, std::move(aPayload)); @@ -312,7 +355,7 @@ CHIP_ERROR InteractionModelEngine::SendReadRequest(ReadPrepareParams & aReadPrep { ReadClient * client = nullptr; CHIP_ERROR err = CHIP_NO_ERROR; - ReturnErrorOnFailure(NewReadClient(&client, aAppIdentifier)); + ReturnErrorOnFailure(NewReadClient(&client, ReadClient::InteractionType::Read, aAppIdentifier)); err = client->SendReadRequest(aReadPrepareParams); if (err != CHIP_NO_ERROR) { @@ -321,6 +364,14 @@ CHIP_ERROR InteractionModelEngine::SendReadRequest(ReadPrepareParams & aReadPrep return err; } +CHIP_ERROR InteractionModelEngine::SendSubscribeRequest(ReadPrepareParams & aReadPrepareParams, uint64_t aAppIdentifier) +{ + ReadClient * client = nullptr; + ReturnErrorOnFailure(NewReadClient(&client, ReadClient::InteractionType::Subscribe, aAppIdentifier)); + ReturnErrorOnFailure(client->SendSubscribeRequest(aReadPrepareParams)); + return CHIP_NO_ERROR; +} + uint16_t InteractionModelEngine::GetReadClientArrayIndex(const ReadClient * const apReadClient) const { return static_cast(apReadClient - mReadClients); @@ -341,10 +392,8 @@ void InteractionModelEngine::ReleaseClusterInfoList(ClusterInfo *& aClusterInfo) while (lastClusterInfo != nullptr && lastClusterInfo->mpNext != nullptr) { - lastClusterInfo->ClearDirty(); lastClusterInfo = lastClusterInfo->mpNext; } - lastClusterInfo->ClearDirty(); lastClusterInfo->mFlags.ClearAll(); lastClusterInfo->mpNext = mpNextAvailableClusterInfo; mpNextAvailableClusterInfo = aClusterInfo; @@ -356,6 +405,7 @@ CHIP_ERROR InteractionModelEngine::PushFront(ClusterInfo *& aClusterInfoList, Cl ClusterInfo * last = aClusterInfoList; if (mpNextAvailableClusterInfo == nullptr) { + ChipLogProgress(InteractionModel, "There is no available cluster info in mClusterInfoPool"); return CHIP_ERROR_NO_MEMORY; } aClusterInfoList = mpNextAvailableClusterInfo; @@ -365,5 +415,50 @@ CHIP_ERROR InteractionModelEngine::PushFront(ClusterInfo *& aClusterInfoList, Cl return CHIP_NO_ERROR; } +bool InteractionModelEngine::MergeOverlappedAttributePath(ClusterInfo * apAttributePathList, ClusterInfo & aAttributePath) +{ + ClusterInfo * runner = apAttributePathList; + while (runner != nullptr) + { + // If overlapped, we would skip this target path, + // --If targetPath is part of previous path, return true + // --If previous path is part of target path, update filedid and listindex and mflags with target path, return true + if (runner->IsAttributePathSupersetOf(aAttributePath)) + { + return true; + } + if (aAttributePath.IsAttributePathSupersetOf(*runner)) + { + runner->mListIndex = aAttributePath.mListIndex; + runner->mFieldId = aAttributePath.mFieldId; + runner->mFlags = aAttributePath.mFlags; + return true; + } + runner = runner->mpNext; + } + return false; +} + +bool InteractionModelEngine::IsOverlappedAttributePath(ClusterInfo & aAttributePath) +{ + for (auto & handler : mReadHandlers) + { + if (handler.IsSubscriptionType() && (handler.IsGeneratingReports() || handler.IsAwaitingReportResponse())) + { + for (auto clusterInfo = handler.GetAttributeClusterInfolist(); clusterInfo != nullptr; + clusterInfo = clusterInfo->mpNext) + { + if (clusterInfo->IsAttributePathSupersetOf(aAttributePath) || + aAttributePath.IsAttributePathSupersetOf(*clusterInfo)) + { + return true; + } + } + } + } + ChipLogDetail(DataManagement, "AttributePath is not interested"); + return false; +} + } // namespace app } // namespace chip diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h index f1c2290ca241c8..3e0dd9e1e30ca3 100644 --- a/src/app/InteractionModelEngine.h +++ b/src/app/InteractionModelEngine.h @@ -111,6 +111,14 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate */ CHIP_ERROR SendReadRequest(ReadPrepareParams & aReadPrepareParams, uint64_t aAppIdentifier = 0); + /** + * Creates a new read client and sends SubscribeRequest message to the node using the read client. + * Shuts down on transmission failure. + * + * @retval #CHIP_ERROR_NO_MEMORY If there is no ReadClient available + * @retval #CHIP_NO_ERROR On success. + */ + CHIP_ERROR SendSubscribeRequest(ReadPrepareParams & aReadPrepareParams, uint64_t aAppIdentifier = 0); /** * Retrieve a WriteClient that the SDK consumer can use to send a write. If the call succeeds, * see WriteClient documentation for lifetime handling. @@ -141,6 +149,10 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate void ReleaseClusterInfoList(ClusterInfo *& aClusterInfo); CHIP_ERROR PushFront(ClusterInfo *& aClusterInfoLisst, ClusterInfo & aClusterInfo); + // Merges aAttributePath inside apAttributePathList if current path is overlapped with existing path in apAttributePathList + // Overlap means the path is superset or subset of another path + bool MergeOverlappedAttributePath(ClusterInfo * apAttributePathList, ClusterInfo & aAttributePath); + bool IsOverlappedAttributePath(ClusterInfo & aAttributePath); private: friend class reporting::Engine; @@ -156,8 +168,9 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate * Called when Interaction Model receives a Read Request message. Errors processing * the Read Request are handled entirely within this function. */ + CHIP_ERROR OnReadInitialRequest(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader, - System::PacketBufferHandle && aPayload); + System::PacketBufferHandle && aPayload, ReadHandler::InteractionType aInteractionType); /** * Called when Interaction Model receives a Write Request message. Errors processing @@ -166,6 +179,11 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate CHIP_ERROR OnWriteRequest(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader, System::PacketBufferHandle && aPayload); + /**This function handles processing of un-solicited ReportData messages on the client, which can + * only occur post subscription establishment + */ + CHIP_ERROR OnUnsolicitedReportData(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader, + System::PacketBufferHandle && aPayload); /** * Retrieve a ReadClient that the SDK consumer can use to send do a read. If the call succeeds, the consumer * is responsible for calling Shutdown() on the ReadClient once it's done using it. @@ -173,7 +191,8 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate * @retval #CHIP_ERROR_INCORRECT_STATE If there is no ReadClient available * @retval #CHIP_NO_ERROR On success. */ - CHIP_ERROR NewReadClient(ReadClient ** const apReadClient, uint64_t aAppIdentifier); + CHIP_ERROR NewReadClient(ReadClient ** const apReadClient, ReadClient::InteractionType aInteractionType, + uint64_t aAppIdentifier); Messaging::ExchangeManager * mpExchangeMgr = nullptr; InteractionModelDelegate * mpDelegate = nullptr; diff --git a/src/app/MessageDef/SubscribeResponse.cpp b/src/app/MessageDef/SubscribeResponse.cpp index 6e19cda36512bd..6add842ded8c92 100644 --- a/src/app/MessageDef/SubscribeResponse.cpp +++ b/src/app/MessageDef/SubscribeResponse.cpp @@ -59,15 +59,27 @@ CHIP_ERROR SubscribeResponse::Parser::CheckSchemaValidity() const } #endif // CHIP_DETAIL_LOGGING break; - case kCsTag_FinalSyncIntervalSeconds: - VerifyOrReturnLogError(!(TagPresenceMask & (1 << kCsTag_FinalSyncIntervalSeconds)), CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << kCsTag_FinalSyncIntervalSeconds); + case kCsTag_MinIntervalFloorSeconds: + VerifyOrReturnLogError(!(TagPresenceMask & (1 << kCsTag_MinIntervalFloorSeconds)), CHIP_ERROR_INVALID_TLV_TAG); + TagPresenceMask |= (1 << kCsTag_MinIntervalFloorSeconds); VerifyOrReturnLogError(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { - uint16_t finalSyncIntervalSeconds; - ReturnLogErrorOnFailure(reader.Get(finalSyncIntervalSeconds)); - PRETTY_PRINT("\tFinalSyncIntervalSeconds = 0x%" PRIx16 ",", finalSyncIntervalSeconds); + uint16_t minIntervalFloorSeconds; + ReturnLogErrorOnFailure(reader.Get(minIntervalFloorSeconds)); + PRETTY_PRINT("\tMinIntervalFloorSeconds = 0x%" PRIx16 ",", minIntervalFloorSeconds); + } +#endif // CHIP_DETAIL_LOGGING + break; + case kCsTag_MaxIntervalCeilingSeconds: + VerifyOrReturnLogError(!(TagPresenceMask & (1 << kCsTag_MaxIntervalCeilingSeconds)), CHIP_ERROR_INVALID_TLV_TAG); + TagPresenceMask |= (1 << kCsTag_MaxIntervalCeilingSeconds); + VerifyOrReturnLogError(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); +#if CHIP_DETAIL_LOGGING + { + uint16_t maxIntervalCeilingSeconds; + ReturnLogErrorOnFailure(reader.Get(maxIntervalCeilingSeconds)); + PRETTY_PRINT("\tMaxIntervalCeilingSeconds = 0x%" PRIx16 ",", maxIntervalCeilingSeconds); } #endif // CHIP_DETAIL_LOGGING break; @@ -80,7 +92,8 @@ CHIP_ERROR SubscribeResponse::Parser::CheckSchemaValidity() const if (CHIP_END_OF_TLV == err) { - const uint16_t RequiredFields = (1 << kCsTag_SubscriptionId) | (1 << kCsTag_FinalSyncIntervalSeconds); + const uint16_t RequiredFields = + (1 << kCsTag_SubscriptionId) | (1 << kCsTag_MinIntervalFloorSeconds) | (1 << kCsTag_MaxIntervalCeilingSeconds); if ((TagPresenceMask & RequiredFields) == RequiredFields) { @@ -97,9 +110,14 @@ CHIP_ERROR SubscribeResponse::Parser::GetSubscriptionId(uint64_t * const apSubsc return GetUnsignedInteger(kCsTag_SubscriptionId, apSubscribeId); } -CHIP_ERROR SubscribeResponse::Parser::GetFinalSyncIntervalSeconds(uint16_t * const apFinalSyncIntervalSeconds) const +CHIP_ERROR SubscribeResponse::Parser::GetMinIntervalFloorSeconds(uint16_t * const apMinIntervalFloorSeconds) const +{ + return GetUnsignedInteger(kCsTag_MinIntervalFloorSeconds, apMinIntervalFloorSeconds); +} + +CHIP_ERROR SubscribeResponse::Parser::GetMaxIntervalCeilingSeconds(uint16_t * const apMaxIntervalCeilingSeconds) const { - return GetUnsignedInteger(kCsTag_FinalSyncIntervalSeconds, apFinalSyncIntervalSeconds); + return GetUnsignedInteger(kCsTag_MaxIntervalCeilingSeconds, apMaxIntervalCeilingSeconds); } CHIP_ERROR SubscribeResponse::Builder::Init(chip::TLV::TLVWriter * const apWriter) @@ -116,11 +134,20 @@ SubscribeResponse::Builder & SubscribeResponse::Builder::SubscriptionId(const ui return *this; } -SubscribeResponse::Builder & SubscribeResponse::Builder::FinalSyncIntervalSeconds(const uint16_t aFinalSyncIntervalSeconds) +SubscribeResponse::Builder & SubscribeResponse::Builder::MinIntervalFloorSeconds(const uint16_t aMinIntervalFloorSeconds) +{ + if (mError == CHIP_NO_ERROR) + { + mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_MinIntervalFloorSeconds), aMinIntervalFloorSeconds); + } + return *this; +} + +SubscribeResponse::Builder & SubscribeResponse::Builder::MaxIntervalCeilingSeconds(const uint16_t aMaxIntervalCeilingSeconds) { if (mError == CHIP_NO_ERROR) { - mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_FinalSyncIntervalSeconds), aFinalSyncIntervalSeconds); + mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_MaxIntervalCeilingSeconds), aMaxIntervalCeilingSeconds); } return *this; } diff --git a/src/app/MessageDef/SubscribeResponse.h b/src/app/MessageDef/SubscribeResponse.h index bf01f1ff74eb3e..0ba9ca4f27d438 100644 --- a/src/app/MessageDef/SubscribeResponse.h +++ b/src/app/MessageDef/SubscribeResponse.h @@ -31,8 +31,9 @@ namespace app { namespace SubscribeResponse { enum { - kCsTag_SubscriptionId = 0, - kCsTag_FinalSyncIntervalSeconds = 1, + kCsTag_SubscriptionId = 0, + kCsTag_MinIntervalFloorSeconds = 1, + kCsTag_MaxIntervalCeilingSeconds = 2, }; class Parser : public chip::app::Parser @@ -66,12 +67,20 @@ class Parser : public chip::app::Parser CHIP_ERROR GetSubscriptionId(uint64_t * const apSubscriptionId) const; /** - * @brief Get FinalSyncIntervalSeconds. Next() must be called before accessing them. + * @brief Get Final MinIntervalFloorSeconds. Next() must be called before accessing them. * * @return #CHIP_NO_ERROR on success * #CHIP_END_OF_TLV if there is no such element */ - CHIP_ERROR GetFinalSyncIntervalSeconds(uint16_t * const apFinalSyncIntervalSeconds) const; + CHIP_ERROR GetMinIntervalFloorSeconds(uint16_t * const apMinIntervalFloorSeconds) const; + + /** + * @brief Get Final MaxIntervalCeilingSeconds. Next() must be called before accessing them. + * + * @return #CHIP_NO_ERROR on success + * #CHIP_END_OF_TLV if there is no such element + */ + CHIP_ERROR GetMaxIntervalCeilingSeconds(uint16_t * const apMaxIntervalCeilingSeconds) const; }; class Builder : public chip::app::Builder @@ -85,9 +94,14 @@ class Builder : public chip::app::Builder SubscribeResponse::Builder & SubscriptionId(const uint64_t SubscriptionId); /** - * @brief Final Sync Interval for the subscription back to the clients. + * @brief Final Min Interval for the subscription back to the clients. + */ + SubscribeResponse::Builder & MinIntervalFloorSeconds(const uint16_t aMinIntervalFloorSeconds); + + /** + * @brief Final Max Interval for the subscription back to the clients. */ - SubscribeResponse::Builder & FinalSyncIntervalSeconds(const uint16_t aFinalSyncIntervalSeconds); + SubscribeResponse::Builder & MaxIntervalCeilingSeconds(const uint16_t aMaxIntervalCeilingSeconds); /** * @brief Mark the end of this SubscribeResponse diff --git a/src/app/ReadClient.cpp b/src/app/ReadClient.cpp index 6b2c4a34ed2bf9..b9dea66a60334f 100644 --- a/src/app/ReadClient.cpp +++ b/src/app/ReadClient.cpp @@ -31,18 +31,22 @@ namespace chip { namespace app { CHIP_ERROR ReadClient::Init(Messaging::ExchangeManager * apExchangeMgr, InteractionModelDelegate * apDelegate, - uint64_t aAppIdentifier) + InteractionType aInteractionType, uint64_t aAppIdentifier) { CHIP_ERROR err = CHIP_NO_ERROR; // Error if already initialized. + VerifyOrExit(IsFree(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(apExchangeMgr != nullptr, err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mpExchangeMgr == nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); - - mpExchangeMgr = apExchangeMgr; - mpDelegate = apDelegate; - mState = ClientState::Initialized; - mAppIdentifier = aAppIdentifier; - mInitialReport = true; + mpExchangeMgr = apExchangeMgr; + mpDelegate = apDelegate; + mState = ClientState::Initialized; + mAppIdentifier = aAppIdentifier; + mMinIntervalFloorSeconds = 0; + mMaxIntervalCeilingSeconds = 0; + mSubscriptionId = 0; + mInitialReport = true; + mInteractionType = aInteractionType; AbortExistingExchangeContext(); exit: @@ -63,12 +67,23 @@ void ReadClient::ShutdownInternal(CHIP_ERROR aError) { mpDelegate->ReadError(this, aError); } - mpDelegate->ReadDone(this); + else + { + mpDelegate->ReadDone(this); + } mpDelegate = nullptr; } - mpExchangeMgr = nullptr; - mpExchangeCtx = nullptr; - mInitialReport = true; + if (IsSubscriptionType()) + { + CancelLivenessCheckTimer(); + } + mMinIntervalFloorSeconds = 0; + mMaxIntervalCeilingSeconds = 0; + mSubscriptionId = 0; + mInteractionType = InteractionType::Read; + mpExchangeMgr = nullptr; + mpExchangeCtx = nullptr; + mInitialReport = true; MoveToState(ClientState::Uninitialized); } @@ -83,6 +98,10 @@ const char * ReadClient::GetStateStr() const return "INIT"; case ClientState::AwaitingInitialReport: return "AwaitingInitialReport"; + case ClientState::AwaitingSubscribeResponse: + return "AwaitingSubscribeResponse"; + case ClientState::SubscriptionActive: + return "SubscriptionActive"; } #endif // CHIP_DETAIL_LOGGING return "N/A"; @@ -175,7 +194,6 @@ CHIP_ERROR ReadClient::SendStatusReport(CHIP_ERROR aError) Protocols::SecureChannel::GeneralStatusCode generalCode = Protocols::SecureChannel::GeneralStatusCode::kSuccess; uint32_t protocolId = Protocols::InteractionModel::Id.ToFullyQualifiedSpecForm(); uint16_t protocolCode = to_underlying(Protocols::InteractionModel::ProtocolCode::Success); - bool expectResponse = false; VerifyOrReturnLogError(mpExchangeCtx != nullptr, CHIP_ERROR_INCORRECT_STATE); if (aError != CHIP_NO_ERROR) @@ -191,9 +209,21 @@ CHIP_ERROR ReadClient::SendStatusReport(CHIP_ERROR aError) System::PacketBufferHandle msgBuf = buf.Finalize(); VerifyOrReturnLogError(!msgBuf.IsNull(), CHIP_ERROR_NO_MEMORY); - ReturnLogErrorOnFailure(mpExchangeCtx->SendMessage( - Protocols::SecureChannel::MsgType::StatusReport, std::move(msgBuf), - Messaging::SendFlags(expectResponse ? Messaging::SendMessageFlags::kExpectResponse : Messaging::SendMessageFlags::kNone))); + if (IsSubscriptionType()) + { + if (IsAwaitingInitialReport()) + { + MoveToState(ClientState::AwaitingSubscribeResponse); + } + else + { + RefreshLivenessCheckTimer(); + } + } + ReturnLogErrorOnFailure( + mpExchangeCtx->SendMessage(Protocols::SecureChannel::MsgType::StatusReport, std::move(msgBuf), + Messaging::SendFlags(IsAwaitingSubscribeResponse() ? Messaging::SendMessageFlags::kExpectResponse + : Messaging::SendMessageFlags::kNone))); return CHIP_NO_ERROR; } @@ -261,14 +291,22 @@ CHIP_ERROR ReadClient::OnMessageReceived(Messaging::ExchangeContext * apExchange err = ProcessReportData(std::move(aPayload)); SuccessOrExit(err); } + else if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::SubscribeResponse)) + { + VerifyOrExit(apExchangeContext == mpExchangeCtx, err = CHIP_ERROR_INCORRECT_STATE); + err = ProcessSubscribeResponse(std::move(aPayload)); + SuccessOrExit(err); + } else { err = CHIP_ERROR_INVALID_MESSAGE_TYPE; } exit: - ShutdownInternal(err); - + if (!IsSubscriptionType() || err != CHIP_NO_ERROR) + { + ShutdownInternal(err); + } return err; } @@ -283,6 +321,18 @@ CHIP_ERROR ReadClient::AbortExistingExchangeContext() return CHIP_NO_ERROR; } +CHIP_ERROR ReadClient::OnUnsolicitedReportData(Messaging::ExchangeContext * apExchangeContext, + System::PacketBufferHandle && aPayload) +{ + mpExchangeCtx = apExchangeContext; + CHIP_ERROR err = ProcessReportData(std::move(aPayload)); + if (err != CHIP_NO_ERROR) + { + ShutdownInternal(err); + } + return err; +} + CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle && aPayload) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -292,6 +342,7 @@ CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle && aPayload) bool isAttributeDataListPresent = false; bool suppressResponse = false; bool moreChunkedMessages = false; + uint64_t subscriptionId = 0; EventList::Parser eventList; AttributeDataList::Parser attributeDataList; System::PacketBufferTLVReader reader; @@ -314,10 +365,31 @@ CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle && aPayload) } SuccessOrExit(err); - if (IsInitialReport()) + err = report.GetSubscriptionId(&subscriptionId); + if (CHIP_NO_ERROR == err) + { + if (IsInitialReport()) + { + mSubscriptionId = subscriptionId; + } + else if (!IsMatchingClient(subscriptionId)) + { + err = CHIP_ERROR_INVALID_ARGUMENT; + } + } + else if (CHIP_END_OF_TLV == err) { - ChipLogProgress(DataManagement, "ProcessReportData handles the initial report"); + if (IsSubscriptionType()) + { + err = CHIP_ERROR_INVALID_ARGUMENT; + } + else + { + err = CHIP_NO_ERROR; + } } + SuccessOrExit(err); + err = report.GetMoreChunkedMessages(&moreChunkedMessages); if (CHIP_END_OF_TLV == err) { @@ -368,6 +440,10 @@ CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle && aPayload) } exit: SendStatusReport(err); + if (!mInitialReport) + { + mpExchangeCtx = nullptr; + } mInitialReport = false; return err; } @@ -453,5 +529,136 @@ CHIP_ERROR ReadClient::ProcessAttributeDataList(TLV::TLVReader & aAttributeDataL exit: return err; } + +CHIP_ERROR ReadClient::RefreshLivenessCheckTimer() +{ + CancelLivenessCheckTimer(); + ChipLogProgress(DataManagement, "Refresh LivenessCheckTime with %d seconds", mMaxIntervalCeilingSeconds); + CHIP_ERROR err = InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionMgr()->SystemLayer()->StartTimer( + mMaxIntervalCeilingSeconds * kMillisecondsPerSecond, OnLivenessTimeoutCallback, this); + + if (err != CHIP_NO_ERROR) + { + ShutdownInternal(err); + } + return err; +} + +void ReadClient::CancelLivenessCheckTimer() +{ + InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionMgr()->SystemLayer()->CancelTimer( + OnLivenessTimeoutCallback, this); +} + +void ReadClient::OnLivenessTimeoutCallback(System::Layer * apSystemLayer, void * apAppState) +{ + ReadClient * const client = reinterpret_cast(apAppState); + ChipLogError(DataManagement, "Subscription Liveness timeout, shutting down"); + if (client->IsFree()) + { + ChipLogError(DataManagement, + "ReadClient::OnLivenessTimeoutCallback invoked on a free client! This is a bug in CHIP stack!"); + return; + } + // TODO: add a more specific error here for liveness timeout failure to distinguish between other classes of timeouts (i.e + // response timeouts). + client->ShutdownInternal(CHIP_ERROR_TIMEOUT); +} + +CHIP_ERROR ReadClient::ProcessSubscribeResponse(System::PacketBufferHandle && aPayload) +{ + System::PacketBufferTLVReader reader; + reader.Init(std::move(aPayload)); + ReturnLogErrorOnFailure(reader.Next()); + + SubscribeResponse::Parser subscribeResponse; + ReturnLogErrorOnFailure(subscribeResponse.Init(reader)); + +#if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK + ReturnLogErrorOnFailure(subscribeResponse.CheckSchemaValidity()); +#endif + + uint64_t subscriptionId = 0; + ReturnLogErrorOnFailure(subscribeResponse.GetSubscriptionId(&subscriptionId)); + VerifyOrReturnLogError(IsMatchingClient(subscriptionId), CHIP_ERROR_INVALID_ARGUMENT); + ReturnLogErrorOnFailure(subscribeResponse.GetMinIntervalFloorSeconds(&mMinIntervalFloorSeconds)); + ReturnLogErrorOnFailure(subscribeResponse.GetMaxIntervalCeilingSeconds(&mMaxIntervalCeilingSeconds)); + mpDelegate->SubscribeResponseProcessed(this); + + MoveToState(ClientState::SubscriptionActive); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ReadClient::SendSubscribeRequest(ReadPrepareParams & aReadPrepareParams) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + System::PacketBufferHandle msgBuf; + System::PacketBufferTLVWriter writer; + SubscribeRequest::Builder request; + VerifyOrExit(ClientState::Initialized == mState, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mpExchangeCtx == nullptr, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mpDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + msgBuf = System::PacketBufferHandle::New(kMaxSecureSduLengthBytes); + VerifyOrExit(!msgBuf.IsNull(), err = CHIP_ERROR_NO_MEMORY); + + writer.Init(std::move(msgBuf)); + + err = request.Init(&writer); + SuccessOrExit(err); + + if (aReadPrepareParams.mEventPathParamsListSize != 0 && aReadPrepareParams.mpEventPathParamsList != nullptr) + { + EventPathList::Builder & eventPathListBuilder = request.CreateEventPathListBuilder(); + SuccessOrExit(err = eventPathListBuilder.GetError()); + err = GenerateEventPathList(eventPathListBuilder, aReadPrepareParams.mpEventPathParamsList, + aReadPrepareParams.mEventPathParamsListSize); + SuccessOrExit(err); + + if (aReadPrepareParams.mEventNumber != 0) + { + // EventNumber is optional + request.EventNumber(aReadPrepareParams.mEventNumber); + } + } + + if (aReadPrepareParams.mAttributePathParamsListSize != 0 && aReadPrepareParams.mpAttributePathParamsList != nullptr) + { + AttributePathList::Builder & attributePathListBuilder = request.CreateAttributePathListBuilder(); + SuccessOrExit(err = attributePathListBuilder.GetError()); + err = GenerateAttributePathList(attributePathListBuilder, aReadPrepareParams.mpAttributePathParamsList, + aReadPrepareParams.mAttributePathParamsListSize); + SuccessOrExit(err); + } + + request.MinIntervalSeconds(aReadPrepareParams.mMinIntervalFloorSeconds) + .MaxIntervalSeconds(aReadPrepareParams.mMaxIntervalCeilingSeconds) + .EndOfSubscribeRequest(); + SuccessOrExit(err = request.GetError()); + + err = writer.Finalize(&msgBuf); + SuccessOrExit(err); + + mpExchangeCtx = mpExchangeMgr->NewContext(aReadPrepareParams.mSessionHandle, this); + VerifyOrExit(mpExchangeCtx != nullptr, err = CHIP_ERROR_NO_MEMORY); + mpExchangeCtx->SetResponseTimeout(kImMessageTimeoutMsec); + + err = mpExchangeCtx->SendMessage(Protocols::InteractionModel::MsgType::SubscribeRequest, std::move(msgBuf), + Messaging::SendFlags(Messaging::SendMessageFlags::kExpectResponse)); + SuccessOrExit(err); + MoveToState(ClientState::AwaitingInitialReport); + +exit: + if (err != CHIP_NO_ERROR) + { + AbortExistingExchangeContext(); + } + if (err != CHIP_NO_ERROR) + { + Shutdown(); + } + return err; +} + }; // namespace app }; // namespace chip diff --git a/src/app/ReadClient.h b/src/app/ReadClient.h index f85442befabcd6..67d8c9123a9c20 100644 --- a/src/app/ReadClient.h +++ b/src/app/ReadClient.h @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -52,6 +54,11 @@ namespace app { class ReadClient : public Messaging::ExchangeDelegate { public: + enum class InteractionType : uint8_t + { + Read, + Subscribe, + }; /** * Shut down the Client. This terminates this instance of the object and releases * all held resources. The object must not be used after Shutdown() is called. @@ -74,8 +81,20 @@ class ReadClient : public Messaging::ExchangeDelegate */ CHIP_ERROR SendReadRequest(ReadPrepareParams & aReadPrepareParams); + /** + * Send a subscribe Request. There can be one Subscribe Request outstanding on a given ReadClient. + * If SendSubscribeRequest returns success, no more subscribe Requests can be sent on this ReadClient + * until the corresponding InteractionModelDelegate::ReadDone call happens with guarantee. + * + * @retval #others fail to send subscribe request + * @retval #CHIP_NO_ERROR On success. + */ + CHIP_ERROR SendSubscribeRequest(ReadPrepareParams & aSubscribePrepareParams); + CHIP_ERROR OnUnsolicitedReportData(Messaging::ExchangeContext * apExchangeContext, System::PacketBufferHandle && aPayload); uint64_t GetAppIdentifier() const { return mAppIdentifier; } Messaging::ExchangeContext * GetExchangeContext() const { return mpExchangeCtx; } + bool IsReadType() { return mInteractionType == InteractionType::Read; } + bool IsSubscriptionType() const { return mInteractionType == InteractionType::Subscribe; }; CHIP_ERROR SendStatusReport(CHIP_ERROR aError); private: @@ -84,11 +103,17 @@ class ReadClient : public Messaging::ExchangeDelegate enum class ClientState { - Uninitialized = 0, ///< The client has not been initialized - Initialized, ///< The client has been initialized and is ready for a SendReadRequest - AwaitingInitialReport, ///< The client is waiting for initial report + Uninitialized = 0, ///< The client has not been initialized + Initialized, ///< The client has been initialized and is ready for a SendReadRequest + AwaitingInitialReport, ///< The client is waiting for initial report + AwaitingSubscribeResponse, ///< The client is waiting for subscribe response + SubscriptionActive, ///< The client is maintaining subscription }; + bool IsMatchingClient(uint64_t aSubscriptionId) + { + return aSubscriptionId == mSubscriptionId && mInteractionType == InteractionType::Subscribe; + } /** * Initialize the client object. Within the lifetime * of this instance, this method is invoked once after object @@ -102,7 +127,8 @@ class ReadClient : public Messaging::ExchangeDelegate * @retval #CHIP_NO_ERROR On success. * */ - CHIP_ERROR Init(Messaging::ExchangeManager * apExchangeMgr, InteractionModelDelegate * apDelegate, uint64_t aAppIdentifier); + CHIP_ERROR Init(Messaging::ExchangeManager * apExchangeMgr, InteractionModelDelegate * apDelegate, + InteractionType aInteractionType, uint64_t aAppIdentifier); virtual ~ReadClient() = default; @@ -115,16 +141,21 @@ class ReadClient : public Messaging::ExchangeDelegate * */ bool IsFree() const { return mState == ClientState::Uninitialized; } + bool IsSubscriptionTypeIdle() const { return mState == ClientState::SubscriptionActive; } bool IsAwaitingInitialReport() const { return mState == ClientState::AwaitingInitialReport; } + bool IsAwaitingSubscribeResponse() const { return mState == ClientState::AwaitingSubscribeResponse; } + CHIP_ERROR GenerateEventPathList(EventPathList::Builder & aEventPathListBuilder, EventPathParams * apEventPathParamsList, size_t aEventPathParamsListSize); CHIP_ERROR GenerateAttributePathList(AttributePathList::Builder & aAttributeathListBuilder, AttributePathParams * apAttributePathParamsList, size_t aAttributePathParamsListSize); CHIP_ERROR ProcessAttributeDataList(TLV::TLVReader & aAttributeDataListReader); - void SetExchangeContext(Messaging::ExchangeContext * apExchangeContext) { mpExchangeCtx = apExchangeContext; } void ClearExchangeContext() { mpExchangeCtx = nullptr; } - + static void OnLivenessTimeoutCallback(System::Layer * apSystemLayer, void * apAppState); + CHIP_ERROR ProcessSubscribeResponse(System::PacketBufferHandle && aPayload); + CHIP_ERROR RefreshLivenessCheckTimer(); + void CancelLivenessCheckTimer(); void MoveToState(const ClientState aTargetState); CHIP_ERROR ProcessReportData(System::PacketBufferHandle && aPayload); CHIP_ERROR AbortExistingExchangeContext(); @@ -142,6 +173,10 @@ class ReadClient : public Messaging::ExchangeDelegate ClientState mState = ClientState::Uninitialized; uint64_t mAppIdentifier = 0; bool mInitialReport = true; + uint16_t mMinIntervalFloorSeconds = 0; + uint16_t mMaxIntervalCeilingSeconds = 0; + uint64_t mSubscriptionId = 0; + InteractionType mInteractionType = InteractionType::Read; }; }; // namespace app diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index f64ba2aedc0d75..4cb1cbcd64f573 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -25,17 +25,21 @@ #include #include #include +#include +#include #include #include +#include #include namespace chip { namespace app { CHIP_ERROR ReadHandler::Init(Messaging::ExchangeManager * apExchangeMgr, InteractionModelDelegate * apDelegate, - Messaging::ExchangeContext * apExchangeContext) + Messaging::ExchangeContext * apExchangeContext, InteractionType aInteractionType) { CHIP_ERROR err = CHIP_NO_ERROR; // Error if already initialized. + VerifyOrReturnError(IsFree(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrReturnError(mpExchangeCtx == nullptr, err = CHIP_ERROR_INCORRECT_STATE); mpExchangeMgr = apExchangeMgr; mpExchangeCtx = apExchangeContext; @@ -45,7 +49,11 @@ CHIP_ERROR ReadHandler::Init(Messaging::ExchangeManager * apExchangeMgr, Interac mCurrentPriority = PriorityLevel::Invalid; mInitialReport = true; MoveToState(HandlerState::Initialized); - mpDelegate = apDelegate; + mpDelegate = apDelegate; + mSubscriptionId = 0; + mHoldReport = false; + mDirty = false; + mInteractionType = aInteractionType; if (apExchangeContext != nullptr) { apExchangeContext->SetDelegate(this); @@ -56,6 +64,11 @@ CHIP_ERROR ReadHandler::Init(Messaging::ExchangeManager * apExchangeMgr, Interac void ReadHandler::Shutdown(ShutdownOptions aOptions) { + if (IsSubscriptionType()) + { + InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionMgr()->SystemLayer()->CancelTimer( + OnRefreshSubscribeTimerSyncCallback, this); + } if (aOptions == ShutdownOptions::AbortCurrentExchange) { if (mpExchangeCtx != nullptr) @@ -65,27 +78,40 @@ void ReadHandler::Shutdown(ShutdownOptions aOptions) } } - if (IsReporting()) + if (IsAwaitingReportResponse()) { InteractionModelEngine::GetInstance()->GetReportingEngine().OnReportConfirm(); } InteractionModelEngine::GetInstance()->ReleaseClusterInfoList(mpAttributeClusterInfoList); InteractionModelEngine::GetInstance()->ReleaseClusterInfoList(mpEventClusterInfoList); - mpExchangeCtx = nullptr; + mSubscriptionId = 0; + mMinIntervalFloorSeconds = 0; + mMaxIntervalCeilingSeconds = 0; + mInteractionType = InteractionType::Read; + mpExchangeCtx = nullptr; MoveToState(HandlerState::Uninitialized); mpAttributeClusterInfoList = nullptr; mpEventClusterInfoList = nullptr; mCurrentPriority = PriorityLevel::Invalid; mInitialReport = false; mpDelegate = nullptr; + mHoldReport = false; + mDirty = false; } CHIP_ERROR ReadHandler::OnReadInitialRequest(System::PacketBufferHandle && aPayload) { CHIP_ERROR err = CHIP_NO_ERROR; System::PacketBufferHandle response; + if (IsSubscriptionType()) + { + err = ProcessSubscribeRequest(std::move(aPayload)); + } + else + { + err = ProcessReadRequest(std::move(aPayload)); + } - err = ProcessReadRequest(std::move(aPayload)); if (err != CHIP_NO_ERROR) { Shutdown(); @@ -107,10 +133,26 @@ CHIP_ERROR ReadHandler::OnStatusReport(Messaging::ExchangeContext * apExchangeCo err = CHIP_ERROR_INVALID_ARGUMENT); switch (mState) { - case HandlerState::Reporting: - Shutdown(); + case HandlerState::AwaitingReportResponse: + if (IsSubscriptionType()) + { + InteractionModelEngine::GetInstance()->GetReportingEngine().OnReportConfirm(); + if (IsInitialReport()) + { + err = SendSubscribeResponse(); + SuccessOrExit(err); + } + else + { + MoveToState(HandlerState::GeneratingReports); + } + } + else + { + Shutdown(); + } break; - case HandlerState::Reportable: + case HandlerState::GeneratingReports: case HandlerState::Initialized: case HandlerState::Uninitialized: default: @@ -128,14 +170,30 @@ CHIP_ERROR ReadHandler::OnStatusReport(Messaging::ExchangeContext * apExchangeCo CHIP_ERROR ReadHandler::SendReportData(System::PacketBufferHandle && aPayload) { VerifyOrReturnLogError(IsReportable(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnLogError(mpExchangeCtx != nullptr, CHIP_ERROR_INCORRECT_STATE); if (IsInitialReport()) { VerifyOrReturnLogError(mpExchangeCtx != nullptr, CHIP_ERROR_INCORRECT_STATE); + mSessionHandle.SetValue(mpExchangeCtx->GetSecureSession()); + } + else + { + mpExchangeCtx = mpExchangeMgr->NewContext(mSessionHandle.Value(), this); + mpExchangeCtx->SetResponseTimeout(kImMessageTimeoutMsec); } VerifyOrReturnLogError(mpExchangeCtx != nullptr, CHIP_ERROR_INCORRECT_STATE); - MoveToState(HandlerState::Reporting); - return mpExchangeCtx->SendMessage(Protocols::InteractionModel::MsgType::ReportData, std::move(aPayload), - Messaging::SendFlags(Messaging::SendMessageFlags::kExpectResponse)); + MoveToState(HandlerState::AwaitingReportResponse); + CHIP_ERROR err = mpExchangeCtx->SendMessage(Protocols::InteractionModel::MsgType::ReportData, std::move(aPayload), + Messaging::SendFlags(Messaging::SendMessageFlags::kExpectResponse)); + if (err == CHIP_NO_ERROR) + { + if (IsSubscriptionType() && !IsInitialReport()) + { + err = RefreshSubscribeSyncTimer(); + } + } + ClearDirty(); + return err; } CHIP_ERROR ReadHandler::OnMessageReceived(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader, @@ -219,7 +277,7 @@ CHIP_ERROR ReadHandler::ProcessReadRequest(System::PacketBufferHandle && aPayloa err = CHIP_NO_ERROR; } - MoveToState(HandlerState::Reportable); + MoveToState(HandlerState::GeneratingReports); err = InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun(); SuccessOrExit(err); @@ -280,18 +338,9 @@ CHIP_ERROR ReadHandler::ProcessAttributePathList(AttributePathList::Parser & aAt err = CHIP_NO_ERROR; } SuccessOrExit(err); - - if (MergeOverlappedAttributePath(clusterInfo)) - { - continue; - } - else - { - err = InteractionModelEngine::GetInstance()->PushFront(mpAttributeClusterInfoList, clusterInfo); - SuccessOrExit(err); - mpAttributeClusterInfoList->SetDirty(); - mInitialReport = true; - } + err = InteractionModelEngine::GetInstance()->PushFront(mpAttributeClusterInfoList, clusterInfo); + SuccessOrExit(err); + mInitialReport = true; } // if we have exhausted this container if (CHIP_END_OF_TLV == err) @@ -303,31 +352,6 @@ CHIP_ERROR ReadHandler::ProcessAttributePathList(AttributePathList::Parser & aAt return err; } -bool ReadHandler::MergeOverlappedAttributePath(ClusterInfo & aAttributePath) -{ - ClusterInfo * runner = mpAttributeClusterInfoList; - while (runner != nullptr) - { - // If overlapped, we would skip this target path, - // --If targetPath is part of previous path, return true - // --If previous path is part of target path, update filedid and listindex and mflags with target path, return true - if (runner->IsAttributePathSupersetOf(aAttributePath)) - { - return true; - } - if (aAttributePath.IsAttributePathSupersetOf(*runner)) - { - runner->mListIndex = aAttributePath.mListIndex; - runner->mFieldId = aAttributePath.mFieldId; - runner->mFlags = aAttributePath.mFlags; - runner->SetDirty(); - return true; - } - runner = runner->mpNext; - } - return false; -} - CHIP_ERROR ReadHandler::ProcessEventPathList(EventPathList::Parser & aEventPathListParser) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -383,11 +407,11 @@ const char * ReadHandler::GetStateStr() const case HandlerState::Initialized: return "Initialized"; - case HandlerState::Reportable: - return "Reportable"; + case HandlerState::GeneratingReports: + return "GeneratingReports"; - case HandlerState::Reporting: - return "Reporting"; + case HandlerState::AwaitingReportResponse: + return "AwaitingReportResponse"; } #endif // CHIP_DETAIL_LOGGING return "N/A"; @@ -441,5 +465,108 @@ void ReadHandler::MoveToNextScheduledDirtyPriority() mCurrentPriority = PriorityLevel::Invalid; } + +CHIP_ERROR ReadHandler::SendSubscribeResponse() +{ + System::PacketBufferHandle packet = System::PacketBufferHandle::New(chip::app::kMaxSecureSduLengthBytes); + VerifyOrReturnLogError(!packet.IsNull(), CHIP_ERROR_NO_MEMORY); + + System::PacketBufferTLVWriter writer; + writer.Init(std::move(packet)); + + SubscribeResponse::Builder response; + ReturnLogErrorOnFailure(response.Init(&writer)); + response.SubscriptionId(mSubscriptionId) + .MinIntervalFloorSeconds(mMaxIntervalCeilingSeconds) + .MaxIntervalCeilingSeconds(mMaxIntervalCeilingSeconds) + .EndOfSubscribeResponse(); + ReturnLogErrorOnFailure(response.GetError()); + + ReturnLogErrorOnFailure(writer.Finalize(&packet)); + VerifyOrReturnLogError(mpExchangeCtx != nullptr, CHIP_ERROR_INCORRECT_STATE); + + ReturnLogErrorOnFailure(RefreshSubscribeSyncTimer()); + mInitialReport = false; + MoveToState(HandlerState::GeneratingReports); + if (mpDelegate != nullptr) + { + mpDelegate->SubscriptionEstablished(this); + } + return mpExchangeCtx->SendMessage(Protocols::InteractionModel::MsgType::SubscribeResponse, std::move(packet)); +} + +CHIP_ERROR ReadHandler::ProcessSubscribeRequest(System::PacketBufferHandle && aPayload) +{ + System::PacketBufferTLVReader reader; + reader.Init(std::move(aPayload)); + + ReturnLogErrorOnFailure(reader.Next()); + SubscribeRequest::Parser subscribeRequestParser; + ReturnLogErrorOnFailure(subscribeRequestParser.Init(reader)); +#if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK + ReturnLogErrorOnFailure(subscribeRequestParser.CheckSchemaValidity()); +#endif + + AttributePathList::Parser attributePathListParser; + CHIP_ERROR err = subscribeRequestParser.GetAttributePathList(&attributePathListParser); + if (err == CHIP_END_OF_TLV) + { + err = CHIP_NO_ERROR; + } + else if (err == CHIP_NO_ERROR) + { + ReturnLogErrorOnFailure(ProcessAttributePathList(attributePathListParser)); + } + ReturnLogErrorOnFailure(err); + + EventPathList::Parser eventPathListParser; + err = subscribeRequestParser.GetEventPathList(&eventPathListParser); + if (err == CHIP_END_OF_TLV) + { + err = CHIP_NO_ERROR; + } + else if (err == CHIP_NO_ERROR) + { + ReturnLogErrorOnFailure(ProcessEventPathList(eventPathListParser)); + } + ReturnLogErrorOnFailure(err); + + ReturnLogErrorOnFailure(subscribeRequestParser.GetMinIntervalSeconds(&mMinIntervalFloorSeconds)); + ReturnLogErrorOnFailure(subscribeRequestParser.GetMaxIntervalSeconds(&mMaxIntervalCeilingSeconds)); + + // TODO: Use GetSecureRandomData to generate subscription id + // it needs #include , but somehow CHIPRNG.h is missing + // err = Platform::Security::GetSecureRandomData((uint8_t *) &mSubscriptionId, sizeof(mSubscriptionId)); + // SuccessOrExit(err); + mSubscriptionId = GetRandU64(); + + MoveToState(HandlerState::GeneratingReports); + + InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun(); + // mpExchangeCtx can be null here due to + // https://github.com/project-chip/connectedhomeip/issues/8031 + if (mpExchangeCtx) + { + mpExchangeCtx->WillSendMessage(); + } + return CHIP_NO_ERROR; +} + +void ReadHandler::OnRefreshSubscribeTimerSyncCallback(System::Layer * apSystemLayer, void * apAppState) +{ + ReadHandler * aReadHandler = static_cast(apAppState); + aReadHandler->mHoldReport = false; + InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun(); +} + +CHIP_ERROR ReadHandler::RefreshSubscribeSyncTimer() +{ + ChipLogProgress(DataManagement, "ReadHandler::Refresh Subscribe Sync Timer with %d seconds", mMinIntervalFloorSeconds); + InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionMgr()->SystemLayer()->CancelTimer( + OnRefreshSubscribeTimerSyncCallback, this); + mHoldReport = true; + return InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionMgr()->SystemLayer()->StartTimer( + mMinIntervalFloorSeconds * kMillisecondsPerSecond, OnRefreshSubscribeTimerSyncCallback, this); +} } // namespace app } // namespace chip diff --git a/src/app/ReadHandler.h b/src/app/ReadHandler.h index 5e91e2be8e4941..0bd8b23377493c 100644 --- a/src/app/ReadHandler.h +++ b/src/app/ReadHandler.h @@ -56,6 +56,12 @@ class ReadHandler : public Messaging::ExchangeDelegate AbortCurrentExchange, }; + enum class InteractionType : uint8_t + { + Read, + Subscribe, + }; + /** * Initialize the ReadHandler. Within the lifetime * of this instance, this method is invoked once after object @@ -68,7 +74,7 @@ class ReadHandler : public Messaging::ExchangeDelegate * */ CHIP_ERROR Init(Messaging::ExchangeManager * apExchangeMgr, InteractionModelDelegate * apDelegate, - Messaging::ExchangeContext * apExchangeContext); + Messaging::ExchangeContext * apExchangeContext, InteractionType aInteractionType); /** * Shut down the ReadHandler. This terminates this instance @@ -77,7 +83,7 @@ class ReadHandler : public Messaging::ExchangeDelegate */ void Shutdown(ShutdownOptions aOptions = ShutdownOptions::KeepCurrentExchange); /** - * Process a read request. Parts of the processing may end up being asynchronous, but the ReadHandler + * Process a read/subscribe request. Parts of the processing may end up being asynchronous, but the ReadHandler * guarantees that it will call Shutdown on itself when processing is done (including if OnReadInitialRequest * returns an error). * @@ -99,8 +105,9 @@ class ReadHandler : public Messaging::ExchangeDelegate CHIP_ERROR SendReportData(System::PacketBufferHandle && aPayload); bool IsFree() const { return mState == HandlerState::Uninitialized; } - bool IsReportable() const { return mState == HandlerState::Reportable; } - bool IsReporting() const { return mState == HandlerState::Reporting; } + bool IsReportable() const { return mState == HandlerState::GeneratingReports && !mHoldReport; } + bool IsGeneratingReports() const { return mState == HandlerState::GeneratingReports; } + bool IsAwaitingReportResponse() const { return mState == HandlerState::AwaitingReportResponse; } virtual ~ReadHandler() = default; ClusterInfo * GetAttributeClusterInfolist() { return mpAttributeClusterInfoList; } @@ -117,17 +124,30 @@ class ReadHandler : public Messaging::ExchangeDelegate // is larger than current self vended event number void MoveToNextScheduledDirtyPriority(); + bool IsReadType() { return mInteractionType == InteractionType::Read; } + bool IsSubscriptionType() { return mInteractionType == InteractionType::Subscribe; } bool IsInitialReport() { return mInitialReport; } + CHIP_ERROR OnSubscribeRequest(Messaging::ExchangeContext * apExchangeContext, System::PacketBufferHandle && aPayload); + void GetSubscriptionId(uint64_t & aSubscriptionId) { aSubscriptionId = mSubscriptionId; } + void SetDirty() { mDirty = true; } + void ClearDirty() { mDirty = false; } + bool IsDirty() { return mDirty; } private: + friend class TestReadInteraction; enum class HandlerState { - Uninitialized = 0, ///< The handler has not been initialized - Initialized, ///< The handler has been initialized and is ready - Reportable, ///< The handler has received read request and is waiting for the data to send to be available - Reporting, ///< The handler is reporting + Uninitialized = 0, ///< The handler has not been initialized + Initialized, ///< The handler has been initialized and is ready + GeneratingReports, ///< The handler has received either a Read or Subscribe request and is the process of generating a + ///< report. + AwaitingReportResponse, ///< The handler has sent the report to the client and is awaiting a status response. }; + static void OnRefreshSubscribeTimerSyncCallback(System::Layer * apSystemLayer, void * apAppState); + CHIP_ERROR RefreshSubscribeSyncTimer(); + CHIP_ERROR SendSubscribeResponse(); + CHIP_ERROR ProcessSubscribeRequest(System::PacketBufferHandle && aPayload); CHIP_ERROR ProcessReadRequest(System::PacketBufferHandle && aPayload); CHIP_ERROR ProcessAttributePathList(AttributePathList::Parser & aAttributePathListParser); CHIP_ERROR ProcessEventPathList(EventPathList::Parser & aEventPathListParser); @@ -141,9 +161,6 @@ class ReadHandler : public Messaging::ExchangeDelegate const char * GetStateStr() const; - // Merges aAttributePath inside the existing internal mpAttributeClusterInfoList - bool MergeOverlappedAttributePath(ClusterInfo & aAttributePath); - Messaging::ExchangeContext * mpExchangeCtx = nullptr; // Don't need the response for report data if true @@ -164,6 +181,13 @@ class ReadHandler : public Messaging::ExchangeDelegate Messaging::ExchangeManager * mpExchangeMgr = nullptr; InteractionModelDelegate * mpDelegate = nullptr; bool mInitialReport = false; + InteractionType mInteractionType = InteractionType::Read; + uint64_t mSubscriptionId = 0; + uint16_t mMinIntervalFloorSeconds = 0; + uint16_t mMaxIntervalCeilingSeconds = 0; + Optional mSessionHandle; + bool mHoldReport = false; + bool mDirty = false; }; } // namespace app } // namespace chip diff --git a/src/app/ReadPrepareParams.h b/src/app/ReadPrepareParams.h index 9740ac29d38ab5..e41c3b7d51a133 100644 --- a/src/app/ReadPrepareParams.h +++ b/src/app/ReadPrepareParams.h @@ -36,8 +36,8 @@ struct ReadPrepareParams size_t mAttributePathParamsListSize = 0; EventNumber mEventNumber = 0; uint32_t mTimeout = kImMessageTimeoutMsec; - uint16_t mMinIntervalSeconds = 0; - uint16_t mMaxIntervalSeconds = 0; + uint16_t mMinIntervalFloorSeconds = 0; + uint16_t mMaxIntervalCeilingSeconds = 0; ReadPrepareParams(SessionHandle sessionHandle) : mSessionHandle(sessionHandle) {} ReadPrepareParams(ReadPrepareParams && other) : mSessionHandle(other.mSessionHandle) @@ -47,8 +47,8 @@ struct ReadPrepareParams mpAttributePathParamsList = other.mpAttributePathParamsList; mAttributePathParamsListSize = other.mAttributePathParamsListSize; mEventNumber = other.mEventNumber; - mMinIntervalSeconds = other.mMinIntervalSeconds; - mMaxIntervalSeconds = other.mMaxIntervalSeconds; + mMinIntervalFloorSeconds = other.mMinIntervalFloorSeconds; + mMaxIntervalCeilingSeconds = other.mMaxIntervalCeilingSeconds; mTimeout = other.mTimeout; other.mpEventPathParamsList = nullptr; other.mEventPathParamsListSize = 0; @@ -67,8 +67,8 @@ struct ReadPrepareParams mpAttributePathParamsList = other.mpAttributePathParamsList; mAttributePathParamsListSize = other.mAttributePathParamsListSize; mEventNumber = other.mEventNumber; - mMinIntervalSeconds = other.mMinIntervalSeconds; - mMaxIntervalSeconds = other.mMaxIntervalSeconds; + mMinIntervalFloorSeconds = other.mMinIntervalFloorSeconds; + mMaxIntervalCeilingSeconds = other.mMaxIntervalCeilingSeconds; mTimeout = other.mTimeout; other.mpEventPathParamsList = nullptr; other.mEventPathParamsListSize = 0; diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index 804171b4f56708..02788e8928c3fd 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -38,6 +38,15 @@ CHIP_ERROR Engine::Init() return CHIP_NO_ERROR; } +void Engine::Shutdown() +{ + mMoreChunkedMessages = false; + mNumReportsInFlight = 0; + mCurReadHandlerIdx = 0; + InteractionModelEngine::GetInstance()->ReleaseClusterInfoList(mpGlobalDirtySet); + mpGlobalDirtySet = nullptr; +} + EventNumber Engine::CountEvents(ReadHandler * apReadHandler, EventNumber * apInitialEvents) { EventNumber event_count = 0; @@ -76,8 +85,6 @@ Engine::RetrieveClusterData(AttributeDataList::Builder & aAttributeDataList, Clu err = attributeDataElementBuilder.GetError(); exit: - aClusterInfo.ClearDirty(); - if (err != CHIP_NO_ERROR) { ChipLogError(DataManagement, "Error retrieving data from clusterId: " ChipLogFormatMEI ", err = %" CHIP_ERROR_FORMAT, @@ -89,29 +96,46 @@ Engine::RetrieveClusterData(AttributeDataList::Builder & aAttributeDataList, Clu CHIP_ERROR Engine::BuildSingleReportDataAttributeDataList(ReportData::Builder & aReportDataBuilder, ReadHandler * apReadHandler) { - CHIP_ERROR err = CHIP_NO_ERROR; - ClusterInfo * clusterInfo = apReadHandler->GetAttributeClusterInfolist(); - bool attributeClean = true; + CHIP_ERROR err = CHIP_NO_ERROR; + bool attributeClean = true; TLV::TLVWriter backup; aReportDataBuilder.Checkpoint(backup); AttributeDataList::Builder attributeDataList = aReportDataBuilder.CreateAttributeDataListBuilder(); SuccessOrExit(err = aReportDataBuilder.GetError()); // TODO: Need to handle multiple chunk of message - while (clusterInfo != nullptr) + for (auto clusterInfo = apReadHandler->GetAttributeClusterInfolist(); clusterInfo != nullptr; clusterInfo = clusterInfo->mpNext) { - if (clusterInfo->IsDirty()) + if (apReadHandler->IsInitialReport()) + { + // Retrieve data for this cluster instance and clear its dirty flag. + err = RetrieveClusterData(attributeDataList, *clusterInfo); + VerifyOrExit(err == CHIP_NO_ERROR, + ChipLogError(DataManagement, " Error retrieving data from cluster, aborting")); + attributeClean = false; + } + else { - if (apReadHandler->IsInitialReport()) + for (auto path = mpGlobalDirtySet; path != nullptr; path = path->mpNext) { - // Retrieve data for this cluster instance and clear its dirty flag. - err = RetrieveClusterData(attributeDataList, *clusterInfo); + if (clusterInfo->IsAttributePathSupersetOf(*path)) + { + err = RetrieveClusterData(attributeDataList, *path); + } + else if (path->IsAttributePathSupersetOf(*clusterInfo)) + { + err = RetrieveClusterData(attributeDataList, *clusterInfo); + } + else + { + // partial overlap is not possible, hence the 'continue' here: clusterInfo and path have nothing in + // common. + continue; + } VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(DataManagement, " Error retrieving data from cluster, aborting")); attributeClean = false; } - clusterInfo->ClearDirty(); } - clusterInfo = clusterInfo->mpNext; } attributeDataList.EndOfAttributeDataList(); err = attributeDataList.GetError(); @@ -242,6 +266,13 @@ CHIP_ERROR Engine::BuildAndSendSingleReportData(ReadHandler * apReadHandler) err = reportDataBuilder.Init(&reportDataWriter); SuccessOrExit(err); + if (apReadHandler->IsSubscriptionType()) + { + uint64_t subscriptionId = 0; + apReadHandler->GetSubscriptionId(subscriptionId); + reportDataBuilder.SubscriptionId(subscriptionId); + } + err = BuildSingleReportDataAttributeDataList(reportDataBuilder, apReadHandler); SuccessOrExit(err); @@ -333,6 +364,66 @@ void Engine::Run() mCurReadHandlerIdx = (mCurReadHandlerIdx + 1) % CHIP_IM_MAX_NUM_READ_HANDLER; readHandler = imEngine->mReadHandlers + mCurReadHandlerIdx; } + + bool allReadClean = true; + for (auto & handler : InteractionModelEngine::GetInstance()->mReadHandlers) + { + UpdateReadHandlerDirty(handler); + if (handler.IsDirty()) + { + allReadClean = false; + break; + } + } + + if (allReadClean) + { + InteractionModelEngine::GetInstance()->ReleaseClusterInfoList(mpGlobalDirtySet); + } +} + +CHIP_ERROR Engine::SetDirty(ClusterInfo & aClusterInfo) +{ + for (auto & handler : InteractionModelEngine::GetInstance()->mReadHandlers) + { + if (handler.IsSubscriptionType() && (handler.IsGeneratingReports() || handler.IsAwaitingReportResponse())) + { + handler.SetDirty(); + } + } + if (!InteractionModelEngine::GetInstance()->MergeOverlappedAttributePath(mpGlobalDirtySet, aClusterInfo) && + InteractionModelEngine::GetInstance()->IsOverlappedAttributePath(aClusterInfo)) + { + ReturnLogErrorOnFailure(InteractionModelEngine::GetInstance()->PushFront(mpGlobalDirtySet, aClusterInfo)); + } + return CHIP_NO_ERROR; +} + +void Engine::UpdateReadHandlerDirty(ReadHandler & aReadHandler) +{ + if (!aReadHandler.IsDirty()) + { + return; + } + if (!aReadHandler.IsSubscriptionType()) + { + return; + } + for (auto clusterInfo = aReadHandler.GetAttributeClusterInfolist(); clusterInfo != nullptr; clusterInfo = clusterInfo->mpNext) + { + bool intersected = false; + for (auto path = mpGlobalDirtySet; path != nullptr; path = path->mpNext) + { + if (path->IsAttributePathSupersetOf(*clusterInfo) || clusterInfo->IsAttributePathSupersetOf(*path)) + { + intersected = true; + } + } + if (!intersected) + { + aReadHandler.ClearDirty(); + } + } } CHIP_ERROR Engine::SendReport(ReadHandler * apReadHandler, System::PacketBufferHandle && aPayload) @@ -341,7 +432,6 @@ CHIP_ERROR Engine::SendReport(ReadHandler * apReadHandler, System::PacketBufferH // We can only have 1 report in flight for any given read - increment and break out. mNumReportsInFlight++; - err = apReadHandler->SendReportData(std::move(aPayload)); return err; } diff --git a/src/app/reporting/Engine.h b/src/app/reporting/Engine.h index 4fcda1f2f98f60..bcd6547c81a330 100644 --- a/src/app/reporting/Engine.h +++ b/src/app/reporting/Engine.h @@ -60,6 +60,8 @@ class Engine */ CHIP_ERROR Init(); + void Shutdown(); + /** * Main work-horse function that executes the run-loop. */ @@ -77,6 +79,11 @@ class Engine */ CHIP_ERROR ScheduleRun(); + /** + * Application marks mutated change path and would be sent out in later report. + */ + CHIP_ERROR SetDirty(ClusterInfo & aClusterInfo); + private: friend class TestReportingEngine; /** @@ -90,6 +97,12 @@ class Engine CHIP_ERROR RetrieveClusterData(AttributeDataList::Builder & aAttributeDataList, ClusterInfo & aClusterInfo); EventNumber CountEvents(ReadHandler * apReadHandler, EventNumber * apInitialEvents); + /** + * Check all active subscription, if the subscription has no paths that intersect with global dirty set, + * it would clear dirty flag for that subscription + * + */ + void UpdateReadHandlerDirty(ReadHandler & aReadHandler); /** * Send Report via ReadHandler * @@ -119,6 +132,15 @@ class Engine * */ uint32_t mCurReadHandlerIdx = 0; + + /** + * mpGlobalDirtySet is used to track the dirty cluster info application modified for attributes during + * post-subscription via SetDirty API, and further form the report. This reporting engine acquires this global dirty + * set from mClusterInfoPool managed by InteractionModelEngine, where all active read handlers also acquire the interested + * cluster Info list from mClusterInfoPool. + * + */ + ClusterInfo * mpGlobalDirtySet = nullptr; }; }; // namespace reporting diff --git a/src/app/reporting/reporting.cpp b/src/app/reporting/reporting.cpp index 78807d0e1ea348..9c9873d78b2f10 100644 --- a/src/app/reporting/reporting.cpp +++ b/src/app/reporting/reporting.cpp @@ -694,53 +694,6 @@ EmberStatus emAfPluginReportingRemoveEntry(uint8_t index) return status; } -void emberAfReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId, uint8_t mask, - uint16_t manufacturerCode, EmberAfAttributeType type, uint8_t * data) -{ - uint8_t i; - for (i = 0; i < REPORT_TABLE_SIZE; i++) - { - EmberAfPluginReportingEntry entry; - emAfPluginReportingGetEntry(i, &entry); - if (entry.endpoint == EMBER_AF_PLUGIN_REPORTING_UNUSED_ENDPOINT_ID) - { - continue; - } - if (entry.direction == EMBER_ZCL_REPORTING_DIRECTION_REPORTED && entry.endpoint == endpoint && - entry.clusterId == clusterId && entry.attributeId == attributeId && entry.mask == mask && - entry.manufacturerCode == manufacturerCode) - { - // For CHAR and OCTET strings, the string value may be too long to fit into the - // lastReportValue field (EmberAfDifferenceType), so instead we save the string's - // hash, and detect changes in string value based on unequal hash. - uint32_t stringHash = 0; - uint8_t dataSize = emberAfGetDataSize(type); - uint8_t * dataRef = data; - if (type == ZCL_OCTET_STRING_ATTRIBUTE_TYPE || type == ZCL_CHAR_STRING_ATTRIBUTE_TYPE) - { - stringHash = computeStringHash(data + 1, emberAfStringLength(data)); - dataRef = (uint8_t *) &stringHash; - dataSize = sizeof(stringHash); - } - // If we are reporting this particular attribute, we only care whether - // the new value meets the reportable change criteria. If it does, we - // mark the entry as ready to report and reschedule the tick. Whether - // the tick will be scheduled for immediate or delayed execution depends - // on the minimum reporting interval. This is handled in the scheduler. - EmberAfDifferenceType difference = - emberAfGetDifference(dataRef, emAfPluginReportVolatileData[i].lastReportValue, dataSize); - uint8_t analogOrDiscrete = emberAfGetAttributeAnalogOrDiscreteType(type); - if ((analogOrDiscrete == EMBER_AF_DATA_TYPE_DISCRETE && difference != 0) || - (analogOrDiscrete == EMBER_AF_DATA_TYPE_ANALOG && entry.data.reported.reportableChange <= difference)) - { - emAfPluginReportVolatileData[i].reportableChange = true; - scheduleTick(); - } - break; - } - } -} - bool emAfPluginReportingDoEntriesMatch(const EmberAfPluginReportingEntry * const entry1, const EmberAfPluginReportingEntry * const entry2) { diff --git a/src/app/reporting/reporting.h b/src/app/reporting/reporting.h index 2ab9de71710283..27cbac7daac870 100644 --- a/src/app/reporting/reporting.h +++ b/src/app/reporting/reporting.h @@ -129,3 +129,6 @@ EmberStatus emberAfClearReportTableCallback(void); */ void emberAfReportingAttributeChangeCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t mask, uint16_t manufacturerCode, EmberAfAttributeType type, uint8_t * data); +void InteractionModelReportingAttributeChangeCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, + chip::AttributeId attributeId, uint8_t mask, uint16_t manufacturerCode, + EmberAfAttributeType type, uint8_t * data); diff --git a/src/app/tests/TestCHIPDeviceCallbacksMgr.cpp b/src/app/tests/TestCHIPDeviceCallbacksMgr.cpp index 836d0de5e49620..52b43c1cb19203 100644 --- a/src/app/tests/TestCHIPDeviceCallbacksMgr.cpp +++ b/src/app/tests/TestCHIPDeviceCallbacksMgr.cpp @@ -313,42 +313,54 @@ void ShouldGetSingleReportCallback(nlTestSuite * testSuite, void * apContext) NL_TEST_ASSERT(context.testSuite, false); }; + const auto reportFilter = [](TLV::TLVReader * reader, Callback::Cancelable * callback, Callback::Cancelable * failureCallback) { + IgnoreUnusedVariable(reader); + IgnoreUnusedVariable(callback); + IgnoreUnusedVariable(failureCallback); + }; + Callback::Callback reportCallback{ onReport, &callbackContext }; { Callback::Cancelable * reportCancelable = nullptr; + TLVDataFilter filter = nullptr; CHIP_ERROR error = - callbacks.GetReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, &reportCancelable); + callbacks.GetReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, &reportCancelable, &filter); NL_TEST_ASSERT(testSuite, error == CHIP_ERROR_KEY_NOT_FOUND); NL_TEST_ASSERT(testSuite, reportCancelable == nullptr); + NL_TEST_ASSERT(testSuite, filter == nullptr); } { - CHIP_ERROR error = - callbacks.AddReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, reportCallback.Cancel()); + CHIP_ERROR error = callbacks.AddReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, + reportCallback.Cancel(), reportFilter); NL_TEST_ASSERT(testSuite, error == CHIP_NO_ERROR); } { Callback::Cancelable * reportCancelable = nullptr; + TLVDataFilter filter = nullptr; CHIP_ERROR error = - callbacks.GetReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, &reportCancelable); + callbacks.GetReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, &reportCancelable, &filter); NL_TEST_ASSERT(testSuite, error == CHIP_NO_ERROR); auto outReportCallback = decltype(reportCallback)::FromCancelable(reportCancelable); NL_TEST_ASSERT(testSuite, outReportCallback == &reportCallback); + NL_TEST_ASSERT(testSuite, filter == reportFilter); } { Callback::Cancelable * reportCancelable = nullptr; + TLVDataFilter filter = nullptr; CHIP_ERROR error = - callbacks.GetReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, &reportCancelable); + callbacks.GetReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, &reportCancelable, &filter); NL_TEST_ASSERT(testSuite, error == CHIP_NO_ERROR); auto outReportCallback = decltype(reportCallback)::FromCancelable(reportCancelable); NL_TEST_ASSERT(testSuite, outReportCallback == &reportCallback); + NL_TEST_ASSERT(testSuite, filter == reportFilter); } } @@ -373,41 +385,53 @@ void ShouldFailGetCanceledReportCallback(nlTestSuite * testSuite, void * apConte NL_TEST_ASSERT(context.testSuite, false); }; + const auto reportFilter = [](TLV::TLVReader * reader, Callback::Cancelable * callback, Callback::Cancelable * failureCallback) { + IgnoreUnusedVariable(reader); + IgnoreUnusedVariable(callback); + IgnoreUnusedVariable(failureCallback); + }; + Callback::Callback reportCallback{ onReport, &callbackContext }; { Callback::Cancelable * reportCancelable = nullptr; + TLVDataFilter filter = nullptr; CHIP_ERROR error = - callbacks.GetReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, &reportCancelable); + callbacks.GetReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, &reportCancelable, &filter); NL_TEST_ASSERT(testSuite, error == CHIP_ERROR_KEY_NOT_FOUND); NL_TEST_ASSERT(testSuite, reportCancelable == nullptr); + NL_TEST_ASSERT(testSuite, filter == nullptr); } { - CHIP_ERROR error = - callbacks.AddReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, reportCallback.Cancel()); + CHIP_ERROR error = callbacks.AddReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, + reportCallback.Cancel(), reportFilter); NL_TEST_ASSERT(testSuite, error == CHIP_NO_ERROR); } { Callback::Cancelable * reportCancelable = nullptr; + TLVDataFilter filter = nullptr; CHIP_ERROR error = - callbacks.GetReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, &reportCancelable); + callbacks.GetReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, &reportCancelable, &filter); NL_TEST_ASSERT(testSuite, error == CHIP_NO_ERROR); auto outReportCallback = decltype(reportCallback)::FromCancelable(reportCancelable); NL_TEST_ASSERT(testSuite, outReportCallback == &reportCallback); + NL_TEST_ASSERT(testSuite, filter == reportFilter); } reportCallback.Cancel(); { Callback::Cancelable * reportCancelable = nullptr; + TLVDataFilter filter = nullptr; CHIP_ERROR error = - callbacks.GetReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, &reportCancelable); + callbacks.GetReportCallback(kTestNodeId, kTestEndpointId, kTestClusterId, kTestAttributeId, &reportCancelable, &filter); NL_TEST_ASSERT(testSuite, error == CHIP_ERROR_KEY_NOT_FOUND); NL_TEST_ASSERT(testSuite, reportCancelable == nullptr); + NL_TEST_ASSERT(testSuite, filter == nullptr); } } diff --git a/src/app/tests/TestClusterInfo.cpp b/src/app/tests/TestClusterInfo.cpp index 22a1c94bcac64f..932fe062104e72 100644 --- a/src/app/tests/TestClusterInfo.cpp +++ b/src/app/tests/TestClusterInfo.cpp @@ -29,15 +29,6 @@ namespace chip { namespace app { namespace TestClusterInfo { -void TestDirty(nlTestSuite * apSuite, void * apContext) -{ - ClusterInfo clusterInfo1; - clusterInfo1.SetDirty(); - NL_TEST_ASSERT(apSuite, clusterInfo1.IsDirty()); - clusterInfo1.ClearDirty(); - NL_TEST_ASSERT(apSuite, !clusterInfo1.IsDirty()); -} - void TestAttributePathIncludedSameFieldId(nlTestSuite * apSuite, void * apContext) { ClusterInfo clusterInfo1; @@ -104,7 +95,6 @@ void TestAttributePathIncludedDifferentClusterId(nlTestSuite * apSuite, void * a namespace { const nlTest sTests[] = { - NL_TEST_DEF("TestDirty", chip::app::TestClusterInfo::TestDirty), NL_TEST_DEF("TestAttributePathIncludedSameFieldId", chip::app::TestClusterInfo::TestAttributePathIncludedSameFieldId), NL_TEST_DEF("TestAttributePathIncludedDifferentFieldId", chip::app::TestClusterInfo::TestAttributePathIncludedDifferentFieldId), NL_TEST_DEF("TestAttributePathIncludedDifferentEndpointId", diff --git a/src/app/tests/TestInteractionModelEngine.cpp b/src/app/tests/TestInteractionModelEngine.cpp index 321fedf918d240..4c4d7507cfd90e 100644 --- a/src/app/tests/TestInteractionModelEngine.cpp +++ b/src/app/tests/TestInteractionModelEngine.cpp @@ -57,6 +57,7 @@ class TestInteractionModelEngine { public: static void TestClusterInfoPushRelease(nlTestSuite * apSuite, void * apContext); + static void TestMergeOverlappedAttributePath(nlTestSuite * apSuite, void * apContext); static int GetClusterInfoListLength(ClusterInfo * apClusterInfoList); }; @@ -101,6 +102,31 @@ void TestInteractionModelEngine::TestClusterInfoPushRelease(nlTestSuite * apSuit InteractionModelEngine::GetInstance()->ReleaseClusterInfoList(clusterInfoList); NL_TEST_ASSERT(apSuite, GetClusterInfoListLength(clusterInfoList) == 0); } + +void TestInteractionModelEngine::TestMergeOverlappedAttributePath(nlTestSuite * apSuite, void * apContext) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + err = InteractionModelEngine::GetInstance()->Init(&gExchangeManager, nullptr); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + ClusterInfo clusterInfoList[2]; + + clusterInfoList[0].mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); + clusterInfoList[0].mFieldId = 1; + clusterInfoList[1].mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); + clusterInfoList[1].mFieldId = 2; + + chip::app::ClusterInfo testClusterInfo; + testClusterInfo.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); + testClusterInfo.mFieldId = 3; + + NL_TEST_ASSERT(apSuite, !InteractionModelEngine::GetInstance()->MergeOverlappedAttributePath(clusterInfoList, testClusterInfo)); + testClusterInfo.mFieldId = 0xFFFFFFFF; + NL_TEST_ASSERT(apSuite, InteractionModelEngine::GetInstance()->MergeOverlappedAttributePath(clusterInfoList, testClusterInfo)); + testClusterInfo.mFlags.Set(chip::app::ClusterInfo::Flags::kListIndexValid); + testClusterInfo.mFieldId = 1; + testClusterInfo.mListIndex = 2; + NL_TEST_ASSERT(apSuite, InteractionModelEngine::GetInstance()->MergeOverlappedAttributePath(clusterInfoList, testClusterInfo)); +} } // namespace app } // namespace chip @@ -130,6 +156,7 @@ void InitializeChip(nlTestSuite * apSuite) const nlTest sTests[] = { NL_TEST_DEF("TestClusterInfoPushRelease", chip::app::TestInteractionModelEngine::TestClusterInfoPushRelease), + NL_TEST_DEF("TestMergeOverlappedAttributePath", chip::app::TestInteractionModelEngine::TestMergeOverlappedAttributePath), NL_TEST_SENTINEL() }; // clang-format on diff --git a/src/app/tests/TestMessageDef.cpp b/src/app/tests/TestMessageDef.cpp index e4d9d75254a2df..178f8137d25f47 100644 --- a/src/app/tests/TestMessageDef.cpp +++ b/src/app/tests/TestMessageDef.cpp @@ -981,7 +981,10 @@ void BuildSubscribeResponse(nlTestSuite * apSuite, chip::TLV::TLVWriter & aWrite subscribeResponseBuilder.SubscriptionId(1); NL_TEST_ASSERT(apSuite, subscribeResponseBuilder.GetError() == CHIP_NO_ERROR); - subscribeResponseBuilder.FinalSyncIntervalSeconds(1); + subscribeResponseBuilder.MinIntervalFloorSeconds(1); + NL_TEST_ASSERT(apSuite, subscribeResponseBuilder.GetError() == CHIP_NO_ERROR); + + subscribeResponseBuilder.MaxIntervalCeilingSeconds(2); NL_TEST_ASSERT(apSuite, subscribeResponseBuilder.GetError() == CHIP_NO_ERROR); subscribeResponseBuilder.EndOfSubscribeResponse(); @@ -993,10 +996,10 @@ void ParseSubscribeResponse(nlTestSuite * apSuite, chip::TLV::TLVReader & aReade CHIP_ERROR err = CHIP_NO_ERROR; SubscribeResponse::Parser subscribeResponseParser; - uint64_t subscriptionId = 0; - uint16_t finalSyncIntervalSeconds = 0; - - err = subscribeResponseParser.Init(aReader); + uint64_t subscriptionId = 0; + uint16_t minIntervalFloorSeconds = 0; + uint16_t maxIntervalCeilingSeconds = 0; + err = subscribeResponseParser.Init(aReader); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK err = subscribeResponseParser.CheckSchemaValidity(); @@ -1005,8 +1008,11 @@ void ParseSubscribeResponse(nlTestSuite * apSuite, chip::TLV::TLVReader & aReade err = subscribeResponseParser.GetSubscriptionId(&subscriptionId); NL_TEST_ASSERT(apSuite, subscriptionId == 1 && err == CHIP_NO_ERROR); - err = subscribeResponseParser.GetFinalSyncIntervalSeconds(&finalSyncIntervalSeconds); - NL_TEST_ASSERT(apSuite, finalSyncIntervalSeconds == 1 && err == CHIP_NO_ERROR); + err = subscribeResponseParser.GetMinIntervalFloorSeconds(&minIntervalFloorSeconds); + NL_TEST_ASSERT(apSuite, minIntervalFloorSeconds == 1 && err == CHIP_NO_ERROR); + + err = subscribeResponseParser.GetMaxIntervalCeilingSeconds(&maxIntervalCeilingSeconds); + NL_TEST_ASSERT(apSuite, maxIntervalCeilingSeconds == 2 && err == CHIP_NO_ERROR); } void BuildTimedRequest(nlTestSuite * apSuite, chip::TLV::TLVWriter & aWriter) diff --git a/src/app/tests/TestReadInteraction.cpp b/src/app/tests/TestReadInteraction.cpp index be52e93a774dcf..88873b23aae49d 100644 --- a/src/app/tests/TestReadInteraction.cpp +++ b/src/app/tests/TestReadInteraction.cpp @@ -117,6 +117,33 @@ void GenerateEvents(nlTestSuite * apSuite, void * apContext) NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); } +void GenerateSubscribeResponse(nlTestSuite * apSuite, void * apContext, chip::System::PacketBufferHandle && aPayload) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + chip::System::PacketBufferTLVWriter writer; + writer.Init(std::move(aPayload)); + + chip::app::SubscribeResponse::Builder subscribeResponseBuilder; + + err = subscribeResponseBuilder.Init(&writer); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + subscribeResponseBuilder.SubscriptionId(0); + NL_TEST_ASSERT(apSuite, subscribeResponseBuilder.GetError() == CHIP_NO_ERROR); + + subscribeResponseBuilder.MinIntervalFloorSeconds(1); + NL_TEST_ASSERT(apSuite, subscribeResponseBuilder.GetError() == CHIP_NO_ERROR); + + subscribeResponseBuilder.MaxIntervalCeilingSeconds(2); + NL_TEST_ASSERT(apSuite, subscribeResponseBuilder.GetError() == CHIP_NO_ERROR); + + subscribeResponseBuilder.EndOfSubscribeResponse(); + NL_TEST_ASSERT(apSuite, subscribeResponseBuilder.GetError() == CHIP_NO_ERROR); + + err = writer.Finalize(&aPayload); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); +} + class MockInteractionModelApp : public chip::app::InteractionModelDelegate { public: @@ -176,10 +203,17 @@ class MockInteractionModelApp : public chip::app::InteractionModelDelegate CHIP_ERROR ReadDone(const chip::app::ReadClient * apReadClient) override { return CHIP_NO_ERROR; } - bool mGotEventResponse = false; - int mNumAttributeResponse = 0; - bool mGotReport = false; - bool mReadError = false; + CHIP_ERROR SubscriptionEstablished(const chip::app::ReadHandler * apReadHandler) override + { + mpReadHandler = const_cast(apReadHandler); + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + bool mGotEventResponse = false; + int mNumAttributeResponse = 0; + bool mGotReport = false; + bool mReadError = false; + chip::app::ReadHandler * mpReadHandler = nullptr; }; } // namespace @@ -190,32 +224,24 @@ CHIP_ERROR ReadSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVWriter * ap uint64_t version = 0; ChipLogDetail(DataManagement, "TEST Cluster %" PRIx32 ", Field %" PRIx32 " is dirty", aClusterInfo.mClusterId, aClusterInfo.mFieldId); + + if (apDataExists != nullptr) + { + *apDataExists = (aClusterInfo.mClusterId == kTestClusterId && aClusterInfo.mEndpointId == kTestEndpointId); + } + if (apWriter == nullptr) { - return CHIP_ERROR_INVALID_ARGUMENT; + return CHIP_NO_ERROR; } if (!(aClusterInfo.mClusterId == kTestClusterId && aClusterInfo.mEndpointId == kTestEndpointId)) { - if (apDataExists != nullptr) - { - *apDataExists = false; - } - return apWriter->Put(chip::TLV::ContextTag(AttributeDataElement::kCsTag_Status), chip::Protocols::InteractionModel::ProtocolCode::UnsupportedAttribute); } - if (apDataExists != nullptr) - { - *apDataExists = true; - } - - CHIP_ERROR err = apWriter->Put(TLV::ContextTag(AttributeDataElement::kCsTag_Data), kTestFieldValue1); - if (err != CHIP_NO_ERROR) - { - return err; - } + ReturnErrorOnFailure(apWriter->Put(TLV::ContextTag(AttributeDataElement::kCsTag_Data), kTestFieldValue1)); return apWriter->Put(TLV::ContextTag(AttributeDataElement::kCsTag_DataVersion), version); } @@ -230,7 +256,11 @@ class TestReadInteraction static void TestReadClientGenerateTwoEventPathList(nlTestSuite * apSuite, void * apContext); static void TestReadClientInvalidReport(nlTestSuite * apSuite, void * apContext); static void TestReadHandlerInvalidAttributePath(nlTestSuite * apSuite, void * apContext); + static void TestProcessSubscribeResponse(nlTestSuite * apSuite, void * apContext); + static void TestProcessSubscribeRequest(nlTestSuite * apSuite, void * apContext); static void TestReadRoundtrip(nlTestSuite * apSuite, void * apContext); + static void TestSubscribeRoundtrip(nlTestSuite * apSuite, void * apContext); + static void TestSubscribeInvalidAttributePathRoundtrip(nlTestSuite * apSuite, void * apContext); static void TestReadInvalidAttributePathRoundtrip(nlTestSuite * apSuite, void * apContext); private: @@ -320,7 +350,8 @@ void TestReadInteraction::TestReadClient(nlTestSuite * apSuite, void * apContext app::ReadClient readClient; chip::app::InteractionModelDelegate delegate; System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); - err = readClient.Init(&ctx.GetExchangeManager(), &delegate, 0 /* application identifier */); + err = readClient.Init(&ctx.GetExchangeManager(), &delegate, chip::app::ReadClient::InteractionType::Read, + 0 /* application identifier */); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice()); err = readClient.SendReadRequest(readPrepareParams); @@ -347,8 +378,9 @@ void TestReadInteraction::TestReadHandler(nlTestSuite * apSuite, void * apContex auto * engine = chip::app::InteractionModelEngine::GetInstance(); err = engine->Init(&ctx.GetExchangeManager(), &delegate); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + Messaging::ExchangeContext * exchangeCtx = ctx.NewExchangeToAlice(nullptr); - readHandler.Init(&ctx.GetExchangeManager(), nullptr, exchangeCtx); + readHandler.Init(&ctx.GetExchangeManager(), nullptr, exchangeCtx, chip::app::ReadHandler::InteractionType::Read); GenerateReportData(apSuite, apContext, reportDatabuf); err = readHandler.SendReportData(std::move(reportDatabuf)); @@ -400,7 +432,8 @@ void TestReadInteraction::TestReadClientGenerateAttributePathList(nlTestSuite * err = request.Init(&writer); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - err = readClient.Init(&ctx.GetExchangeManager(), &delegate, 0 /* application identifier */); + err = readClient.Init(&ctx.GetExchangeManager(), &delegate, chip::app::ReadClient::InteractionType::Read, + 0 /* application identifier */); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); AttributePathParams attributePathParams[2]; @@ -424,7 +457,8 @@ void TestReadInteraction::TestReadClientGenerateInvalidAttributePathList(nlTestS msgBuf = System::PacketBufferHandle::New(kMaxSecureSduLengthBytes); NL_TEST_ASSERT(apSuite, !msgBuf.IsNull()); writer.Init(std::move(msgBuf)); - err = readClient.Init(&ctx.GetExchangeManager(), &delegate, 0 /* application identifier */); + err = readClient.Init(&ctx.GetExchangeManager(), &delegate, chip::app::ReadClient::InteractionType::Read, + 0 /* application identifier */); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); err = request.Init(&writer); @@ -446,7 +480,8 @@ void TestReadInteraction::TestReadClientInvalidReport(nlTestSuite * apSuite, voi chip::app::InteractionModelDelegate delegate; System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); - err = readClient.Init(&ctx.GetExchangeManager(), &delegate, 0 /* application identifier */); + err = readClient.Init(&ctx.GetExchangeManager(), &delegate, chip::app::ReadClient::InteractionType::Read, + 0 /* application identifier */); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice()); @@ -475,8 +510,9 @@ void TestReadInteraction::TestReadHandlerInvalidAttributePath(nlTestSuite * apSu auto * engine = chip::app::InteractionModelEngine::GetInstance(); err = engine->Init(&ctx.GetExchangeManager(), &delegate); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + Messaging::ExchangeContext * exchangeCtx = ctx.NewExchangeToAlice(nullptr); - readHandler.Init(&ctx.GetExchangeManager(), nullptr, exchangeCtx); + readHandler.Init(&ctx.GetExchangeManager(), nullptr, exchangeCtx, chip::app::ReadHandler::InteractionType::Read); GenerateReportData(apSuite, apContext, reportDatabuf); err = readHandler.SendReportData(std::move(reportDatabuf)); @@ -524,7 +560,8 @@ void TestReadInteraction::TestReadClientGenerateOneEventPathList(nlTestSuite * a err = request.Init(&writer); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - err = readClient.Init(&ctx.GetExchangeManager(), &delegate, 0 /* application identifier */); + err = readClient.Init(&ctx.GetExchangeManager(), &delegate, chip::app::ReadClient::InteractionType::Read, + 0 /* application identifier */); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); chip::app::EventPathParams eventPathParams[2]; @@ -573,7 +610,8 @@ void TestReadInteraction::TestReadClientGenerateTwoEventPathList(nlTestSuite * a err = request.Init(&writer); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - err = readClient.Init(&ctx.GetExchangeManager(), &delegate, 0 /* application identifier */); + err = readClient.Init(&ctx.GetExchangeManager(), &delegate, chip::app::ReadClient::InteractionType::Read, + 0 /* application identifier */); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); chip::app::EventPathParams eventPathParams[2]; @@ -651,7 +689,7 @@ void TestReadInteraction::TestReadRoundtrip(nlTestSuite * apSuite, void * apCont attributePathParams[1].mNodeId = chip::kTestDeviceNodeId; attributePathParams[1].mEndpointId = kTestEndpointId; attributePathParams[1].mClusterId = kTestClusterId; - attributePathParams[1].mFieldId = 1; + attributePathParams[1].mFieldId = 2; attributePathParams[1].mListIndex = 1; attributePathParams[1].mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); attributePathParams[1].mFlags.Set(chip::app::AttributePathParams::Flags::kListIndexValid); @@ -666,7 +704,7 @@ void TestReadInteraction::TestReadRoundtrip(nlTestSuite * apSuite, void * apCont InteractionModelEngine::GetInstance()->GetReportingEngine().Run(); NL_TEST_ASSERT(apSuite, delegate.mGotEventResponse); - NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 1); + NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2); NL_TEST_ASSERT(apSuite, delegate.mGotReport); NL_TEST_ASSERT(apSuite, !delegate.mReadError); // By now we should have closed all exchanges and sent all pending acks, so @@ -716,6 +754,330 @@ void TestReadInteraction::TestReadInvalidAttributePathRoundtrip(nlTestSuite * ap engine->Shutdown(); } + +void TestReadInteraction::TestProcessSubscribeResponse(nlTestSuite * apSuite, void * apContext) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + TestContext & ctx = *static_cast(apContext); + app::ReadClient readClient; + chip::app::InteractionModelDelegate delegate; + System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); + err = readClient.Init(&ctx.GetExchangeManager(), &delegate, chip::app::ReadClient::InteractionType::Subscribe, + 0 /* application identifier */); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + readClient.MoveToState(chip::app::ReadClient::ClientState::AwaitingSubscribeResponse); + + GenerateSubscribeResponse(apSuite, apContext, buf.Retain()); + + err = readClient.ProcessSubscribeResponse(std::move(buf)); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + readClient.ShutdownInternal(CHIP_NO_ERROR); +} + +void TestReadInteraction::TestProcessSubscribeRequest(nlTestSuite * apSuite, void * apContext) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + TestContext & ctx = *static_cast(apContext); + app::ReadHandler readHandler; + System::PacketBufferTLVWriter writer; + System::PacketBufferHandle subscribeRequestbuf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); + SubscribeRequest::Builder subscribeRequestBuilder; + chip::app::InteractionModelDelegate delegate; + auto * engine = chip::app::InteractionModelEngine::GetInstance(); + err = engine->Init(&ctx.GetExchangeManager(), &delegate); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + Messaging::ExchangeContext * exchangeCtx = ctx.NewExchangeToAlice(nullptr); + readHandler.Init(&ctx.GetExchangeManager(), nullptr, exchangeCtx, chip::app::ReadHandler::InteractionType::Subscribe); + + writer.Init(std::move(subscribeRequestbuf)); + err = subscribeRequestBuilder.Init(&writer); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + AttributePathList::Builder attributePathListBuilder = subscribeRequestBuilder.CreateAttributePathListBuilder(); + NL_TEST_ASSERT(apSuite, attributePathListBuilder.GetError() == CHIP_NO_ERROR); + + AttributePath::Builder attributePathBuilder = attributePathListBuilder.CreateAttributePathBuilder(); + NL_TEST_ASSERT(apSuite, attributePathListBuilder.GetError() == CHIP_NO_ERROR); + + attributePathBuilder.NodeId(1).EndpointId(2).ClusterId(3).FieldId(4).ListIndex(5).EndOfAttributePath(); + err = attributePathBuilder.GetError(); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + attributePathListBuilder.EndOfAttributePathList(); + err = attributePathListBuilder.GetError(); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + subscribeRequestBuilder.MinIntervalSeconds(2); + NL_TEST_ASSERT(apSuite, subscribeRequestBuilder.GetError() == CHIP_NO_ERROR); + + subscribeRequestBuilder.MaxIntervalSeconds(3); + NL_TEST_ASSERT(apSuite, subscribeRequestBuilder.GetError() == CHIP_NO_ERROR); + + subscribeRequestBuilder.KeepExistingSubscriptions(true); + NL_TEST_ASSERT(apSuite, subscribeRequestBuilder.GetError() == CHIP_NO_ERROR); + + subscribeRequestBuilder.IsProxy(true); + NL_TEST_ASSERT(apSuite, subscribeRequestBuilder.GetError() == CHIP_NO_ERROR); + + subscribeRequestBuilder.EndOfSubscribeRequest(); + NL_TEST_ASSERT(apSuite, subscribeRequestBuilder.GetError() == CHIP_NO_ERROR); + + NL_TEST_ASSERT(apSuite, subscribeRequestBuilder.GetError() == CHIP_NO_ERROR); + err = writer.Finalize(&subscribeRequestbuf); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + err = readHandler.ProcessSubscribeRequest(std::move(subscribeRequestbuf)); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + exchangeCtx->Close(); + engine->Shutdown(); +} + +void TestReadInteraction::TestSubscribeRoundtrip(nlTestSuite * apSuite, void * apContext) +{ + TestContext & ctx = *static_cast(apContext); + CHIP_ERROR err = CHIP_NO_ERROR; + + Messaging::ReliableMessageMgr * rm = ctx.GetExchangeManager().GetReliableMessageMgr(); + // Shouldn't have anything in the retransmit table when starting the test. + NL_TEST_ASSERT(apSuite, rm->TestGetCountRetransTable() == 0); + + GenerateEvents(apSuite, apContext); + + MockInteractionModelApp delegate; + auto * engine = chip::app::InteractionModelEngine::GetInstance(); + err = engine->Init(&ctx.GetExchangeManager(), &delegate); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(apSuite, !delegate.mGotEventResponse); + + ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice()); + chip::app::EventPathParams eventPathParams[2]; + readPrepareParams.mpEventPathParamsList = eventPathParams; + readPrepareParams.mpEventPathParamsList[0].mNodeId = kTestNodeId; + readPrepareParams.mpEventPathParamsList[0].mEndpointId = kTestEndpointId; + readPrepareParams.mpEventPathParamsList[0].mClusterId = kTestClusterId; + readPrepareParams.mpEventPathParamsList[0].mEventId = kTestEventIdDebug; + + readPrepareParams.mpEventPathParamsList[1].mNodeId = kTestNodeId; + readPrepareParams.mpEventPathParamsList[1].mEndpointId = kTestEndpointId; + readPrepareParams.mpEventPathParamsList[1].mClusterId = kTestClusterId; + readPrepareParams.mpEventPathParamsList[1].mEventId = kTestEventIdCritical; + + readPrepareParams.mEventPathParamsListSize = 2; + + chip::app::AttributePathParams attributePathParams[2]; + readPrepareParams.mpAttributePathParamsList = attributePathParams; + readPrepareParams.mpAttributePathParamsList[0].mNodeId = chip::kTestDeviceNodeId; + readPrepareParams.mpAttributePathParamsList[0].mEndpointId = kTestEndpointId; + readPrepareParams.mpAttributePathParamsList[0].mClusterId = kTestClusterId; + readPrepareParams.mpAttributePathParamsList[0].mFieldId = 1; + readPrepareParams.mpAttributePathParamsList[0].mListIndex = 0; + readPrepareParams.mpAttributePathParamsList[0].mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + + readPrepareParams.mpAttributePathParamsList[1].mNodeId = chip::kTestDeviceNodeId; + readPrepareParams.mpAttributePathParamsList[1].mEndpointId = kTestEndpointId; + readPrepareParams.mpAttributePathParamsList[1].mClusterId = kTestClusterId; + readPrepareParams.mpAttributePathParamsList[1].mFieldId = 2; + readPrepareParams.mpAttributePathParamsList[1].mListIndex = 0; + readPrepareParams.mpAttributePathParamsList[1].mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + + readPrepareParams.mAttributePathParamsListSize = 2; + + readPrepareParams.mMinIntervalFloorSeconds = 2; + readPrepareParams.mMaxIntervalCeilingSeconds = 5; + printf("\nSend subscribe request message to Node: %" PRIu64 "\n", chip::kTestDeviceNodeId); + + err = engine->SendSubscribeRequest(readPrepareParams); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + delegate.mGotReport = false; + engine->GetReportingEngine().Run(); + NL_TEST_ASSERT(apSuite, delegate.mGotReport); + NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2); + + chip::app::ClusterInfo dirtyPath1; + dirtyPath1.mClusterId = kTestClusterId; + dirtyPath1.mEndpointId = kTestEndpointId; + dirtyPath1.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); + dirtyPath1.mFieldId = 1; + + chip::app::ClusterInfo dirtyPath2; + dirtyPath2.mClusterId = kTestClusterId; + dirtyPath2.mEndpointId = kTestEndpointId; + dirtyPath2.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); + dirtyPath2.mFieldId = 2; + + chip::app::ClusterInfo dirtyPath3; + dirtyPath2.mClusterId = kTestClusterId; + dirtyPath2.mEndpointId = kTestEndpointId; + dirtyPath2.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); + dirtyPath2.mFlags.Set(chip::app::ClusterInfo::Flags::kListIndexValid); + dirtyPath2.mFieldId = 2; + dirtyPath2.mListIndex = 1; + + chip::app::ClusterInfo dirtyPath4; + dirtyPath4.mClusterId = kTestClusterId; + dirtyPath4.mEndpointId = kTestEndpointId; + dirtyPath4.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); + dirtyPath4.mFieldId = 3; + + chip::app::ClusterInfo dirtyPath5; + dirtyPath5.mClusterId = kTestClusterId; + dirtyPath5.mEndpointId = kTestEndpointId; + dirtyPath5.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); + dirtyPath5.mFieldId = 4; + + // Test report with 2 different path + delegate.mpReadHandler->mHoldReport = false; + delegate.mGotReport = false; + delegate.mNumAttributeResponse = 0; + err = engine->GetReportingEngine().SetDirty(dirtyPath1); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = engine->GetReportingEngine().SetDirty(dirtyPath2); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + engine->GetReportingEngine().Run(); + NL_TEST_ASSERT(apSuite, delegate.mGotReport); + NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2); + + // Test report with 2 different path, and 1 same path + delegate.mpReadHandler->mHoldReport = false; + delegate.mGotReport = false; + delegate.mNumAttributeResponse = 0; + err = engine->GetReportingEngine().SetDirty(dirtyPath1); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = engine->GetReportingEngine().SetDirty(dirtyPath2); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = engine->GetReportingEngine().SetDirty(dirtyPath2); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + engine->GetReportingEngine().Run(); + NL_TEST_ASSERT(apSuite, delegate.mGotReport); + NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2); + + // Test report with 3 different path, and one path is overlapped with another + delegate.mpReadHandler->mHoldReport = false; + delegate.mGotReport = false; + delegate.mNumAttributeResponse = 0; + err = engine->GetReportingEngine().SetDirty(dirtyPath1); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = engine->GetReportingEngine().SetDirty(dirtyPath2); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = engine->GetReportingEngine().SetDirty(dirtyPath3); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + engine->GetReportingEngine().Run(); + NL_TEST_ASSERT(apSuite, delegate.mGotReport); + NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2); + + // Test report with 3 different path, all are not overlapped, one path is not interested for current subscription + delegate.mpReadHandler->mHoldReport = false; + delegate.mGotReport = false; + delegate.mNumAttributeResponse = 0; + err = engine->GetReportingEngine().SetDirty(dirtyPath1); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = engine->GetReportingEngine().SetDirty(dirtyPath2); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = engine->GetReportingEngine().SetDirty(dirtyPath4); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + engine->GetReportingEngine().Run(); + NL_TEST_ASSERT(apSuite, delegate.mGotReport); + NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2); + + // Test empty report + delegate.mpReadHandler->mHoldReport = false; + delegate.mGotReport = false; + delegate.mNumAttributeResponse = 0; + engine->GetReportingEngine().Run(); + NL_TEST_ASSERT(apSuite, delegate.mGotReport); + NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 0); + + // Test multiple subscriptipn + delegate.mNumAttributeResponse = 0; + delegate.mGotReport = false; + ReadPrepareParams readPrepareParams1(ctx.GetSessionBobToAlice()); + chip::app::AttributePathParams attributePathParams1[1]; + readPrepareParams1.mpAttributePathParamsList = attributePathParams1; + readPrepareParams1.mpAttributePathParamsList[0].mNodeId = chip::kTestDeviceNodeId; + readPrepareParams1.mpAttributePathParamsList[0].mEndpointId = kTestEndpointId; + readPrepareParams1.mpAttributePathParamsList[0].mClusterId = kTestClusterId; + readPrepareParams1.mpAttributePathParamsList[0].mFieldId = 1; + readPrepareParams1.mpAttributePathParamsList[0].mListIndex = 0; + readPrepareParams1.mpAttributePathParamsList[0].mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + readPrepareParams1.mAttributePathParamsListSize = 1; + readPrepareParams1.mMinIntervalFloorSeconds = 2; + readPrepareParams1.mMaxIntervalCeilingSeconds = 5; + printf("\nSend another subscribe request message to Node: %" PRIu64 "\n", chip::kTestDeviceNodeId); + + err = engine->SendSubscribeRequest(readPrepareParams1); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + engine->GetReportingEngine().Run(); + NL_TEST_ASSERT(apSuite, delegate.mGotReport); + NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 1); + + // Test report with 1 path modification for 2 subscription + delegate.mpReadHandler->mHoldReport = false; + delegate.mGotReport = false; + delegate.mNumAttributeResponse = 0; + err = engine->GetReportingEngine().SetDirty(dirtyPath1); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + engine->GetReportingEngine().Run(); + NL_TEST_ASSERT(apSuite, delegate.mGotReport); + NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 1); + + delegate.mpReadHandler->mHoldReport = false; + engine->GetReportingEngine().Run(); + NL_TEST_ASSERT(apSuite, delegate.mGotReport); + NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 1); + // By now we should have closed all exchanges and sent all pending acks, so + // there should be no queued-up things in the retransmit table. + NL_TEST_ASSERT(apSuite, rm->TestGetCountRetransTable() == 0); + + engine->Shutdown(); +} + +void TestReadInteraction::TestSubscribeInvalidAttributePathRoundtrip(nlTestSuite * apSuite, void * apContext) +{ + TestContext & ctx = *static_cast(apContext); + CHIP_ERROR err = CHIP_NO_ERROR; + + Messaging::ReliableMessageMgr * rm = ctx.GetExchangeManager().GetReliableMessageMgr(); + // Shouldn't have anything in the retransmit table when starting the test. + NL_TEST_ASSERT(apSuite, rm->TestGetCountRetransTable() == 0); + + GenerateEvents(apSuite, apContext); + + MockInteractionModelApp delegate; + auto * engine = chip::app::InteractionModelEngine::GetInstance(); + err = engine->Init(&ctx.GetExchangeManager(), &delegate); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(apSuite, !delegate.mGotEventResponse); + + ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice()); + chip::app::AttributePathParams attributePathParams[1]; + readPrepareParams.mpAttributePathParamsList = attributePathParams; + readPrepareParams.mpAttributePathParamsList[0].mNodeId = chip::kTestDeviceNodeId; + readPrepareParams.mpAttributePathParamsList[0].mEndpointId = kTestEndpointId; + readPrepareParams.mpAttributePathParamsList[0].mClusterId = kInvalidTestClusterId; + readPrepareParams.mpAttributePathParamsList[0].mFieldId = 1; + readPrepareParams.mpAttributePathParamsList[0].mListIndex = 0; + readPrepareParams.mpAttributePathParamsList[0].mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + + readPrepareParams.mAttributePathParamsListSize = 1; + + readPrepareParams.mSessionHandle = ctx.GetSessionBobToAlice(); + readPrepareParams.mMinIntervalFloorSeconds = 2; + readPrepareParams.mMaxIntervalCeilingSeconds = 5; + printf("\nSend subscribe request message to Node: %" PRIu64 "\n", chip::kTestDeviceNodeId); + + err = chip::app::InteractionModelEngine::GetInstance()->SendSubscribeRequest(readPrepareParams); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + delegate.mNumAttributeResponse = 0; + InteractionModelEngine::GetInstance()->GetReportingEngine().Run(); + NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 0); + delegate.mpReadHandler->mHoldReport = false; + InteractionModelEngine::GetInstance()->GetReportingEngine().Run(); + NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 0); + engine->Shutdown(); +} + } // namespace app } // namespace chip @@ -737,6 +1099,10 @@ const nlTest sTests[] = NL_TEST_DEF("TestReadClientGenerateTwoEventPathList", chip::app::TestReadInteraction::TestReadClientGenerateTwoEventPathList), NL_TEST_DEF("TestReadClientInvalidReport", chip::app::TestReadInteraction::TestReadClientInvalidReport), NL_TEST_DEF("TestReadHandlerInvalidAttributePath", chip::app::TestReadInteraction::TestReadHandlerInvalidAttributePath), + NL_TEST_DEF("TestProcessSubscribeResponse", chip::app::TestReadInteraction::TestProcessSubscribeResponse), + NL_TEST_DEF("TestProcessSubscribeRequest", chip::app::TestReadInteraction::TestProcessSubscribeRequest), + NL_TEST_DEF("TestSubscribeRoundtrip", chip::app::TestReadInteraction::TestSubscribeRoundtrip), + NL_TEST_DEF("TestSubscribeInvalidAttributePathRoundtrip", chip::app::TestReadInteraction::TestSubscribeInvalidAttributePathRoundtrip), NL_TEST_DEF("TestReadInvalidAttributePathRoundtrip", chip::app::TestReadInteraction::TestReadInvalidAttributePathRoundtrip), NL_TEST_SENTINEL() }; diff --git a/src/app/tests/TestReportingEngine.cpp b/src/app/tests/TestReportingEngine.cpp index c38e1d6b5dcb1f..7732686c7f227c 100644 --- a/src/app/tests/TestReportingEngine.cpp +++ b/src/app/tests/TestReportingEngine.cpp @@ -50,12 +50,12 @@ static SecureSessionMgr gSessionManager; static Messaging::ExchangeManager gExchangeManager; static TransportMgr gTransportManager; static secure_channel::MessageCounterManager gMessageCounterManager; -constexpr ClusterId kTestClusterId = 6; -constexpr EndpointId kTestEndpointId = 1; -constexpr chip::FieldId kTestFieldId1 = 1; -constexpr chip::FieldId kTestFieldId2 = 2; -constexpr uint8_t kTestFieldValue1 = 1; -constexpr uint8_t kTestFieldValue2 = 2; +constexpr ClusterId kTestClusterId = 6; +constexpr EndpointId kTestEndpointId = 1; +constexpr chip::AttributeId kTestFieldId1 = 1; +constexpr chip::AttributeId kTestFieldId2 = 2; +constexpr uint8_t kTestFieldValue1 = 1; +constexpr uint8_t kTestFieldValue2 = 2; namespace app { CHIP_ERROR ReadSingleClusterData(AttributePathParams & aAttributePathParams, TLV::TLVWriter * apWriter, bool * apDataExists) @@ -102,7 +102,6 @@ void TestReportingEngine::TestBuildAndSendSingleReportData(nlTestSuite * apSuite { CHIP_ERROR err = CHIP_NO_ERROR; app::ReadHandler readHandler; - Engine reportingEngine; System::PacketBufferTLVWriter writer; System::PacketBufferHandle readRequestbuf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); ReadRequest::Builder readRequestBuilder; @@ -122,22 +121,34 @@ void TestReportingEngine::TestBuildAndSendSingleReportData(nlTestSuite * apSuite NL_TEST_ASSERT(apSuite, readRequestBuilder.GetError() == CHIP_NO_ERROR); attributePathBuilder = attributePathListBuilder.CreateAttributePathBuilder(); NL_TEST_ASSERT(apSuite, attributePathListBuilder.GetError() == CHIP_NO_ERROR); - attributePathBuilder = - attributePathBuilder.NodeId(1).EndpointId(kTestEndpointId).ClusterId(kTestClusterId).FieldId(0).EndOfAttributePath(); + attributePathBuilder = attributePathBuilder.NodeId(1) + .EndpointId(kTestEndpointId) + .ClusterId(kTestClusterId) + .FieldId(kTestFieldId1) + .EndOfAttributePath(); + NL_TEST_ASSERT(apSuite, attributePathBuilder.GetError() == CHIP_NO_ERROR); + + attributePathBuilder = attributePathListBuilder.CreateAttributePathBuilder(); + NL_TEST_ASSERT(apSuite, attributePathListBuilder.GetError() == CHIP_NO_ERROR); + attributePathBuilder = attributePathBuilder.NodeId(1) + .EndpointId(kTestEndpointId) + .ClusterId(kTestClusterId) + .FieldId(kTestFieldId2) + .EndOfAttributePath(); NL_TEST_ASSERT(apSuite, attributePathBuilder.GetError() == CHIP_NO_ERROR); attributePathListBuilder.EndOfAttributePathList(); - readRequestBuilder.EventNumber(1); + NL_TEST_ASSERT(apSuite, readRequestBuilder.GetError() == CHIP_NO_ERROR); readRequestBuilder.EndOfReadRequest(); NL_TEST_ASSERT(apSuite, readRequestBuilder.GetError() == CHIP_NO_ERROR); err = writer.Finalize(&readRequestbuf); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - + readHandler.Init(&gExchangeManager, nullptr, exchangeCtx, chip::app::ReadHandler::InteractionType::Read); readHandler.OnReadInitialRequest(std::move(readRequestbuf)); - reportingEngine.Init(); - err = reportingEngine.BuildAndSendSingleReportData(&readHandler); - NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_INCORRECT_STATE); + err = InteractionModelEngine::GetInstance()->GetReportingEngine().BuildAndSendSingleReportData(&readHandler); + NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_NOT_CONNECTED); } + } // namespace reporting } // namespace app } // namespace chip diff --git a/src/app/tests/integration/chip_im_initiator.cpp b/src/app/tests/integration/chip_im_initiator.cpp index 57b5f4e7062caa..7c1a3ce2786fc9 100644 --- a/src/app/tests/integration/chip_im_initiator.cpp +++ b/src/app/tests/integration/chip_im_initiator.cpp @@ -51,6 +51,9 @@ constexpr size_t kMaxWriteMessageCount = 3; constexpr uint32_t gMessageIntervalMsec = 1200; constexpr uint32_t gMessageTimeoutMsec = 1000; constexpr chip::FabricIndex gFabricIndex = 0; +constexpr size_t kMaxSubMessageCount = 1; +constexpr int32_t gMessageIntervalSeconds = 1; +constexpr uint64_t gSubMaxReport = 5; chip::TransportMgr gTransportManager; chip::Inet::IPAddress gDestAddr; @@ -76,6 +79,15 @@ uint64_t gWriteCount = 0; // Count of the number of WriteResponses received. uint64_t gWriteRespCount = 0; +// Count of the number of SubscribeRequests sent. +uint64_t gSubCount = 0; + +// Count of the number of SubscribeResponses received. +uint64_t gSubRespCount = 0; + +// Count of the number of reports for subscription. +uint64_t gSubReportCount = 0; + // Whether the last command successed. enum class TestCommandResult : uint8_t { @@ -90,6 +102,7 @@ void CommandRequestTimerHandler(chip::System::Layer * systemLayer, void * appSta void BadCommandRequestTimerHandler(chip::System::Layer * systemLayer, void * appState); void ReadRequestTimerHandler(chip::System::Layer * systemLayer, void * appState); void WriteRequestTimerHandler(chip::System::Layer * systemLayer, void * appState); +void SubscribeRequestTimerHandler(chip::System::Layer * systemLayer, void * appState); CHIP_ERROR SendCommandRequest(chip::app::CommandSender * commandSender) { @@ -255,6 +268,54 @@ CHIP_ERROR SendWriteRequest(chip::app::WriteClientHandle & apWriteClient) return err; } +CHIP_ERROR SendSubscribeRequest() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + gLastMessageTime = chip::System::Clock::GetMonotonicMilliseconds(); + + chip::app::ReadPrepareParams readPrepareParams(chip::SessionHandle(chip::kTestDeviceNodeId, 0, 0, gFabricIndex)); + chip::app::EventPathParams eventPathParams[2]; + chip::app::AttributePathParams attributePathParams[1]; + readPrepareParams.mpEventPathParamsList = eventPathParams; + readPrepareParams.mpEventPathParamsList[0].mNodeId = kTestNodeId; + readPrepareParams.mpEventPathParamsList[0].mEndpointId = kTestEndpointId; + readPrepareParams.mpEventPathParamsList[0].mClusterId = kTestClusterId; + readPrepareParams.mpEventPathParamsList[0].mEventId = kTestChangeEvent1; + + readPrepareParams.mpEventPathParamsList[1].mNodeId = kTestNodeId; + readPrepareParams.mpEventPathParamsList[1].mEndpointId = kTestEndpointId; + readPrepareParams.mpEventPathParamsList[1].mClusterId = kTestClusterId; + readPrepareParams.mpEventPathParamsList[1].mEventId = kTestChangeEvent2; + + readPrepareParams.mEventPathParamsListSize = 2; + + readPrepareParams.mpAttributePathParamsList = attributePathParams; + readPrepareParams.mpAttributePathParamsList[0].mNodeId = chip::kTestDeviceNodeId; + readPrepareParams.mpAttributePathParamsList[0].mEndpointId = kTestEndpointId; + readPrepareParams.mpAttributePathParamsList[0].mClusterId = kTestClusterId; + readPrepareParams.mpAttributePathParamsList[0].mFieldId = 1; + readPrepareParams.mpAttributePathParamsList[0].mListIndex = 0; + readPrepareParams.mpAttributePathParamsList[0].mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + + readPrepareParams.mAttributePathParamsListSize = 1; + + readPrepareParams.mMinIntervalFloorSeconds = 2; + readPrepareParams.mMaxIntervalCeilingSeconds = 5; + printf("\nSend subscribe request message to Node: %" PRIu64 "\n", chip::kTestDeviceNodeId); + + err = chip::app::InteractionModelEngine::GetInstance()->SendSubscribeRequest(readPrepareParams); + SuccessOrExit(err); + + gSubCount++; + +exit: + if (err != CHIP_NO_ERROR) + { + printf("Send subscribe request failed, err: %s\n", chip::ErrorStr(err)); + } + return err; +} + CHIP_ERROR EstablishSecureSession() { CHIP_ERROR err = CHIP_NO_ERROR; @@ -304,6 +365,15 @@ void HandleWriteComplete() static_cast(gWriteRespCount) * 100 / gWriteCount, static_cast(transitTime) / 1000); } +void HandleSubscribeReportComplete() +{ + uint32_t respTime = chip::System::Clock::GetMonotonicMilliseconds(); + uint32_t transitTime = respTime - gLastMessageTime; + gSubRespCount++; + printf("Subscribe Complete: %" PRIu64 "/%" PRIu64 "(%.2f%%) time=%.3fms\n", gSubRespCount, gSubCount, + static_cast(gSubRespCount) * 100 / gSubCount, static_cast(transitTime) / 1000); +} + void CommandRequestTimerHandler(chip::System::Layer * systemLayer, void * appState) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -419,6 +489,39 @@ void WriteRequestTimerHandler(chip::System::Layer * systemLayer, void * appState VerifyOrExit(err == CHIP_NO_ERROR, printf("Failed to schedule timer with error: %s\n", chip::ErrorStr(err))); } else + { + err = chip::DeviceLayer::SystemLayer().StartTimer(gMessageIntervalSeconds * 1000, SubscribeRequestTimerHandler, NULL); + VerifyOrExit(err == CHIP_NO_ERROR, printf("Failed to schedule timer with error: %s\n", chip::ErrorStr(err))); + } + +exit: + if (err != CHIP_NO_ERROR) + { + chip::DeviceLayer::PlatformMgr().StopEventLoopTask(); + } +} + +void SubscribeRequestTimerHandler(chip::System::Layer * systemLayer, void * appState) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + if (gSubRespCount != gSubCount) + { + printf("No response received\n"); + + // Set gSubRespCount to gSubCount to start next iteration if there is any. + gSubRespCount = gSubCount; + } + + if (gSubRespCount < kMaxSubMessageCount) + { + err = SendSubscribeRequest(); + VerifyOrExit(err == CHIP_NO_ERROR, printf("Failed to send write request with error: %s\n", chip::ErrorStr(err))); + + err = chip::DeviceLayer::SystemLayer().StartTimer(20 * 1000, SubscribeRequestTimerHandler, NULL); + VerifyOrExit(err == CHIP_NO_ERROR, printf("Failed to schedule timer with error: %s\n", chip::ErrorStr(err))); + } + else { // Complete all tests. chip::DeviceLayer::PlatformMgr().StopEventLoopTask(); @@ -444,7 +547,20 @@ class MockInteractionModelApp : public chip::app::InteractionModelDelegate { return CHIP_NO_ERROR; } - CHIP_ERROR ReportProcessed(const chip::app::ReadClient * apReadClient) override { return CHIP_NO_ERROR; } + CHIP_ERROR ReportProcessed(const chip::app::ReadClient * apReadClient) override + { + if (apReadClient->IsSubscriptionType()) + { + gSubReportCount++; + if (gSubReportCount == gSubMaxReport) + { + HandleSubscribeReportComplete(); + } + } + + return CHIP_NO_ERROR; + } + CHIP_ERROR ReadError(const chip::app::ReadClient * apReadClient, CHIP_ERROR aError) override { printf("ReadError with err %" CHIP_ERROR_FORMAT, aError.Format()); @@ -452,7 +568,10 @@ class MockInteractionModelApp : public chip::app::InteractionModelDelegate } CHIP_ERROR ReadDone(const chip::app::ReadClient * apReadClient) override { - HandleReadComplete(); + if (!apReadClient->IsSubscriptionType()) + { + HandleReadComplete(); + } return CHIP_NO_ERROR; } CHIP_ERROR CommandResponseStatus(const chip::app::CommandSender * apCommandSender, diff --git a/src/app/tests/integration/chip_im_responder.cpp b/src/app/tests/integration/chip_im_responder.cpp index ef1414b46ecb4f..b95d7ec4c95dd3 100644 --- a/src/app/tests/integration/chip_im_responder.cpp +++ b/src/app/tests/integration/chip_im_responder.cpp @@ -139,6 +139,7 @@ CHIP_ERROR WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & a } // namespace chip namespace { +bool testSyncReport = false; chip::TransportMgr gTransportManager; chip::SecurePairingUsingTestSecret gTestPairing; LivenessEventGenerator gLivenessGenerator; @@ -159,12 +160,47 @@ void InitializeEventLogging(chip::Messaging::ExchangeManager * apMgr) chip::app::EventManagement::CreateEventManagement(apMgr, sizeof(logStorageResources) / sizeof(logStorageResources[0]), gCircularEventBuffer, logStorageResources); } + +void MutateClusterHandler(chip::System::Layer * systemLayer, void * appState) +{ + chip::app::ClusterInfo dirtyPath; + dirtyPath.mClusterId = kTestClusterId; + dirtyPath.mEndpointId = kTestEndpointId; + dirtyPath.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); + printf("MutateClusterHandler is triggered..."); + // send dirty change + if (!testSyncReport) + { + dirtyPath.mFieldId = 1; + chip::app::InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(dirtyPath); + chip::app::InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun(); + chip::DeviceLayer::SystemLayer().StartTimer(1000, MutateClusterHandler, NULL); + testSyncReport = true; + } + else + { + dirtyPath.mFieldId = 10; // unknown field + chip::app::InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(dirtyPath); + // send sync message(empty report) + chip::app::InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun(); + } +} + +class MockInteractionModelApp : public chip::app::InteractionModelDelegate +{ +public: + virtual CHIP_ERROR SubscriptionEstablished(const chip::app::ReadHandler * apReadHandler) + { + chip::DeviceLayer::SystemLayer().StartTimer(1000, MutateClusterHandler, NULL); + return CHIP_NO_ERROR; + } +}; } // namespace int main(int argc, char * argv[]) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::app::InteractionModelDelegate mockDelegate; + MockInteractionModelApp mockDelegate; chip::Optional peer(chip::Transport::Type::kUndefined); const chip::FabricIndex gFabricIndex = 0; chip::Transport::FabricTable fabrics; diff --git a/src/app/tests/suites/TestDelayCommands.yaml b/src/app/tests/suites/TestDelayCommands.yaml index b3f7839bdc93f3..6a32a4c7eaf972 100644 --- a/src/app/tests/suites/TestDelayCommands.yaml +++ b/src/app/tests/suites/TestDelayCommands.yaml @@ -20,7 +20,7 @@ config: tests: - label: "Wait 100ms" - cluster: "DelayCommands" + cluster: "TestSuite" command: "WaitForMs" arguments: values: diff --git a/src/app/tests/suites/TestSubscribe_OnOff.yaml b/src/app/tests/suites/TestSubscribe_OnOff.yaml new file mode 100644 index 00000000000000..69c0c4620d80c2 --- /dev/null +++ b/src/app/tests/suites/TestSubscribe_OnOff.yaml @@ -0,0 +1,41 @@ +# Copyright (c) 2021 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Subscribe Tests - OnOff Cluster + +config: + cluster: "On/Off" + endpoint: 1 + +tests: + - label: "Set OnOff Attribute to false" + command: "Off" + - label: "Subscribe OnOff Attribute" + command: "subscribeAttribute" + attribute: "OnOff" + minInterval: 2 + maxInterval: 10 + response: + value: false + - label: "Turn On the light to see attribute change" + command: "On" + - label: "Check for attribute report" + cluster: "TestSuite" + command: "WaitForAttributeReport" + waitfor: + endpoint: 1 + cluster: "On/Off" + attribute: "OnOff" + response: + value: true diff --git a/src/app/util/CHIPDeviceCallbacksMgr.cpp b/src/app/util/CHIPDeviceCallbacksMgr.cpp index 14c8fe99d4efab..5dbc9efdb254cc 100644 --- a/src/app/util/CHIPDeviceCallbacksMgr.cpp +++ b/src/app/util/CHIPDeviceCallbacksMgr.cpp @@ -29,23 +29,6 @@ #include #include -namespace { - -struct ReportCallbackInfo -{ - chip::NodeId nodeId; - chip::EndpointId endpointId; - chip::ClusterId clusterId; - chip::AttributeId attributeId; - - bool operator==(ReportCallbackInfo const & other) - { - return nodeId == other.nodeId && endpointId == other.endpointId && clusterId == other.clusterId && - attributeId == other.attributeId; - } -}; -} // namespace - namespace chip { namespace app { @@ -145,10 +128,55 @@ CHIP_ERROR CHIPDeviceCallbacksMgr::GetResponseCallback(NodeId nodeId, uint8_t se return CHIP_NO_ERROR; } +CHIP_ERROR CHIPDeviceCallbacksMgr::SetSubscribeFilter(const ReportCallbackInfo & info, TLVDataFilter filter) +{ + constexpr ReportCallbackInfo kEmptyInfo{ kPlaceholderNodeId, 0, 0, 0 }; + + for (size_t i = 0; i < kTLVFilterPoolSize; i++) + { + if (mReportFilterPool[i].info == info) + { + mReportFilterPool[i].filter = filter; + return CHIP_NO_ERROR; + } + } + + for (size_t i = 0; i < kTLVFilterPoolSize; i++) + { + if (mReportFilterPool[i].info == kEmptyInfo) + { + mReportFilterPool[i].info = info; + mReportFilterPool[i].filter = filter; + return CHIP_NO_ERROR; + } + } + + return CHIP_ERROR_NO_MEMORY; +} + +CHIP_ERROR CHIPDeviceCallbacksMgr::GetSubscribeFilter(const ReportCallbackInfo & info, TLVDataFilter * outFilter) +{ + for (size_t i = 0; i < kTLVFilterPoolSize; i++) + { + if (mReportFilterPool[i].info == info) + { + if (outFilter != nullptr) + { + *outFilter = mReportFilterPool[i].filter; + } + return CHIP_NO_ERROR; + } + } + + return CHIP_ERROR_KEY_NOT_FOUND; +} + CHIP_ERROR CHIPDeviceCallbacksMgr::AddReportCallback(NodeId nodeId, EndpointId endpointId, ClusterId clusterId, - AttributeId attributeId, Callback::Cancelable * onReportCallback) + AttributeId attributeId, Callback::Cancelable * onReportCallback, + TLVDataFilter filter) { VerifyOrReturnError(onReportCallback != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(filter != nullptr, CHIP_ERROR_INVALID_ARGUMENT); ReportCallbackInfo info = { nodeId, endpointId, clusterId, attributeId }; static_assert(sizeof(onReportCallback->mInfo) >= sizeof(info), "Callback info too large"); @@ -157,16 +185,20 @@ CHIP_ERROR CHIPDeviceCallbacksMgr::AddReportCallback(NodeId nodeId, EndpointId e // If a callback has already been registered for the same ReportCallbackInfo, let's cancel it. CancelCallback(info, mReports); + ReturnErrorOnFailure(SetSubscribeFilter(info, filter)); + mReports.Enqueue(onReportCallback); return CHIP_NO_ERROR; } CHIP_ERROR CHIPDeviceCallbacksMgr::GetReportCallback(NodeId nodeId, EndpointId endpointId, ClusterId clusterId, - AttributeId attributeId, Callback::Cancelable ** onReportCallback) + AttributeId attributeId, Callback::Cancelable ** onReportCallback, + TLVDataFilter * outFilter) { ReportCallbackInfo info = { nodeId, endpointId, clusterId, attributeId }; ReturnErrorOnFailure(GetCallback(info, mReports, onReportCallback)); + ReturnErrorOnFailure(GetSubscribeFilter(info, outFilter)); return CHIP_NO_ERROR; } diff --git a/src/app/util/CHIPDeviceCallbacksMgr.h b/src/app/util/CHIPDeviceCallbacksMgr.h index c50353d3fd8753..cba369a4103d32 100644 --- a/src/app/util/CHIPDeviceCallbacksMgr.h +++ b/src/app/util/CHIPDeviceCallbacksMgr.h @@ -51,6 +51,7 @@ constexpr size_t kTLVFilterPoolSize = CHIP_DEVICE_CALLBACK_MANAGER_TLV_FILTER_PO * The possible implementation of this function might be: * - Unpack the data with some schema from TLV * - Call success callback and failure callback according to the result of unpack routine. + * - onFailure MAY be nullptr, in this case, response error will be ignored. (Usually for subscribe responses.) */ using TLVDataFilter = void (*)(chip::TLV::TLVReader * data, chip::Callback::Cancelable * onSuccess, chip::Callback::Cancelable * onFailure); @@ -75,9 +76,9 @@ class DLL_EXPORT CHIPDeviceCallbacksMgr Callback::Cancelable ** onFailureCallback, TLVDataFilter * callbackFilter = nullptr); CHIP_ERROR AddReportCallback(NodeId nodeId, EndpointId endpointId, ClusterId clusterId, AttributeId attributeId, - Callback::Cancelable * onReportCallback); + Callback::Cancelable * onReportCallback, TLVDataFilter callbackFilter); CHIP_ERROR GetReportCallback(NodeId nodeId, EndpointId endpointId, ClusterId clusterId, AttributeId attributeId, - Callback::Cancelable ** onReportCallback); + Callback::Cancelable ** onReportCallback, TLVDataFilter * callbackFilter); private: CHIPDeviceCallbacksMgr() {} @@ -93,10 +94,25 @@ class DLL_EXPORT CHIPDeviceCallbacksMgr } }; + struct ReportCallbackInfo + { + chip::NodeId nodeId; + chip::EndpointId endpointId; + chip::ClusterId clusterId; + chip::AttributeId attributeId; + + bool operator==(ReportCallbackInfo const & other) + { + return nodeId == other.nodeId && endpointId == other.endpointId && clusterId == other.clusterId && + attributeId == other.attributeId; + } + }; + + template struct TLVFilterItem { - ResponseCallbackInfo info = { kPlaceholderNodeId, 0 }; - TLVDataFilter filter = nullptr; + T info = { .nodeId = kPlaceholderNodeId }; + TLVDataFilter filter = nullptr; }; template @@ -138,10 +154,14 @@ class DLL_EXPORT CHIPDeviceCallbacksMgr CHIP_ERROR AddResponseFilter(const ResponseCallbackInfo & info, TLVDataFilter callbackFilter); CHIP_ERROR PopResponseFilter(const ResponseCallbackInfo & info, TLVDataFilter * callbackFilter); + CHIP_ERROR SetSubscribeFilter(const ReportCallbackInfo & info, TLVDataFilter callbackFilter); + CHIP_ERROR GetSubscribeFilter(const ReportCallbackInfo & info, TLVDataFilter * callbackFilter); + Callback::CallbackDeque mResponsesSuccess; Callback::CallbackDeque mResponsesFailure; - TLVFilterItem mTLVFilterPool[kTLVFilterPoolSize]; + TLVFilterItem mTLVFilterPool[kTLVFilterPoolSize]; Callback::CallbackDeque mReports; + TLVFilterItem mReportFilterPool[kTLVFilterPoolSize]; }; } // namespace app diff --git a/src/app/util/attribute-table.cpp b/src/app/util/attribute-table.cpp index 5ec0810a14a67e..2ea8bc6fd51e12 100644 --- a/src/app/util/attribute-table.cpp +++ b/src/app/util/attribute-table.cpp @@ -600,7 +600,7 @@ EmberAfStatus emAfWriteAttribute(EndpointId endpoint, ClusterId cluster, Attribu // Function itself will weed out tokens that are not tokenized. emAfSaveAttributeToToken(data, endpoint, cluster, metadata); - emberAfReportingAttributeChangeCallback(endpoint, cluster, attributeID, mask, manufacturerCode, dataType, data); + InteractionModelReportingAttributeChangeCallback(endpoint, cluster, attributeID, mask, manufacturerCode, dataType, data); // Post write attribute callback for all attributes changes, regardless // of cluster. diff --git a/src/app/util/ember-compatibility-functions.cpp b/src/app/util/ember-compatibility-functions.cpp index 72e7c6cf65d87a..8eaf54da4b38ca 100644 --- a/src/app/util/ember-compatibility-functions.cpp +++ b/src/app/util/ember-compatibility-functions.cpp @@ -21,8 +21,10 @@ * when calling ember callbacks. */ +#include #include #include +#include #include #include #include @@ -460,6 +462,23 @@ CHIP_ERROR WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & a : Protocols::SecureChannel::GeneralStatusCode::kFailure, Protocols::SecureChannel::Id, imCode); } - } // namespace app } // namespace chip + +void InteractionModelReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId, + uint8_t mask, uint16_t manufacturerCode, EmberAfAttributeType type, + uint8_t * data) +{ + IgnoreUnusedVariable(manufacturerCode); + IgnoreUnusedVariable(type); + IgnoreUnusedVariable(data); + IgnoreUnusedVariable(mask); + + ClusterInfo info; + info.mClusterId = clusterId; + info.mFieldId = attributeId; + info.mEndpointId = endpoint; + info.mFlags.Set(ClusterInfo::Flags::kFieldIdValid); + + InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(info); +} diff --git a/src/app/util/im-client-callbacks.cpp b/src/app/util/im-client-callbacks.cpp index 1a05a88846cc5f..5abb573a855131 100644 --- a/src/app/util/im-client-callbacks.cpp +++ b/src/app/util/im-client-callbacks.cpp @@ -372,10 +372,20 @@ bool IMReadReportAttributesResponseCallback(const app::ReadClient * apReadClient Callback::Cancelable * onSuccessCallback = nullptr; Callback::Cancelable * onFailureCallback = nullptr; app::TLVDataFilter tlvFilter = nullptr; - NodeId sourceId = aPath.mNodeId; + NodeId sourceId = apReadClient->GetExchangeContext()->GetSecureSession().GetPeerNodeId(); // In CHIPClusters.cpp, we are using sequenceNumber as application identifier. uint8_t sequenceNumber = static_cast(apReadClient->GetAppIdentifier()); - CHIP_ERROR err = gCallbacks.GetResponseCallback(sourceId, sequenceNumber, &onSuccessCallback, &onFailureCallback, &tlvFilter); + + CHIP_ERROR err = CHIP_NO_ERROR; + if (apReadClient->IsSubscriptionType()) + { + err = gCallbacks.GetReportCallback(sourceId, aPath.mEndpointId, aPath.mClusterId, aPath.mFieldId, &onSuccessCallback, + &tlvFilter); + } + else + { + err = gCallbacks.GetResponseCallback(sourceId, sequenceNumber, &onSuccessCallback, &onFailureCallback, &tlvFilter); + } if (CHIP_NO_ERROR != err) { @@ -384,7 +394,7 @@ bool IMReadReportAttributesResponseCallback(const app::ReadClient * apReadClient ChipLogDetail(Zcl, "%s: Missing success callback", __FUNCTION__); } - if (onFailureCallback == nullptr) + if (onFailureCallback == nullptr && !apReadClient->IsSubscriptionType()) { ChipLogDetail(Zcl, "%s: Missing failure callback", __FUNCTION__); } @@ -404,7 +414,7 @@ bool IMReadReportAttributesResponseCallback(const app::ReadClient * apReadClient ChipLogProgress(Zcl, " attribute TLV Type: 0x%02x", apData->GetType()); tlvFilter(apData, onSuccessCallback, onFailureCallback); } - else + else if (onFailureCallback != nullptr) { Callback::Callback * cb = Callback::Callback::FromCancelable(onFailureCallback); @@ -415,6 +425,51 @@ bool IMReadReportAttributesResponseCallback(const app::ReadClient * apReadClient return true; } +bool IMSubscribeResponseCallback(const chip::app::ReadClient * apSubscribeClient, EmberAfStatus status) +{ + ChipLogProgress(Zcl, "SubscribeResponse:"); + ChipLogProgress(Zcl, " ApplicationIdentifier: %" PRIx64, apSubscribeClient->GetAppIdentifier()); + LogStatus(status); + + // In CHIPClusters.cpp, we are using sequenceNumber as application identifier. + uint8_t sequenceNumber = static_cast(apSubscribeClient->GetAppIdentifier()); + + CHIP_ERROR err = CHIP_NO_ERROR; + Callback::Cancelable * onSuccessCallback = nullptr; + Callback::Cancelable * onFailureCallback = nullptr; + err = gCallbacks.GetResponseCallback(apSubscribeClient->GetExchangeContext()->GetSecureSession().GetPeerNodeId(), + sequenceNumber, &onSuccessCallback, &onFailureCallback); + + if (CHIP_NO_ERROR != err) + { + if (onSuccessCallback == nullptr) + { + ChipLogDetail(Zcl, "%s: Missing success callback", __FUNCTION__); + } + + if (onFailureCallback == nullptr) + { + ChipLogDetail(Zcl, "%s: Missing failure callback", __FUNCTION__); + } + return true; + } + + if (status == EMBER_ZCL_STATUS_SUCCESS) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onSuccessCallback); + cb->mCall(cb->mContext); + } + else + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, static_cast(status)); + } + + return true; +} + bool emberAfDefaultResponseCallback(ClusterId clusterId, CommandId commandId, EmberAfStatus status) { ChipLogProgress(Zcl, "DefaultResponse:"); diff --git a/src/app/util/im-client-callbacks.h b/src/app/util/im-client-callbacks.h index 1af3014c608398..cc01f87218b25f 100644 --- a/src/app/util/im-client-callbacks.h +++ b/src/app/util/im-client-callbacks.h @@ -32,6 +32,7 @@ bool IMDefaultResponseCallback(const chip::app::Command * commandObj, EmberAfSta bool IMReadReportAttributesResponseCallback(const chip::app::ReadClient * apReadClient, const chip::app::ClusterInfo & aPath, chip::TLV::TLVReader * apData, chip::Protocols::InteractionModel::ProtocolCode status); bool IMWriteResponseCallback(const chip::app::WriteClient * writeClient, EmberAfStatus status); +bool IMSubscribeResponseCallback(const chip::app::ReadClient * apSubscribeClient, EmberAfStatus status); void LogStatus(uint8_t status); // Global Response Callbacks diff --git a/src/app/zap-templates/common/ClusterTestGeneration.js b/src/app/zap-templates/common/ClusterTestGeneration.js index 1252c234e1d464..58f9a37b66e926 100644 --- a/src/app/zap-templates/common/ClusterTestGeneration.js +++ b/src/app/zap-templates/common/ClusterTestGeneration.js @@ -26,7 +26,7 @@ const path = require('path'); // Import helpers from zap core const templateUtil = require(zapPath + 'dist/src-electron/generator/template-util.js') -const { DelayCommands } = require('./simulated-clusters/TestDelayCommands.js'); +const { TestSuiteHelperCluster } = require('./TestSuiteHelperCluster.js'); const { Clusters, asBlocks, asPromise } = require('./ClustersHelper.js'); const kClusterName = 'cluster'; @@ -73,6 +73,12 @@ function setDefaultType(test) test.isWriteAttribute = true; break; + case 'subscribeAttribute': + test.isAttribute = true; + test.isReadAttribute = true; + test.isSubscribeAttribute = true; + break; + default: test.isCommand = true; break; @@ -141,6 +147,7 @@ function setDefaultResponse(test) } if (!hasResponseValueOrConstraints) { + console.log(test); console.log(test[kResponseName]); const errorStr = 'Test does not have a "value" or a "constraints" defined.'; throwError(test, errorStr); @@ -214,18 +221,19 @@ function getClusters() { // Create a new array to merge the configured clusters list and test // simulated clusters. - return Clusters.getClusters().then(clusters => clusters.concat(DelayCommands)); + return Clusters.getClusters().then(clusters => clusters.concat(TestSuiteHelperCluster)); } function getCommands(clusterName) { - return (clusterName == DelayCommands.name) ? Promise.resolve(DelayCommands.commands) : Clusters.getClientCommands(clusterName); + return (clusterName == TestSuiteHelperCluster.name) ? Promise.resolve(TestSuiteHelperCluster.commands) + : Clusters.getClientCommands(clusterName); } function getAttributes(clusterName) { - return (clusterName == DelayCommands.name) ? Promise.resolve(DelayCommands.attributes) - : Clusters.getServerAttributes(clusterName); + return (clusterName == TestSuiteHelperCluster.name) ? Promise.resolve(TestSuiteHelperCluster.attributes) + : Clusters.getServerAttributes(clusterName); } function assertCommandOrAttribute(context) @@ -291,7 +299,15 @@ function chip_tests_items(options) function isTestOnlyCluster(name) { - return name == DelayCommands.name; + return name == TestSuiteHelperCluster.name; +} + +function chip_tests_with_command_attribute_info(options) +{ + const promise = assertCommandOrAttribute(this).then(item => { + return [ item ]; + }); + return asBlocks.call(this, promise, options); } function chip_tests_item_parameters(options) @@ -360,11 +376,20 @@ function chip_tests_item_response_parameters(options) return asBlocks.call(this, promise, options); } +function chip_tests_WaitForAttributeReport_attribute_info(options) +{ + const waitfor = Object.assign(JSON.parse(JSON.stringify(this.waitfor)), { command : 'readAttribute', isAttribute : true }); + setDefaults(waitfor, this.parent); + return templateUtil.collectBlocks([ waitfor ], options, this); +} + // // Module exports // -exports.chip_tests = chip_tests; -exports.chip_tests_items = chip_tests_items; -exports.chip_tests_item_parameters = chip_tests_item_parameters; -exports.chip_tests_item_response_parameters = chip_tests_item_response_parameters; -exports.isTestOnlyCluster = isTestOnlyCluster; +exports.chip_tests = chip_tests; +exports.chip_tests_items = chip_tests_items; +exports.chip_tests_item_parameters = chip_tests_item_parameters; +exports.chip_tests_item_response_parameters = chip_tests_item_response_parameters; +exports.isTestOnlyCluster = isTestOnlyCluster; +exports.chip_tests_with_command_attribute_info = chip_tests_with_command_attribute_info; +exports.chip_tests_WaitForAttributeReport_attribute_info = chip_tests_WaitForAttributeReport_attribute_info; diff --git a/src/app/zap-templates/common/simulated-clusters/TestDelayCommands.js b/src/app/zap-templates/common/TestSuiteHelperCluster.js similarity index 67% rename from src/app/zap-templates/common/simulated-clusters/TestDelayCommands.js rename to src/app/zap-templates/common/TestSuiteHelperCluster.js index 7c4736dc533e1b..73fd1f3ef21b9d 100644 --- a/src/app/zap-templates/common/simulated-clusters/TestDelayCommands.js +++ b/src/app/zap-templates/common/TestSuiteHelperCluster.js @@ -16,7 +16,7 @@ */ /* - * This file declare test suites utilities methods for delayed commands. + * This file declare test suites utilities methods for test suite. * * Each method declared in this file needs to be implemented on a per-language * basis and permits to exposes methods to the test suites that are not part @@ -30,12 +30,21 @@ const WaitForMs = { response : { arguments : [] } }; -const DelayCommands = { - name : 'DelayCommands', - commands : [ WaitForMs ], +const WaitForAttributeRepor = { + name : 'WaitForAttributeReport', + arguments : [], + response : { arguments : [ { name : 'value' } ] } + /* + * 'WaitForAttributeResponse' will take "attribute" parameter for detailed attribute path. + */ +}; + +const TestSuiteHelperCluster = { + name : 'TestSuite', + commands : [ WaitForMs, WaitForAttributeRepor ], }; // // Module exports // -exports.DelayCommands = DelayCommands; +exports.TestSuiteHelperCluster = TestSuiteHelperCluster; diff --git a/src/app/zap-templates/templates/app/CHIPClientCallbacks-src.zapt b/src/app/zap-templates/templates/app/CHIPClientCallbacks-src.zapt index 29d6ffa23fe2de..f9ab49717d9e6d 100644 --- a/src/app/zap-templates/templates/app/CHIPClientCallbacks-src.zapt +++ b/src/app/zap-templates/templates/app/CHIPClientCallbacks-src.zapt @@ -346,8 +346,11 @@ void {{asUpperCamelCase parent.name}}Cluster{{asUpperCamelCase name}}ListAttribu EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -418,240 +421,4 @@ bool emberAf{{asUpperCamelCase parent.name}}Cluster{{asUpperCamelCase name}}Call {{/chip_cluster_responses}} {{/chip_client_clusters}} - -bool emberAfReportAttributesCallback(ClusterId clusterId, uint8_t * message, uint16_t messageLen) -{ - ChipLogProgress(Zcl, "emberAfReportAttributeCallback:"); - ChipLogProgress(Zcl, " ClusterId: " ChipLogFormatMEI, ChipLogValueMEI(clusterId)); - - NodeId sourceId = emberAfCurrentCommand()->SourceNodeId(); - ChipLogProgress(Zcl, " Source NodeId: %" PRIu64, sourceId); - - EndpointId endpointId = emberAfCurrentCommand()->apsFrame->sourceEndpoint; - ChipLogProgress(Zcl, " Source EndpointId: 0x%04x", endpointId); - - // TODO onFailureCallback is just here because of the CHECK_MESSAGE_LENGTH macro. It needs to be removed. - Callback::Cancelable * onFailureCallback = nullptr; - - while (messageLen) - { - CHECK_MESSAGE_LENGTH(4); - AttributeId attributeId = Encoding::LittleEndian::Read32(message); // attribId - ChipLogProgress(Zcl, " attributeId: " ChipLogFormatMEI, ChipLogValueMEI(attributeId)); - - GET_REPORT_CALLBACK("emberAfReportAttributesCallback"); - - CHECK_MESSAGE_LENGTH(1); - uint8_t attributeType = Encoding::Read8(message); - ChipLogProgress(Zcl, " attributeType: 0x%02x", attributeType); - - switch (attributeType) - { - case 0x00: // nodata / No data - case 0x0A: // data24 / 24-bit data - case 0x0C: // data40 / 40-bit data - case 0x0D: // data48 / 48-bit data - case 0x0E: // data56 / 56-bit data - case 0x1A: // map24 / 24-bit bitmap - case 0x1C: // map40 / 40-bit bitmap - case 0x1D: // map48 / 48-bit bitmap - case 0x1E: // map56 / 56-bit bitmap - case 0x22: // uint24 / Unsigned 24-bit integer - case 0x24: // uint40 / Unsigned 40-bit integer - case 0x25: // uint48 / Unsigned 48-bit integer - case 0x26: // uint56 / Unsigned 56-bit integer - case 0x2A: // int24 / Signed 24-bit integer - case 0x2C: // int40 / Signed 40-bit integer - case 0x2D: // int48 / Signed 48-bit integer - case 0x2E: // int56 / Signed 56-bit integer - case 0x38: // semi / Semi-precision - case 0x39: // single / Single precision - case 0x3A: // double / Double precision - case 0x48: // array / Array - case 0x49: // struct / Structure - case 0x50: // set / Set - case 0x51: // bag / Bag - case 0xE0: // ToD / Time of day - { - ChipLogError(Zcl, "attributeType 0x%02x is not supported", attributeType); - return true; - } - - case 0x41: // octstr / Octet string - case 0x42: // string / Character string - { - // Short Strings must contains at least one byte for the length - CHECK_MESSAGE_LENGTH(1); - uint8_t length = Encoding::Read8(message); - ChipLogProgress(Zcl, " length: 0x%02x", length); - - // When the length is set to 0xFF, it represents a non-value. In this case the data field is zero length. - if (length == 0xFF) - { - length = 0; - } - - CHECK_MESSAGE_LENGTH(length); - if (attributeType == 0x41) - { - Callback::Callback * cb = Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - else - { - Callback::Callback * cb = Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - break; - } - - case 0x43: // octstr16 / Long octet string - case 0x44: // string16 / Long character string - { - // Long Strings must contains at least two bytes for the length - CHECK_MESSAGE_LENGTH(2); - uint16_t length = Encoding::LittleEndian::Read16(message); - ChipLogProgress(Zcl, " length: 0x%02x", length); - - // When the length is set to 0xFFFF, it represents a non-value. In this case the data field is zero length. - if (length == 0xFFFF) - { - length = 0; - } - - CHECK_MESSAGE_LENGTH(length); - if (attributeType == 0x43) - { - Callback::Callback * cb = Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - else - { - Callback::Callback * cb = Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - break; - } - - case 0x08: // data8 / 8-bit data - case 0x18: // map8 / 8-bit bitmap - case 0x20: // uint8 / Unsigned 8-bit integer - case 0x30: // enum8 / 8-bit enumeration - { - CHECK_MESSAGE_LENGTH(1); - uint8_t value = Encoding::Read8(message); - ChipLogProgress(Zcl, " value: 0x%02x", value); - - Callback::Callback * cb = Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x09: // data16 / 16-bit data - case 0x19: // map16 / 16-bit bitmap - case 0x21: // uint16 / Unsigned 16-bit integer - case 0x31: // enum16 / 16-bit enumeration - case 0xE8: // clusterId / Cluster ID - case 0xE9: // attribId / Attribute ID - case 0xEA: // bacOID / BACnet OID - case 0xF1: // key128 / 128-bit security key - case 0xFF: // unk / Unknown - { - CHECK_MESSAGE_LENGTH(2); - uint16_t value = Encoding::LittleEndian::Read16(message); - ChipLogProgress(Zcl, " value: 0x%04x", value); - - Callback::Callback * cb = Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x0B: // data32 / 32-bit data - case 0x1B: // map32 / 32-bit bitmap - case 0x23: // uint32 / Unsigned 32-bit integer - case 0xE1: // date / Date - case 0xE2: // UTC / UTCTime - { - CHECK_MESSAGE_LENGTH(4); - uint32_t value = Encoding::LittleEndian::Read32(message); - ChipLogProgress(Zcl, " value: 0x%08x", value); - - Callback::Callback * cb = Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x0F: // data64 / 64-bit data - case 0x1F: // map64 / 64-bit bitmap - case 0x27: // uint64 / Unsigned 64-bit integer - case 0xF0: // EUI64 / IEEE address - { - CHECK_MESSAGE_LENGTH(8); - uint64_t value = Encoding::LittleEndian::Read64(message); - ChipLogProgress(Zcl, " value: 0x" ChipLogFormatX64, ChipLogValueX64(value)); - - Callback::Callback * cb = Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x10: // bool / Boolean - { - CHECK_MESSAGE_LENGTH(1); - uint8_t value = Encoding::Read8(message); - ChipLogProgress(Zcl, " value: %d", value); - - Callback::Callback * cb = Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x28: // int8 / Signed 8-bit integer - { - CHECK_MESSAGE_LENGTH(1); - int8_t value = CastToSigned(Encoding::Read8(message)); - ChipLogProgress(Zcl, " value: %" PRId8, value); - - Callback::Callback * cb = Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x29: // int16 / Signed 16-bit integer - { - CHECK_MESSAGE_LENGTH(2); - int16_t value = CastToSigned(Encoding::LittleEndian::Read16(message)); - ChipLogProgress(Zcl, " value: %" PRId16, value); - - Callback::Callback * cb = Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x2B: // int32 / Signed 32-bit integer - { - CHECK_MESSAGE_LENGTH(4); - int32_t value = CastToSigned(Encoding::LittleEndian::Read32(message)); - ChipLogProgress(Zcl, " value: %" PRId32, value); - - Callback::Callback * cb = Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x2F: // int64 / Signed 64-bit integer - { - CHECK_MESSAGE_LENGTH(8); - int64_t value = CastToSigned(Encoding::LittleEndian::Read64(message)); - ChipLogProgress(Zcl, " value: %" PRId64, value); - - Callback::Callback * cb = Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - } - } - - return true; -} {{/if}} diff --git a/src/app/zap-templates/templates/app/CHIPClusters-src.zapt b/src/app/zap-templates/templates/app/CHIPClusters-src.zapt index 2cdab62e764bbf..fa6dc463e1a284 100644 --- a/src/app/zap-templates/templates/app/CHIPClusters-src.zapt +++ b/src/app/zap-templates/templates/app/CHIPClusters-src.zapt @@ -52,9 +52,7 @@ namespace { // Pick source endpoint as 1 for now constexpr EndpointId kSourceEndpoint = 1; - - [[maybe_unused]] const uint8_t kReportingDirectionReported = 0x00; -} // namespace +} using namespace app::Clusters; using namespace System; @@ -161,24 +159,18 @@ CHIP_ERROR {{asUpperCamelCase parent.name}}Cluster::WriteAttribute{{asUpperCamel {{#if isReportableAttribute}} CHIP_ERROR {{asUpperCamelCase parent.name}}Cluster::ConfigureAttribute{{asUpperCamelCase name}}(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval{{#if isAnalog}}, {{chipType}} change{{/if}}) { - COMMAND_HEADER("Report{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}", {{asUpperCamelCase parent.name}}::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32({{#if isGlobalAttribute}}Globals{{else}}{{asUpperCamelCase parent.name}}{{/if}}::Attributes::Ids::{{asUpperCamelCase name}}) - .Put8({{atomicTypeId}}) - .Put16(minInterval) - .Put16(maxInterval); - {{#if isAnalog}} - buf.Put{{chipTypePutLength}}(static_cast<{{chipTypePutCastType}}>(change)); - {{/if}} - COMMAND_FOOTER(); + {{#if isAnalog}}IgnoreUnusedVariable(change);{{/if}} + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = {{#if isGlobalAttribute}}Globals{{else}}{{asUpperCamelCase parent.name}}{{/if}}::Attributes::Ids::{{asUpperCamelCase name}}; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR {{asUpperCamelCase parent.name}}Cluster::ReportAttribute{{asUpperCamelCase name}}(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting({{asHex code 4}}, onReportCallback); + return RequestAttributeReporting({{#if isGlobalAttribute}}Globals{{else}}{{asUpperCamelCase parent.name}}{{/if}}::Attributes::Ids::{{asUpperCamelCase name}}, onReportCallback, BasicAttributeFilter<{{chipCallback.name}}AttributeCallback>); } {{/if}} diff --git a/src/app/zap-templates/templates/app/helper.js b/src/app/zap-templates/templates/app/helper.js index 22e39b6a8d395d..cf5d8588127270 100644 --- a/src/app/zap-templates/templates/app/helper.js +++ b/src/app/zap-templates/templates/app/helper.js @@ -335,16 +335,22 @@ function asMEI(prefix, suffix) return cHelper.asHex((prefix << 16) + suffix, 8); } +function asTestSuiteSimulatedClusterCommandPartial(label) +{ + return "TestSuiteHelper_" + asUpperCamelCase(label) +} + // // Module exports // -exports.asPrintFormat = asPrintFormat; -exports.asReadType = asReadType; -exports.asReadTypeLength = asReadTypeLength; -exports.chip_endpoint_generated_functions = chip_endpoint_generated_functions -exports.chip_endpoint_cluster_list = chip_endpoint_cluster_list -exports.asTypeLiteralSuffix = asTypeLiteralSuffix; -exports.asLowerCamelCase = asLowerCamelCase; -exports.asUpperCamelCase = asUpperCamelCase; -exports.hasSpecificAttributes = hasSpecificAttributes; -exports.asMEI = asMEI; +exports.asPrintFormat = asPrintFormat; +exports.asReadType = asReadType; +exports.asReadTypeLength = asReadTypeLength; +exports.chip_endpoint_generated_functions = chip_endpoint_generated_functions +exports.chip_endpoint_cluster_list = chip_endpoint_cluster_list +exports.asTypeLiteralSuffix = asTypeLiteralSuffix; +exports.asLowerCamelCase = asLowerCamelCase; +exports.asUpperCamelCase = asUpperCamelCase; +exports.hasSpecificAttributes = hasSpecificAttributes; +exports.asMEI = asMEI; +exports.asTestSuiteSimulatedClusterCommandPartial = asTestSuiteSimulatedClusterCommandPartial; diff --git a/src/controller/CHIPCluster.cpp b/src/controller/CHIPCluster.cpp index 35ab120a99f438..7ee70683767e3f 100644 --- a/src/controller/CHIPCluster.cpp +++ b/src/controller/CHIPCluster.cpp @@ -80,10 +80,12 @@ CHIP_ERROR ClusterBase::SendCommand(uint8_t seqNum, chip::System::PacketBufferHa return err; } -CHIP_ERROR ClusterBase::RequestAttributeReporting(AttributeId attributeId, Callback::Cancelable * onReportCallback) +CHIP_ERROR ClusterBase::RequestAttributeReporting(AttributeId attributeId, Callback::Cancelable * onReportCallback, + app::TLVDataFilter tlvDataFilter) { VerifyOrReturnError(onReportCallback != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - mDevice->AddReportHandler(mEndpoint, mClusterId, attributeId, onReportCallback); + VerifyOrReturnError(tlvDataFilter != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + mDevice->AddReportHandler(mEndpoint, mClusterId, attributeId, onReportCallback, tlvDataFilter); return CHIP_NO_ERROR; } diff --git a/src/controller/CHIPCluster.h b/src/controller/CHIPCluster.h index 2f3451502c1039..b1d5e061f5e6da 100644 --- a/src/controller/CHIPCluster.h +++ b/src/controller/CHIPCluster.h @@ -68,8 +68,10 @@ class DLL_EXPORT ClusterBase * The reporting handler continues to be called as long as the callback * is active. The user can stop the reporting by cancelling the callback. * Reference: chip::Callback::Cancel() + * @param[in] tlvDataFilter Filter interface for processing data from TLV */ - CHIP_ERROR RequestAttributeReporting(AttributeId attributeId, Callback::Cancelable * reportHandler); + CHIP_ERROR RequestAttributeReporting(AttributeId attributeId, Callback::Cancelable * reportHandler, + app::TLVDataFilter tlvDataFilter); const ClusterId mClusterId; Device * mDevice; diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index ce621a161798bb..52a8e42f328881 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -688,9 +688,9 @@ void Device::CancelIMResponseHandler(app::CommandSender * commandObj) } void Device::AddReportHandler(EndpointId endpoint, ClusterId cluster, AttributeId attribute, - Callback::Cancelable * onReportCallback) + Callback::Cancelable * onReportCallback, app::TLVDataFilter tlvDataFilter) { - mCallbacksMgr.AddReportCallback(mDeviceId, endpoint, cluster, attribute, onReportCallback); + mCallbacksMgr.AddReportCallback(mDeviceId, endpoint, cluster, attribute, onReportCallback, tlvDataFilter); } CHIP_ERROR Device::SendReadAttributeRequest(app::AttributePathParams aPath, Callback::Cancelable * onSuccessCallback, @@ -706,7 +706,7 @@ CHIP_ERROR Device::SendReadAttributeRequest(app::AttributePathParams aPath, Call { AddResponseHandler(seqNum, onSuccessCallback, onFailureCallback, aTlvDataFilter); } - // The application context is used to identify different requests from client applicaiton the type of it is intptr_t, here we + // The application context is used to identify different requests from client application the type of it is intptr_t, here we // use the seqNum. chip::app::ReadPrepareParams readPrepareParams(mSecureSession.Value()); readPrepareParams.mpAttributePathParamsList = &aPath; @@ -720,6 +720,45 @@ CHIP_ERROR Device::SendReadAttributeRequest(app::AttributePathParams aPath, Call return err; } +CHIP_ERROR Device::SendSubscribeAttributeRequest(app::AttributePathParams aPath, uint16_t mMinIntervalFloorSeconds, + uint16_t mMaxIntervalCeilingSeconds, Callback::Cancelable * onSuccessCallback, + Callback::Cancelable * onFailureCallback) +{ + bool loadedSecureSession = false; + uint8_t seqNum = GetNextSequenceNumber(); + aPath.mNodeId = GetDeviceId(); + + ReturnErrorOnFailure(LoadSecureSessionParametersIfNeeded(loadedSecureSession)); + + app::AttributePathParams * path = mpIMDelegate->AllocateAttributePathParam(1, seqNum); + + VerifyOrReturnError(path != nullptr, CHIP_ERROR_NO_MEMORY); + + *path = aPath; + + // The application context is used to identify different requests from client application the type of it is intptr_t, here we + // use the seqNum. + app::ReadPrepareParams params(GetSecureSession()); + params.mpAttributePathParamsList = path; + params.mAttributePathParamsListSize = 1; + params.mMinIntervalFloorSeconds = mMinIntervalFloorSeconds; + params.mMaxIntervalCeilingSeconds = mMaxIntervalCeilingSeconds; + + CHIP_ERROR err = + chip::app::InteractionModelEngine::GetInstance()->SendSubscribeRequest(params, seqNum /* application context */); + if (err != CHIP_NO_ERROR) + { + mpIMDelegate->FreeAttributePathParam(seqNum); + return err; + } + + if (onSuccessCallback != nullptr || onFailureCallback != nullptr) + { + AddResponseHandler(seqNum, onSuccessCallback, onFailureCallback); + } + return CHIP_NO_ERROR; +} + CHIP_ERROR Device::SendWriteAttributeRequest(app::WriteClientHandle aHandle, Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index 2934523d34dd65..73c7cbb54e2bb5 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -87,7 +88,8 @@ struct ControllerDeviceInitParams #if CONFIG_NETWORK_LAYER_BLE Ble::BleLayer * bleLayer = nullptr; #endif - Transport::FabricTable * fabricsTable = nullptr; + Transport::FabricTable * fabricsTable = nullptr; + DeviceControllerInteractionModelDelegate * imDelegate = nullptr; }; class Device; @@ -150,6 +152,10 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta CHIP_ERROR SendReadAttributeRequest(app::AttributePathParams aPath, Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, app::TLVDataFilter aTlvDataFilter); + CHIP_ERROR SendSubscribeAttributeRequest(app::AttributePathParams aPath, uint16_t mMinIntervalFloorSeconds, + uint16_t mMaxIntervalCeilingSeconds, Callback::Cancelable * onSuccessCallback, + Callback::Cancelable * onFailureCallback); + CHIP_ERROR SendWriteAttributeRequest(app::WriteClientHandle aHandle, Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback); @@ -196,6 +202,7 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta mStorageDelegate = params.storageDelegate; mIDAllocator = params.idAllocator; mFabricsTable = params.fabricsTable; + mpIMDelegate = params.imDelegate; #if CONFIG_NETWORK_LAYER_BLE mBleLayer = params.bleLayer; #endif @@ -377,10 +384,11 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta void AddResponseHandler(uint8_t seqNum, Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, app::TLVDataFilter tlvDataFilter = nullptr); void CancelResponseHandler(uint8_t seqNum); - void AddReportHandler(EndpointId endpoint, ClusterId cluster, AttributeId attribute, Callback::Cancelable * onReportCallback); + void AddReportHandler(EndpointId endpoint, ClusterId cluster, AttributeId attribute, Callback::Cancelable * onReportCallback, + app::TLVDataFilter tlvDataFilter); - // This two functions are pretty tricky, it is used to bridge the response, we need to implement interaction model delegate on - // the app side instead of register callbacks here. The IM delegate can provide more infomation then callback and it is + // This two functions are pretty tricky, it is used to bridge the response, we need to implement interaction model delegate + // on the app side instead of register callbacks here. The IM delegate can provide more infomation then callback and it is // type-safe. // TODO: Implement interaction model delegate in the application. void AddIMResponseHandler(app::CommandSender * commandObj, Callback::Cancelable * onSuccessCallback, @@ -475,6 +483,8 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta Optional mSecureSession = Optional::Missing(); + DeviceControllerInteractionModelDelegate * mpIMDelegate = nullptr; + uint8_t mSequenceNumber = 0; uint32_t mLocalMessageCounter = 0; diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 1c497ece4e92a3..4f7662a5b2b037 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -177,13 +177,14 @@ CHIP_ERROR DeviceController::Init(ControllerInitParams params) if (params.imDelegate != nullptr) { - ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->Init(mExchangeMgr, params.imDelegate)); + mInteractionModelDelegate = params.imDelegate; } else { - mDefaultIMDelegate = chip::Platform::New(); - ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->Init(mExchangeMgr, mDefaultIMDelegate)); + mDefaultIMDelegate = chip::Platform::New(); + mInteractionModelDelegate = mDefaultIMDelegate; } + ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->Init(mExchangeMgr, mInteractionModelDelegate)); mExchangeMgr->SetDelegate(this); @@ -715,6 +716,7 @@ ControllerDeviceInitParams DeviceController::GetControllerDeviceInitParams() .storageDelegate = mStorageDelegate, .idAllocator = &mIDAllocator, .fabricsTable = &mFabrics, + .imDelegate = mInteractionModelDelegate, }; } @@ -1641,6 +1643,16 @@ CHIP_ERROR DeviceControllerInteractionModelDelegate::ReadError(const app::ReadCl return CHIP_NO_ERROR; } +CHIP_ERROR DeviceControllerInteractionModelDelegate::ReadDone(const app::ReadClient * apReadClient) +{ + // Release the object for subscription + if (apReadClient->IsSubscriptionType()) + { + FreeAttributePathParam(apReadClient->GetAppIdentifier()); + } + return CHIP_NO_ERROR; +} + CHIP_ERROR DeviceControllerInteractionModelDelegate::WriteResponseStatus( const app::WriteClient * apWriteClient, const Protocols::SecureChannel::GeneralStatusCode aGeneralCode, const uint32_t aProtocolId, const uint16_t aProtocolCode, app::AttributePathParams & aAttributePathParams, @@ -1665,6 +1677,15 @@ CHIP_ERROR DeviceControllerInteractionModelDelegate::WriteResponseError(const ap return CHIP_NO_ERROR; } +CHIP_ERROR DeviceControllerInteractionModelDelegate::SubscribeResponseProcessed(const app::ReadClient * apSubscribeClient) +{ +#if !CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE // temporary - until example app clusters are updated (Issue 8347) + // When WriteResponseError occurred, it means we failed to receive the response from server. + IMSubscribeResponseCallback(apSubscribeClient, EMBER_ZCL_STATUS_SUCCESS); +#endif + return CHIP_NO_ERROR; +} + void BasicSuccess(void * context, uint16_t val) { ChipLogProgress(Controller, "Received success response 0x%x\n", val); diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index e9f16b07f06eb9..79a2966e09a4a4 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -86,7 +87,7 @@ struct ControllerInitParams #if CONFIG_NETWORK_LAYER_BLE Ble::BleLayer * bleLayer = nullptr; #endif - app::InteractionModelDelegate * imDelegate = nullptr; + DeviceControllerInteractionModelDelegate * imDelegate = nullptr; #if CHIP_DEVICE_CONFIG_ENABLE_MDNS DeviceAddressUpdateDelegate * mDeviceAddressUpdateDelegate = nullptr; #endif @@ -173,39 +174,6 @@ struct CommissionerInitParams : public ControllerInitParams DevicePairingDelegate * pairingDelegate = nullptr; }; -/** - * @brief - * Used for make current OnSuccessCallback & OnFailureCallback works when interaction model landed, it will be removed - * after #6308 is landed. - */ -class DeviceControllerInteractionModelDelegate : public chip::app::InteractionModelDelegate -{ -public: - CHIP_ERROR CommandResponseStatus(const app::CommandSender * apCommandSender, - const Protocols::SecureChannel::GeneralStatusCode aGeneralCode, const uint32_t aProtocolId, - const uint16_t aProtocolCode, chip::EndpointId aEndpointId, const chip::ClusterId aClusterId, - chip::CommandId aCommandId, uint8_t aCommandIndex) override; - - CHIP_ERROR CommandResponseProtocolError(const app::CommandSender * apCommandSender, uint8_t aCommandIndex) override; - - CHIP_ERROR CommandResponseError(const app::CommandSender * apCommandSender, CHIP_ERROR aError) override; - - CHIP_ERROR CommandResponseProcessed(const app::CommandSender * apCommandSender) override; - - void OnReportData(const app::ReadClient * apReadClient, const app::ClusterInfo & aPath, TLV::TLVReader * apData, - Protocols::InteractionModel::ProtocolCode status) override; - CHIP_ERROR ReadError(const app::ReadClient * apReadClient, CHIP_ERROR aError) override; - - CHIP_ERROR WriteResponseStatus(const app::WriteClient * apWriteClient, - const Protocols::SecureChannel::GeneralStatusCode aGeneralCode, const uint32_t aProtocolId, - const uint16_t aProtocolCode, app::AttributePathParams & aAttributePathParams, - uint8_t aCommandIndex) override; - - CHIP_ERROR WriteResponseProtocolError(const app::WriteClient * apWriteClient, uint8_t aAttributeIndex) override; - - CHIP_ERROR WriteResponseError(const app::WriteClient * apWriteClient, CHIP_ERROR aError) override; -}; - /** * @brief * Controller applications can use this class to communicate with already paired CHIP devices. The @@ -303,6 +271,8 @@ class DLL_EXPORT DeviceController : public Messaging::ExchangeDelegate, */ uint64_t GetFabricId() const { return mFabricId; } + DeviceControllerInteractionModelDelegate * GetInteractionModelDelegate() { return mInteractionModelDelegate; } + protected: enum class State { @@ -340,7 +310,8 @@ class DLL_EXPORT DeviceController : public Messaging::ExchangeDelegate, #if CONFIG_NETWORK_LAYER_BLE Ble::BleLayer * mBleLayer = nullptr; #endif - System::Layer * mSystemLayer = nullptr; + System::Layer * mSystemLayer = nullptr; + DeviceControllerInteractionModelDelegate * mInteractionModelDelegate = nullptr; uint16_t mListenPort; uint16_t GetInactiveDeviceIndex(); diff --git a/src/controller/DeviceControllerInteractionModelDelegate.h b/src/controller/DeviceControllerInteractionModelDelegate.h new file mode 100644 index 00000000000000..1a0c23f6f37bda --- /dev/null +++ b/src/controller/DeviceControllerInteractionModelDelegate.h @@ -0,0 +1,86 @@ +#pragma once + +#include + +#include + +namespace chip { +namespace Controller { +/** + * @brief + * Used for make current OnSuccessCallback & OnFailureCallback works when interaction model landed, it will be removed + * after #6308 is landed. + */ +class DeviceControllerInteractionModelDelegate : public chip::app::InteractionModelDelegate +{ +public: + CHIP_ERROR CommandResponseStatus(const app::CommandSender * apCommandSender, + const Protocols::SecureChannel::GeneralStatusCode aGeneralCode, const uint32_t aProtocolId, + const uint16_t aProtocolCode, chip::EndpointId aEndpointId, const chip::ClusterId aClusterId, + chip::CommandId aCommandId, uint8_t aCommandIndex) override; + + CHIP_ERROR CommandResponseProtocolError(const app::CommandSender * apCommandSender, uint8_t aCommandIndex) override; + + CHIP_ERROR CommandResponseError(const app::CommandSender * apCommandSender, CHIP_ERROR aError) override; + + CHIP_ERROR CommandResponseProcessed(const app::CommandSender * apCommandSender) override; + + void OnReportData(const app::ReadClient * apReadClient, const app::ClusterInfo & aPath, TLV::TLVReader * apData, + Protocols::InteractionModel::ProtocolCode status) override; + CHIP_ERROR ReadError(const app::ReadClient * apReadClient, CHIP_ERROR aError) override; + + CHIP_ERROR WriteResponseStatus(const app::WriteClient * apWriteClient, + const Protocols::SecureChannel::GeneralStatusCode aGeneralCode, const uint32_t aProtocolId, + const uint16_t aProtocolCode, app::AttributePathParams & aAttributePathParams, + uint8_t aCommandIndex) override; + + CHIP_ERROR WriteResponseProtocolError(const app::WriteClient * apWriteClient, uint8_t aAttributeIndex) override; + + CHIP_ERROR WriteResponseError(const app::WriteClient * apWriteClient, CHIP_ERROR aError) override; + + CHIP_ERROR SubscribeResponseProcessed(const app::ReadClient * apSubscribeClient) override; + + CHIP_ERROR ReadDone(const app::ReadClient * apReadClient) override; + + // TODO: FreeAttributePathParam and AllocateAttributePathParam are used by CHIPDevice.cpp for getting a long-live attribute path + // object. + void FreeAttributePathParam(uint64_t applicationId) + { + for (auto & item : mAttributePathTransactionMapPool) + { + if (item.ApplicationId == applicationId) + { + item.ApplicationId = UINT64_MAX; + } + } + } + + // TODO: We only support allocating one path, should support multiple path later. + app::AttributePathParams * AllocateAttributePathParam(size_t n, uint64_t applicationId) + { + if (n > 1) + { + return nullptr; + } + for (auto & item : mAttributePathTransactionMapPool) + { + if (item.ApplicationId == UINT64_MAX) + { + item.ApplicationId = applicationId; + return &item.Params; + } + } + return nullptr; + } + +private: + struct AttributePathTransactionMap + { + uint64_t ApplicationId = UINT64_MAX; + app::AttributePathParams Params; + }; + AttributePathTransactionMap mAttributePathTransactionMapPool[CHIP_DEVICE_CONTROLLER_SUBSCRIPTION_ATTRIBUTE_PATH_POOL_SIZE]; +}; + +} // namespace Controller +} // namespace chip diff --git a/src/controller/python/chip/interaction_model/Delegate.cpp b/src/controller/python/chip/interaction_model/Delegate.cpp index b51e00f607b3ef..c65bdd151d3e18 100644 --- a/src/controller/python/chip/interaction_model/Delegate.cpp +++ b/src/controller/python/chip/interaction_model/Delegate.cpp @@ -126,8 +126,9 @@ void PythonInteractionModelDelegate::OnReportData(const app::ReadClient * apRead { AttributePath path{ .endpointId = aPath.mEndpointId, .clusterId = aPath.mClusterId, .fieldId = aPath.mFieldId }; onReportDataFunct(apReadClient->GetExchangeContext()->GetSecureSession().GetPeerNodeId(), - apReadClient->GetAppIdentifier(), &path, sizeof(path), writerBuffer, writer.GetLengthWritten(), - to_underlying(status)); + apReadClient->GetAppIdentifier(), + /* TODO: Use real SubscriptionId */ apReadClient->IsSubscriptionType() ? 1 : 0, &path, sizeof(path), + writerBuffer, writer.GetLengthWritten(), to_underlying(status)); } else { diff --git a/src/controller/python/chip/interaction_model/Delegate.h b/src/controller/python/chip/interaction_model/Delegate.h index 0dea367a4b7122..ed34a7aa629aee 100644 --- a/src/controller/python/chip/interaction_model/Delegate.h +++ b/src/controller/python/chip/interaction_model/Delegate.h @@ -79,8 +79,9 @@ typedef void (*PythonInteractionModelDelegate_OnCommandResponseFunct)(uint64_t c typedef void (*PythonInteractionModelDelegate_OnWriteResponseStatusFunct)(void * writeStatusBuf, uint32_t writeStatusBufLen); typedef void (*PythonInteractionModelDelegate_OnReportDataFunct)(chip::NodeId nodeId, uint64_t readClientAppIdentifier, - void * attributePathBuf, size_t attributePathBufLen, - uint8_t * readTlvData, size_t readTlvDataLen, uint16_t statusCode); + uint64_t subscriptionId, void * attributePathBuf, + size_t attributePathBufLen, uint8_t * readTlvData, + size_t readTlvDataLen, uint16_t statusCode); void pychip_InteractionModelDelegate_SetCommandResponseStatusCallback( PythonInteractionModelDelegate_OnCommandResponseStatusCodeReceivedFunct f); diff --git a/src/controller/python/chip/interaction_model/__init__.py b/src/controller/python/chip/interaction_model/__init__.py index 506ecac01dc6e0..30fdb1738469eb 100644 --- a/src/controller/python/chip/interaction_model/__init__.py +++ b/src/controller/python/chip/interaction_model/__init__.py @@ -22,6 +22,8 @@ """Provides Python APIs for CHIP.""" from construct.core import EnumInteger + +from .delegate import OnSubscriptionReport, SetAttributeReportCallback, AttributePath __all__ = ["IMDelegate", "ProtocolCode"] diff --git a/src/controller/python/chip/interaction_model/delegate.py b/src/controller/python/chip/interaction_model/delegate.py index b48a86da5398fd..7f40a0f5f029a1 100644 --- a/src/controller/python/chip/interaction_model/delegate.py +++ b/src/controller/python/chip/interaction_model/delegate.py @@ -14,6 +14,7 @@ limitations under the License. ''' +from abc import abstractmethod from construct import Struct, Int64ul, Int32ul, Int16ul, Int8ul from ctypes import CFUNCTYPE, c_void_p, c_uint32, c_uint64, c_uint8, c_uint16, c_ssize_t import ctypes @@ -86,7 +87,7 @@ class AttributeWriteResult: _OnCommandResponseProtocolErrorFunct = CFUNCTYPE(None, c_uint64, c_uint8) _OnCommandResponseFunct = CFUNCTYPE(None, c_uint64, c_uint32) _OnReportDataFunct = CFUNCTYPE( - None, c_uint64, c_ssize_t, c_void_p, c_uint32, c_void_p, c_uint32, c_uint16) + None, c_uint64, c_uint64, c_ssize_t, c_void_p, c_uint32, c_void_p, c_uint32, c_uint16) _OnWriteResponseStatusFunct = CFUNCTYPE(None, c_void_p, c_uint32) _commandStatusDict = dict() @@ -105,6 +106,14 @@ class AttributeWriteResult: DEFAULT_ATTRIBUTEREAD_APPID = 0 DEFAULT_ATTRIBUTEWRITE_APPID = 0 +_onSubscriptionReport = None + + +class OnSubscriptionReport: + @abstractmethod + def OnData(self, path: AttributePath, subscriptionId: int, data: typing.Any) -> None: + pass + def _GetCommandStatus(commandHandle: int): with _commandStatusLock: @@ -151,7 +160,8 @@ def _OnCommandResponse(commandHandle: int, errorcode: int): @ _OnReportDataFunct -def _OnReportData(nodeId: int, appId: int, attrPathBuf, attrPathBufLen: int, tlvDataBuf, tlvDataBufLen: int, statusCode: int): +def _OnReportData(nodeId: int, appId: int, subscriptionId: int, attrPathBuf, attrPathBufLen: int, tlvDataBuf, tlvDataBufLen: int, statusCode: int): + global _onSubscriptionReport attrPath = AttributePathStruct.parse( ctypes.string_at(attrPathBuf, attrPathBufLen)) tlvData = None @@ -166,6 +176,10 @@ def _OnReportData(nodeId: int, appId: int, attrPathBuf, attrPathBufLen: int, tlv # For all attribute read requests using CHIPCluster API, appId is filled by CHIPDevice, and should be smaller than 256 (UINT8_MAX). appId = DEFAULT_ATTRIBUTEREAD_APPID + if subscriptionId != 0: + if _onSubscriptionReport: + _onSubscriptionReport.OnData(path, subscriptionId, tlvData) + with _attributeDictLock: _attributeDict[appId] = AttributeReadResult( path, statusCode, tlvData) @@ -276,3 +290,8 @@ def GetAttributeReadResponse(appId: int) -> AttributeReadResult: def GetAttributeWriteResponse(appId: int) -> AttributeWriteResult: with _writeStatusDictLock: return _writeStatusDict.get(appId, None) + + +def SetAttributeReportCallback(path: AttributePath, callback: OnSubscriptionReport): + global _onSubscriptionReport + _onSubscriptionReport = callback diff --git a/src/controller/python/test/test_scripts/base.py b/src/controller/python/test/test_scripts/base.py index 397f9c9789834b..cdf1c7ad7b7fa4 100644 --- a/src/controller/python/test/test_scripts/base.py +++ b/src/controller/python/test/test_scripts/base.py @@ -17,6 +17,7 @@ from dataclasses import dataclass from typing import Any +import typing from chip import ChipDeviceCtrl import chip.interaction_model as IM import threading @@ -236,6 +237,60 @@ class AttributeWriteRequest: return False return True + def TestSubscription(self, nodeid: int, endpoint: int): + class _subscriptionHandler(IM.OnSubscriptionReport): + def __init__(self, path: IM.AttributePath, logger: logging.Logger): + super(_subscriptionHandler, self).__init__() + self.subscriptionReceived = 0 + self.path = path + self.countLock = threading.Lock() + self.cv = threading.Condition(self.countLock) + self.logger = logger + + def OnData(self, path: IM.AttributePath, subscriptionId: int, data: typing.Any) -> None: + if path != self.path: + return + logger.info( + f"Received report from server: path: {path}, value: {data}, subscriptionId: {subscriptionId}") + with self.countLock: + self.subscriptionReceived += 1 + self.cv.notify_all() + + class _conductAttributeChange(threading.Thread): + def __init__(self, devCtrl: ChipDeviceCtrl.ChipDeviceController, nodeid: int, endpoint: int): + super(_conductAttributeChange, self).__init__() + self.nodeid = nodeid + self.endpoint = endpoint + self.devCtrl = devCtrl + + def run(self): + for i in range(5): + time.sleep(3) + self.devCtrl.ZCLSend( + "OnOff", "Toggle", self.nodeid, self.endpoint, 0, {}) + + try: + subscribedPath = IM.AttributePath( + nodeId=nodeid, endpointId=endpoint, clusterId=6, attributeId=0) + # OnOff Cluster, OnOff Attribute + handler = _subscriptionHandler(subscribedPath, self.logger) + IM.SetAttributeReportCallback(subscribedPath, handler) + self.devCtrl.ZCLConfigureAttribute( + "OnOff", "OnOff", nodeid, endpoint, 1, 10, 0) + changeThread = _conductAttributeChange( + self.devCtrl, nodeid, endpoint) + changeThread.start() + with handler.cv: + while handler.subscriptionReceived < 5: + # We should observe 10 attribute changes + handler.cv.wait() + return True + except Exception as ex: + self.logger.exception(f"Failed to finish API test: {ex}") + return False + + return True + def TestNonControllerAPIs(self): ''' This function validates various APIs provided by chip package which is not related to controller. diff --git a/src/controller/python/test/test_scripts/mobile-device-test.py b/src/controller/python/test/test_scripts/mobile-device-test.py index dfcaeeafcda8b7..ec2980fc136455 100755 --- a/src/controller/python/test/test_scripts/mobile-device-test.py +++ b/src/controller/python/test/test_scripts/mobile-device-test.py @@ -108,6 +108,10 @@ def main(): group=GROUP_ID), "Failed to test Write Basic Attributes") + logger.info("Testing subscription") + FailIfNot(test.TestSubscription(nodeid=1, endpoint=LIGHTING_ENDPOINT_ID), + "Failed to subscribe attributes.") + logger.info("Testing closing sessions") FailIfNot(test.TestCloseSession(nodeid=1), "Failed to close sessions") diff --git a/src/darwin/Framework/CHIP/templates/clusters-tests.zapt b/src/darwin/Framework/CHIP/templates/clusters-tests.zapt index 12e90d51d2ade5..8281b816da0379 100644 --- a/src/darwin/Framework/CHIP/templates/clusters-tests.zapt +++ b/src/darwin/Framework/CHIP/templates/clusters-tests.zapt @@ -142,80 +142,7 @@ CHIPDevice * GetPairedDevice(uint64_t deviceId) [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } -- (void)testSendClusterTestCluster_Reporting_0000_BindOnOff_Test -{ - XCTestExpectation * expectation = [self expectationWithDescription:@"Binding to OnOff Cluster complete"]; - CHIPDevice * device = GetPairedDevice(kDeviceId); - dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPBinding * bindingCluster = [[CHIPBinding alloc] initWithDevice:device endpoint:1 queue:queue]; - XCTAssertNotNil(bindingCluster); - [bindingCluster bind:kDeviceId groupId:0 - endpointId:1 - clusterId:6 - responseHandler:^(NSError * err, NSDictionary * values) { - NSLog(@"Reporting Test Binding status : %@", err); - XCTAssertEqual(err.code, 0); - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; -} - -- (void)testSendClusterTestCluster_Reporting_0001_ConfigureOnOff_Test -{ - XCTestExpectation * expectation = [self expectationWithDescription:@"Reporting OnOff configured"]; - CHIPDevice * device = GetPairedDevice(kDeviceId); - dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPOnOff * onOffCluster = [[CHIPOnOff alloc] initWithDevice:device endpoint:1 queue:queue]; - XCTAssertNotNil(onOffCluster); - [onOffCluster configureAttributeOnOffWithMinInterval:0 - maxInterval:1 - responseHandler:^(NSError * err, NSDictionary * values) { - NSLog(@"Reporting Test Configure status: %@", err); - - XCTAssertEqual(err.code, 0); - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; -} - -- (void)testSendClusterTestCluster_Reporting_0002_ReportOnOff_Test -{ - XCTestExpectation * expectation = [self expectationWithDescription:@"First report received"]; - CHIPDevice * device = GetPairedDevice(kDeviceId); - dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPOnOff * onOffCluster = [[CHIPOnOff alloc] initWithDevice:device endpoint:1 queue:queue]; - XCTAssertNotNil(onOffCluster); - [onOffCluster reportAttributeOnOffWithResponseHandler:^(NSError * err, NSDictionary * values) - { - NSLog(@"Reporting Test Report first report: %@", err); - [expectation fulfill]; - XCTAssertEqual(err.code, 0); - }]; - - [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; -} - -- (void)testSendClusterTestCluster_Reporting_0003_StopReportOnOff_Test -{ - XCTestExpectation * expectation = [self expectationWithDescription:@"Reporting OnOff cancelled"]; - CHIPDevice * device = GetPairedDevice(kDeviceId); - dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPOnOff * onOffCluster = [[CHIPOnOff alloc] initWithDevice:device endpoint:1 queue:queue]; - XCTAssertNotNil(onOffCluster); - [onOffCluster configureAttributeOnOffWithMinInterval:0 - maxInterval:0xffff - responseHandler:^(NSError * err, NSDictionary * values) { - NSLog(@"Reporting Test Cancel Reports status: %@", err); - - XCTAssertEqual(err.code, 0); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; -} - -{{>test_cluster tests="TestCluster, TestConstraints, TestDelayCommands, Test_TC_OO_1_1, Test_TC_OO_2_1, Test_TC_OO_2_2, Test_TC_DM_1_1, Test_TC_DM_3_1, Test_TC_CC_3_4, Test_TC_CC_5, Test_TC_CC_6, Test_TC_CC_7, Test_TC_CC_8, Test_TC_WNCV_1_1, Test_TC_WNCV_2_1, Test_TC_BI_1_1, Test_TC_FLW_1_1, Test_TC_TM_1_1, Test_TC_OCC_1_1, OperationalCredentialsCluster"}} +{{>test_cluster tests="TestCluster, TestConstraints, TestDelayCommands, TestSubscribe_OnOff, Test_TC_OO_1_1, Test_TC_OO_2_1, Test_TC_OO_2_2, Test_TC_DM_1_1, Test_TC_DM_3_1, Test_TC_CC_3_4, Test_TC_CC_5, Test_TC_CC_6, Test_TC_CC_7, Test_TC_CC_8, Test_TC_WNCV_1_1, Test_TC_WNCV_2_1, Test_TC_BI_1_1, Test_TC_FLW_1_1, Test_TC_TM_1_1, Test_TC_OCC_1_1, OperationalCredentialsCluster"}} {{#chip_client_clusters}} {{#unless (isStrEqual "Test Cluster" name)}} diff --git a/src/darwin/Framework/CHIP/templates/partials/process_response_value.zapt b/src/darwin/Framework/CHIP/templates/partials/process_response_value.zapt new file mode 100644 index 00000000000000..87927090450d6e --- /dev/null +++ b/src/darwin/Framework/CHIP/templates/partials/process_response_value.zapt @@ -0,0 +1,38 @@ + {{#chip_tests_item_response_parameters}} + {{#if hasExpectedValue}} + {{#if isList}} + XCTAssertEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] count], {{expectedValue.length}}); + {{else}} + {{#if (isString type)}} + {{#if (isOctetString type)}} + NSString * {{asLowerCamelCase name}}ArgumentString= @"{{expectedValue}}"; + NSData * {{asLowerCamelCase name}}Argument = [{{asLowerCamelCase name}}ArgumentString dataUsingEncoding:NSUTF8StringEncoding]; + XCTAssertTrue([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] isEqualToData:{{asLowerCamelCase name}}Argument]); + {{else}} + NSString * {{asLowerCamelCase name}}Argument= @"{{expectedValue}}"; + XCTAssertTrue([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] isEqualToString:{{asLowerCamelCase name}}Argument]); + {{/if}} + {{else}} + XCTAssertEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] {{asObjectiveCNumberType "" type true}}Value], {{expectedValue}}{{asTypeLiteralSuffix}}); + {{/if}} + {{/if}} + {{/if}} + {{#if hasExpectedConstraints}} + {{#if expectedConstraints.minLength}} + XCTAssertGreaterThanOrEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] length], {{expectedConstraints.minLength}}); + {{/if}} + {{#if expectedConstraints.maxLength}} + XCTAssertLessThanOrEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] length], {{expectedConstraints.maxLength}}); + {{/if}} + {{#if expectedConstraints.minValue}} + XCTAssertGreaterThanOrEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] {{asObjectiveCNumberType "" type true}}Value], {{expectedConstraints.minValue}}); + {{/if}} + {{#if expectedConstraints.maxValue}} + XCTAssertLessThanOrEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] {{asObjectiveCNumberType "" type true}}Value], {{expectedConstraints.maxValue}}); + {{/if}} + {{#if expectedConstraints.notValue}} + XCTAssertNotEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] {{asObjectiveCNumberType "" type true}}Value], {{expectedConstraints.notValue}}); + {{/if}} + {{/if}} + {{/chip_tests_item_response_parameters}} + \ No newline at end of file diff --git a/src/darwin/Framework/CHIP/templates/partials/test_cluster.zapt b/src/darwin/Framework/CHIP/templates/partials/test_cluster.zapt index 275ff0635b0405..85c2ab459b505f 100644 --- a/src/darwin/Framework/CHIP/templates/partials/test_cluster.zapt +++ b/src/darwin/Framework/CHIP/templates/partials/test_cluster.zapt @@ -4,8 +4,7 @@ { XCTestExpectation * expectation = [self expectationWithDescription:@"{{label}}"]; {{#if (isTestOnlyCluster cluster)}} - dispatch_queue_t queue = dispatch_get_main_queue(); - {{command}}(expectation, queue{{#chip_tests_item_parameters}}, {{definedValue}}{{/chip_tests_item_parameters}}); +{{> (asTestSuiteSimulatedClusterCommandPartial command)}} {{else}} CHIPDevice * device = GetPairedDevice(kDeviceId); dispatch_queue_t queue = dispatch_get_main_queue(); @@ -29,6 +28,18 @@ {{/if}} {{#if isCommand}} [cluster {{asLowerCamelCase command}}:{{#chip_tests_item_parameters}}{{#not_first}}{{asLowerCamelCase name}}:{{/not_first}}{{asLowerCamelCase name}}Argument {{#last}}responseHandler:{{/last}}{{/chip_tests_item_parameters}}^(NSError * err, NSDictionary * values) { + {{else if isSubscribeAttribute}} + __block bool initialReportReceived = false; + [cluster reportAttribute{{asUpperCamelCase attribute}}WithResponseHandler:^(NSError * err, NSDictionary * values) { + NSLog(@"Reporting Test Report: %@", err); + XCTAssertEqual(err.code, 0); + {{> process_response_value}} + initialReportReceived = true; + }]; + + [cluster configureAttribute{{asUpperCamelCase attribute}}WithMinInterval:{{minInterval}} + maxInterval:{{maxInterval}} + responseHandler:^(NSError * err, NSDictionary * values) { {{else if isReadAttribute}} [cluster readAttribute{{asUpperCamelCase attribute}}WithResponseHandler:^(NSError * err, NSDictionary * values) { {{else if isWriteAttribute}} @@ -47,45 +58,12 @@ {{#unless (isStrEqual "0" response.error)}} [expectation fulfill]; {{else}} - {{#chip_tests_item_response_parameters}} - {{#if hasExpectedValue}} - {{#if isList}} - XCTAssertEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] count], {{expectedValue.length}}); + {{#unless isSubscribeAttribute}} + {{> process_response_value}} {{else}} - {{#if (isString type)}} - {{#if (isOctetString type)}} - NSString * {{asLowerCamelCase name}}ArgumentString= @"{{expectedValue}}"; - NSData * {{asLowerCamelCase name}}Argument = [{{asLowerCamelCase name}}ArgumentString dataUsingEncoding:NSUTF8StringEncoding]; - XCTAssertTrue([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] isEqualToData:{{asLowerCamelCase name}}Argument]); - {{else}} - NSString * {{asLowerCamelCase name}}Argument= @"{{expectedValue}}"; - XCTAssertTrue([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] isEqualToString:{{asLowerCamelCase name}}Argument]); - {{/if}} - {{else}} - XCTAssertEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] {{asObjectiveCNumberType "" type true}}Value], {{expectedValue}}{{asTypeLiteralSuffix}}); - {{/if}} - {{/if}} - {{/if}} - {{#if hasExpectedConstraints}} - {{#if expectedConstraints.minLength}} - XCTAssertGreaterThanOrEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] length], {{expectedConstraints.minLength}}); - {{/if}} - {{#if expectedConstraints.maxLength}} - XCTAssertLessThanOrEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] length], {{expectedConstraints.maxLength}}); - {{/if}} - {{#if expectedConstraints.minValue}} - XCTAssertGreaterThanOrEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] {{asObjectiveCNumberType "" type true}}Value], {{expectedConstraints.minValue}}); - {{/if}} - {{#if expectedConstraints.maxValue}} - XCTAssertLessThanOrEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] {{asObjectiveCNumberType "" type true}}Value], {{expectedConstraints.maxValue}}); - {{/if}} - {{#if expectedConstraints.notValue}} - XCTAssertNotEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] {{asObjectiveCNumberType "" type true}}Value], {{expectedConstraints.notValue}}); - {{/if}} - {{/if}} - {{/chip_tests_item_response_parameters}} + XCTAssertEqual(initialReportReceived, true); + {{/unless}} [expectation fulfill]; - {{/unless}} }]; diff --git a/src/darwin/Framework/CHIP/templates/partials/testsuite/WaitForAttributeReport.zapt b/src/darwin/Framework/CHIP/templates/partials/testsuite/WaitForAttributeReport.zapt new file mode 100644 index 00000000000000..33c9332063e08e --- /dev/null +++ b/src/darwin/Framework/CHIP/templates/partials/testsuite/WaitForAttributeReport.zapt @@ -0,0 +1,14 @@ +{{#chip_tests_WaitForAttributeReport_attribute_info}} + CHIPDevice * device = GetPairedDevice(kDeviceId); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIP{{asUpperCamelCase cluster}} * cluster = [[CHIP{{asUpperCamelCase cluster}} alloc] initWithDevice:device endpoint:{{endpoint}} queue:queue]; + XCTAssertNotNil(cluster); + + [cluster reportAttribute{{asUpperCamelCase attribute}}WithResponseHandler:^(NSError * err, NSDictionary * values) { + NSLog(@"Reporting Test Report: %@", err); + XCTAssertEqual(err.code, 0); + + {{> process_response_value}} + [expectation fulfill]; + }]; +{{/chip_tests_WaitForAttributeReport_attribute_info}} diff --git a/src/darwin/Framework/CHIP/templates/partials/testsuite/WaitForMs.zapt b/src/darwin/Framework/CHIP/templates/partials/testsuite/WaitForMs.zapt new file mode 100644 index 00000000000000..57326c64d83df6 --- /dev/null +++ b/src/darwin/Framework/CHIP/templates/partials/testsuite/WaitForMs.zapt @@ -0,0 +1,2 @@ +dispatch_queue_t queue = dispatch_get_main_queue(); +{{command}}(expectation, queue{{#chip_tests_item_parameters}}, {{definedValue}}{{/chip_tests_item_parameters}}); diff --git a/src/darwin/Framework/CHIP/templates/templates.json b/src/darwin/Framework/CHIP/templates/templates.json index 7960d62a3c8618..72b96a1fabb180 100644 --- a/src/darwin/Framework/CHIP/templates/templates.json +++ b/src/darwin/Framework/CHIP/templates/templates.json @@ -19,9 +19,21 @@ "name": "test_cluster", "path": "partials/test_cluster.zapt" }, + { + "name": "process_response_value", + "path": "partials/process_response_value.zapt" + }, { "name": "CHIPCallbackBridge", "path": "partials/CHIPCallbackBridge.zapt" + }, + { + "name": "TestSuiteHelper_WaitForMs", + "path": "partials/testsuite/WaitForMs.zapt" + }, + { + "name": "TestSuiteHelper_WaitForAttributeReport", + "path": "partials/testsuite/WaitForAttributeReport.zapt" } ], "templates": [ diff --git a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m index 50d8408e27f758..b94ceebad22512 100644 --- a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m @@ -160,79 +160,6 @@ - (void)testReuseChipClusterObject [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } -- (void)testSendClusterTestCluster_Reporting_0000_BindOnOff_Test -{ - XCTestExpectation * expectation = [self expectationWithDescription:@"Binding to OnOff Cluster complete"]; - CHIPDevice * device = GetPairedDevice(kDeviceId); - dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPBinding * bindingCluster = [[CHIPBinding alloc] initWithDevice:device endpoint:1 queue:queue]; - XCTAssertNotNil(bindingCluster); - [bindingCluster bind:kDeviceId - groupId:0 - endpointId:1 - clusterId:6 - responseHandler:^(NSError * err, NSDictionary * values) { - NSLog(@"Reporting Test Binding status : %@", err); - XCTAssertEqual(err.code, 0); - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; -} - -- (void)testSendClusterTestCluster_Reporting_0001_ConfigureOnOff_Test -{ - XCTestExpectation * expectation = [self expectationWithDescription:@"Reporting OnOff configured"]; - CHIPDevice * device = GetPairedDevice(kDeviceId); - dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPOnOff * onOffCluster = [[CHIPOnOff alloc] initWithDevice:device endpoint:1 queue:queue]; - XCTAssertNotNil(onOffCluster); - [onOffCluster configureAttributeOnOffWithMinInterval:0 - maxInterval:1 - responseHandler:^(NSError * err, NSDictionary * values) { - NSLog(@"Reporting Test Configure status: %@", err); - - XCTAssertEqual(err.code, 0); - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; -} - -- (void)testSendClusterTestCluster_Reporting_0002_ReportOnOff_Test -{ - XCTestExpectation * expectation = [self expectationWithDescription:@"First report received"]; - CHIPDevice * device = GetPairedDevice(kDeviceId); - dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPOnOff * onOffCluster = [[CHIPOnOff alloc] initWithDevice:device endpoint:1 queue:queue]; - XCTAssertNotNil(onOffCluster); - [onOffCluster reportAttributeOnOffWithResponseHandler:^(NSError * err, NSDictionary * values) { - NSLog(@"Reporting Test Report first report: %@", err); - [expectation fulfill]; - XCTAssertEqual(err.code, 0); - }]; - - [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; -} - -- (void)testSendClusterTestCluster_Reporting_0003_StopReportOnOff_Test -{ - XCTestExpectation * expectation = [self expectationWithDescription:@"Reporting OnOff cancelled"]; - CHIPDevice * device = GetPairedDevice(kDeviceId); - dispatch_queue_t queue = dispatch_get_main_queue(); - CHIPOnOff * onOffCluster = [[CHIPOnOff alloc] initWithDevice:device endpoint:1 queue:queue]; - XCTAssertNotNil(onOffCluster); - [onOffCluster configureAttributeOnOffWithMinInterval:0 - maxInterval:0xffff - responseHandler:^(NSError * err, NSDictionary * values) { - NSLog(@"Reporting Test Cancel Reports status: %@", err); - - XCTAssertEqual(err.code, 0); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; -} - - (void)testSendClusterTestCluster_000000_Test { XCTestExpectation * expectation = [self expectationWithDescription:@"Send Test Command"]; @@ -2421,6 +2348,86 @@ - (void)testSendClusterTestDelayCommands_000000_WaitForMs [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } +- (void)testSendClusterTestSubscribe_OnOff_000000_Off +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Set OnOff Attribute to false"]; + CHIPDevice * device = GetPairedDevice(kDeviceId); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPOnOff * cluster = [[CHIPOnOff alloc] initWithDevice:device endpoint:1 queue:queue]; + XCTAssertNotNil(cluster); + + [cluster off:^(NSError * err, NSDictionary * values) { + NSLog(@"Set OnOff Attribute to false Error: %@", err); + + XCTAssertEqual(err.code, 0); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTestSubscribe_OnOff_000001_SubscribeAttribute +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Subscribe OnOff Attribute"]; + CHIPDevice * device = GetPairedDevice(kDeviceId); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPOnOff * cluster = [[CHIPOnOff alloc] initWithDevice:device endpoint:1 queue:queue]; + XCTAssertNotNil(cluster); + + __block bool initialReportReceived = false; + [cluster reportAttributeOnOffWithResponseHandler:^(NSError * err, NSDictionary * values) { + NSLog(@"Reporting Test Report: %@", err); + XCTAssertEqual(err.code, 0); + XCTAssertEqual([values[@"value"] boolValue], false); + initialReportReceived = true; + }]; + + [cluster configureAttributeOnOffWithMinInterval:2 + maxInterval:10 + responseHandler:^(NSError * err, NSDictionary * values) { + NSLog(@"Subscribe OnOff Attribute Error: %@", err); + + XCTAssertEqual(err.code, 0); + XCTAssertEqual(initialReportReceived, true); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTestSubscribe_OnOff_000002_On +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Turn On the light to see attribute change"]; + CHIPDevice * device = GetPairedDevice(kDeviceId); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPOnOff * cluster = [[CHIPOnOff alloc] initWithDevice:device endpoint:1 queue:queue]; + XCTAssertNotNil(cluster); + + [cluster on:^(NSError * err, NSDictionary * values) { + NSLog(@"Turn On the light to see attribute change Error: %@", err); + + XCTAssertEqual(err.code, 0); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTestSubscribe_OnOff_000003_WaitForAttributeReport +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Check for attribute report"]; + CHIPDevice * device = GetPairedDevice(kDeviceId); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPOnOff * cluster = [[CHIPOnOff alloc] initWithDevice:device endpoint:1 queue:queue]; + XCTAssertNotNil(cluster); + + [cluster reportAttributeOnOffWithResponseHandler:^(NSError * err, NSDictionary * values) { + NSLog(@"Reporting Test Report: %@", err); + XCTAssertEqual(err.code, 0); + + XCTAssertEqual([values[@"value"] boolValue], true); + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} + - (void)testSendClusterTest_TC_OO_1_1_000000_ReadAttribute { XCTestExpectation * expectation = [self expectationWithDescription:@"read the global attribute: ClusterRevision"]; diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index b0efc02a376ceb..6b2169096f0142 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -2428,7 +2428,7 @@ extern const char CHIP_NON_PRODUCTION_MARKER[]; * @brief Defines the maximum number of path objects, limits the number of attributes being read or subscribed at the same time. */ #ifndef CHIP_IM_SERVER_MAX_NUM_PATH_GROUPS -#define CHIP_IM_SERVER_MAX_NUM_PATH_GROUPS 4 +#define CHIP_IM_SERVER_MAX_NUM_PATH_GROUPS 8 #endif /** @@ -2449,6 +2449,15 @@ extern const char CHIP_NON_PRODUCTION_MARKER[]; #define CHIP_IM_MAX_NUM_WRITE_CLIENT 4 #endif +/** + * @def CHIP_DEVICE_CONTROLLER_SUBSCRIPTION_ATTRIBUTE_PATH_POOL_SIZE + * + * @brief Defines the object pool for allocating attribute path for subscription in device controller. + */ +#ifndef CHIP_DEVICE_CONTROLLER_SUBSCRIPTION_ATTRIBUTE_PATH_POOL_SIZE +#define CHIP_DEVICE_CONTROLLER_SUBSCRIPTION_ATTRIBUTE_PATH_POOL_SIZE CHIP_IM_MAX_NUM_READ_CLIENT +#endif + /** * @} */ diff --git a/zzz_generated/chip-tool/zap-generated/reporting/Commands.h b/zzz_generated/chip-tool/zap-generated/reporting/Commands.h index 25c0a5d7f519d4..2728c84b7e5c10 100644 --- a/zzz_generated/chip-tool/zap-generated/reporting/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/reporting/Commands.h @@ -61,55 +61,78 @@ class Listen : public ReportingCommand { chip::app::CHIPDeviceCallbacksMgr & callbacksMgr = chip::app::CHIPDeviceCallbacksMgr::GetInstance(); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x000F, 0x0055, - onReportBinaryInputBasicPresentValueCallback->Cancel()); + onReportBinaryInputBasicPresentValueCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x000F, 0x006F, - onReportBinaryInputBasicStatusFlagsCallback->Cancel()); + onReportBinaryInputBasicStatusFlagsCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0300, 0x0000, - onReportColorControlCurrentHueCallback->Cancel()); + onReportColorControlCurrentHueCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0300, 0x0001, - onReportColorControlCurrentSaturationCallback->Cancel()); + onReportColorControlCurrentSaturationCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0300, 0x0003, - onReportColorControlCurrentXCallback->Cancel()); + onReportColorControlCurrentXCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0300, 0x0004, - onReportColorControlCurrentYCallback->Cancel()); + onReportColorControlCurrentYCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0300, 0x0007, - onReportColorControlColorTemperatureCallback->Cancel()); + onReportColorControlColorTemperatureCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0101, 0x0000, - onReportDoorLockLockStateCallback->Cancel()); + onReportDoorLockLockStateCallback->Cancel(), BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0008, 0x0000, - onReportLevelControlCurrentLevelCallback->Cancel()); + onReportLevelControlCurrentLevelCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0406, 0x0000, - onReportOccupancySensingOccupancyCallback->Cancel()); + onReportOccupancySensingOccupancyCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0006, 0x0000, - onReportOnOffOnOffCallback->Cancel()); + onReportOnOffOnOffCallback->Cancel(), BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0403, 0x0000, - onReportPressureMeasurementMeasuredValueCallback->Cancel()); + onReportPressureMeasurementMeasuredValueCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0200, 0x0013, - onReportPumpConfigurationAndControlCapacityCallback->Cancel()); + onReportPumpConfigurationAndControlCapacityCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0405, 0x0000, - onReportRelativeHumidityMeasurementMeasuredValueCallback->Cancel()); + onReportRelativeHumidityMeasurementMeasuredValueCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x003B, 0x0001, - onReportSwitchCurrentPositionCallback->Cancel()); + onReportSwitchCurrentPositionCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0402, 0x0000, - onReportTemperatureMeasurementMeasuredValueCallback->Cancel()); + onReportTemperatureMeasurementMeasuredValueCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0201, 0x0000, - onReportThermostatLocalTemperatureCallback->Cancel()); + onReportThermostatLocalTemperatureCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x0008, - onReportWindowCoveringCurrentPositionLiftPercentageCallback->Cancel()); + onReportWindowCoveringCurrentPositionLiftPercentageCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x0009, - onReportWindowCoveringCurrentPositionTiltPercentageCallback->Cancel()); + onReportWindowCoveringCurrentPositionTiltPercentageCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x000A, - onReportWindowCoveringOperationalStatusCallback->Cancel()); + onReportWindowCoveringOperationalStatusCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x000B, - onReportWindowCoveringTargetPositionLiftPercent100thsCallback->Cancel()); + onReportWindowCoveringTargetPositionLiftPercent100thsCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x000C, - onReportWindowCoveringTargetPositionTiltPercent100thsCallback->Cancel()); + onReportWindowCoveringTargetPositionTiltPercent100thsCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x000E, - onReportWindowCoveringCurrentPositionLiftPercent100thsCallback->Cancel()); + onReportWindowCoveringCurrentPositionLiftPercent100thsCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x000F, - onReportWindowCoveringCurrentPositionTiltPercent100thsCallback->Cancel()); + onReportWindowCoveringCurrentPositionTiltPercent100thsCallback->Cancel(), + BasicAttributeFilter); callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x001A, - onReportWindowCoveringSafetyStatusCallback->Cancel()); + onReportWindowCoveringSafetyStatusCallback->Cancel(), + BasicAttributeFilter); } static void OnDefaultSuccessResponse(void * context) { ChipLogProgress(chipTool, "Default Success Response"); } diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index e968d06cb58911..2db816bf363b27 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -74,6 +74,7 @@ class TV_TargetNavigatorCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterTargetNavigatorCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterTargetNavigatorCommandReadAttribute_0() @@ -139,6 +140,7 @@ class TV_TargetNavigatorCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterTargetNavigatorCommandNavigateTarget_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterTargetNavigatorCommandNavigateTarget_1() @@ -247,6 +249,7 @@ class TV_AudioOutputCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterAudioOutputCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterAudioOutputCommandReadAttribute_0() @@ -311,6 +314,7 @@ class TV_AudioOutputCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterAudioOutputCommandSelectOutput_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterAudioOutputCommandSelectOutput_1() @@ -368,6 +372,7 @@ class TV_AudioOutputCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterAudioOutputCommandRenameOutput_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterAudioOutputCommandRenameOutput_2() @@ -478,6 +483,7 @@ class TV_ApplicationLauncherCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterApplicationLauncherCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterApplicationLauncherCommandReadAttribute_0() @@ -542,6 +548,7 @@ class TV_ApplicationLauncherCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterApplicationLauncherCommandLaunchApp_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterApplicationLauncherCommandLaunchApp_1() @@ -603,6 +610,7 @@ class TV_ApplicationLauncherCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterApplicationLauncherCommandReadAttribute_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterApplicationLauncherCommandReadAttribute_2() @@ -666,6 +674,7 @@ class TV_ApplicationLauncherCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterApplicationLauncherCommandReadAttribute_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterApplicationLauncherCommandReadAttribute_3() @@ -771,6 +780,7 @@ class TV_KeypadInputCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterKeypadInputCommandSendKey_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterKeypadInputCommandSendKey_0() @@ -874,6 +884,7 @@ class TV_AccountLoginCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterAccountLoginCommandGetSetupPIN_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterAccountLoginCommandGetSetupPIN_0() @@ -930,6 +941,7 @@ class TV_AccountLoginCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterAccountLoginCommandLogin_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterAccountLoginCommandLogin_1() @@ -1032,6 +1044,7 @@ class TV_WakeOnLanCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterWakeOnLanCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterWakeOnLanCommandReadAttribute_0() @@ -1149,6 +1162,7 @@ class TV_ApplicationBasicCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterApplicationBasicCommandChangeStatus_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterApplicationBasicCommandChangeStatus_0() @@ -1206,6 +1220,7 @@ class TV_ApplicationBasicCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterApplicationBasicCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterApplicationBasicCommandReadAttribute_1() @@ -1269,6 +1284,7 @@ class TV_ApplicationBasicCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterApplicationBasicCommandReadAttribute_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterApplicationBasicCommandReadAttribute_2() @@ -1332,6 +1348,7 @@ class TV_ApplicationBasicCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterApplicationBasicCommandReadAttribute_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterApplicationBasicCommandReadAttribute_3() @@ -1468,6 +1485,7 @@ class TV_MediaPlaybackCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterMediaPlaybackCommandMediaPlay_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterMediaPlaybackCommandMediaPlay_0() @@ -1531,6 +1549,7 @@ class TV_MediaPlaybackCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterMediaPlaybackCommandMediaPause_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterMediaPlaybackCommandMediaPause_1() @@ -1594,6 +1613,7 @@ class TV_MediaPlaybackCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterMediaPlaybackCommandMediaStop_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterMediaPlaybackCommandMediaStop_2() @@ -1657,6 +1677,7 @@ class TV_MediaPlaybackCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterMediaPlaybackCommandMediaStartOver_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterMediaPlaybackCommandMediaStartOver_3() @@ -1720,6 +1741,7 @@ class TV_MediaPlaybackCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_4{ OnTestSendClusterMediaPlaybackCommandMediaPrevious_4_FailureResponse, this }; + bool mIsFailureExpected_4 = 0; CHIP_ERROR TestSendClusterMediaPlaybackCommandMediaPrevious_4() @@ -1783,6 +1805,7 @@ class TV_MediaPlaybackCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_5{ OnTestSendClusterMediaPlaybackCommandMediaNext_5_FailureResponse, this }; + bool mIsFailureExpected_5 = 0; CHIP_ERROR TestSendClusterMediaPlaybackCommandMediaNext_5() @@ -1846,6 +1869,7 @@ class TV_MediaPlaybackCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_6{ OnTestSendClusterMediaPlaybackCommandMediaRewind_6_FailureResponse, this }; + bool mIsFailureExpected_6 = 0; CHIP_ERROR TestSendClusterMediaPlaybackCommandMediaRewind_6() @@ -1909,6 +1933,7 @@ class TV_MediaPlaybackCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_7{ OnTestSendClusterMediaPlaybackCommandMediaFastForward_7_FailureResponse, this }; + bool mIsFailureExpected_7 = 0; CHIP_ERROR TestSendClusterMediaPlaybackCommandMediaFastForward_7() @@ -1972,6 +1997,7 @@ class TV_MediaPlaybackCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_8{ OnTestSendClusterMediaPlaybackCommandMediaSkipForward_8_FailureResponse, this }; + bool mIsFailureExpected_8 = 0; CHIP_ERROR TestSendClusterMediaPlaybackCommandMediaSkipForward_8() @@ -2037,6 +2063,7 @@ class TV_MediaPlaybackCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_9{ OnTestSendClusterMediaPlaybackCommandMediaSkipBackward_9_FailureResponse, this }; + bool mIsFailureExpected_9 = 0; CHIP_ERROR TestSendClusterMediaPlaybackCommandMediaSkipBackward_9() @@ -2103,6 +2130,7 @@ class TV_MediaPlaybackCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_10{ OnTestSendClusterMediaPlaybackCommandMediaSeek_10_FailureResponse, this }; + bool mIsFailureExpected_10 = 0; CHIP_ERROR TestSendClusterMediaPlaybackCommandMediaSeek_10() @@ -2216,6 +2244,7 @@ class TV_TvChannelCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterTvChannelCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterTvChannelCommandReadAttribute_0() @@ -2280,6 +2309,7 @@ class TV_TvChannelCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterTvChannelCommandChangeChannelByNumber_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterTvChannelCommandChangeChannelByNumber_1() @@ -2339,6 +2369,7 @@ class TV_TvChannelCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterTvChannelCommandSkipChannel_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterTvChannelCommandSkipChannel_2() @@ -2437,6 +2468,7 @@ class TV_LowPowerCluster : public TestCommand this }; chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterLowPowerCommandSleep_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterLowPowerCommandSleep_0() @@ -2551,6 +2583,7 @@ class TV_MediaInputCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterMediaInputCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterMediaInputCommandReadAttribute_0() @@ -2615,6 +2648,7 @@ class TV_MediaInputCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterMediaInputCommandSelectInput_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterMediaInputCommandSelectInput_1() @@ -2672,6 +2706,7 @@ class TV_MediaInputCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterMediaInputCommandReadAttribute_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterMediaInputCommandReadAttribute_2() @@ -2735,6 +2770,7 @@ class TV_MediaInputCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterMediaInputCommandHideInputStatus_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterMediaInputCommandHideInputStatus_3() @@ -2791,6 +2827,7 @@ class TV_MediaInputCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_4{ OnTestSendClusterMediaInputCommandShowInputStatus_4_FailureResponse, this }; + bool mIsFailureExpected_4 = 0; CHIP_ERROR TestSendClusterMediaInputCommandShowInputStatus_4() @@ -2847,6 +2884,7 @@ class TV_MediaInputCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_5{ OnTestSendClusterMediaInputCommandRenameInput_5_FailureResponse, this }; + bool mIsFailureExpected_5 = 0; CHIP_ERROR TestSendClusterMediaInputCommandRenameInput_5() @@ -3280,6 +3318,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterTestClusterCommandTest_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterTestClusterCommandTest_0() @@ -3336,6 +3375,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterTestClusterCommandTestNotHandled_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 1; CHIP_ERROR TestSendClusterTestClusterCommandTestNotHandled_1() @@ -3392,6 +3432,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterTestClusterCommandTestSpecific_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterTestClusterCommandTestSpecific_2() @@ -3455,6 +3496,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterTestClusterCommandTestAddArguments_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterTestClusterCommandTestAddArguments_3() @@ -3520,6 +3562,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_4{ OnTestSendClusterTestClusterCommandTestAddArguments_4_FailureResponse, this }; + bool mIsFailureExpected_4 = 1; CHIP_ERROR TestSendClusterTestClusterCommandTestAddArguments_4() @@ -3578,6 +3621,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_5{ OnTestSendClusterTestClusterCommandReadAttribute_5_FailureResponse, this }; + bool mIsFailureExpected_5 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_5() @@ -3641,6 +3685,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_6{ OnTestSendClusterTestClusterCommandWriteAttribute_6_FailureResponse, this }; + bool mIsFailureExpected_6 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_6() @@ -3698,6 +3743,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_7{ OnTestSendClusterTestClusterCommandReadAttribute_7_FailureResponse, this }; + bool mIsFailureExpected_7 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_7() @@ -3761,6 +3807,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_8{ OnTestSendClusterTestClusterCommandWriteAttribute_8_FailureResponse, this }; + bool mIsFailureExpected_8 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_8() @@ -3818,6 +3865,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_9{ OnTestSendClusterTestClusterCommandReadAttribute_9_FailureResponse, this }; + bool mIsFailureExpected_9 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_9() @@ -3881,6 +3929,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_10{ OnTestSendClusterTestClusterCommandReadAttribute_10_FailureResponse, this }; + bool mIsFailureExpected_10 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_10() @@ -3944,6 +3993,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_11{ OnTestSendClusterTestClusterCommandWriteAttribute_11_FailureResponse, this }; + bool mIsFailureExpected_11 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_11() @@ -4001,6 +4051,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_12{ OnTestSendClusterTestClusterCommandReadAttribute_12_FailureResponse, this }; + bool mIsFailureExpected_12 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_12() @@ -4064,6 +4115,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_13{ OnTestSendClusterTestClusterCommandWriteAttribute_13_FailureResponse, this }; + bool mIsFailureExpected_13 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_13() @@ -4121,6 +4173,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_14{ OnTestSendClusterTestClusterCommandReadAttribute_14_FailureResponse, this }; + bool mIsFailureExpected_14 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_14() @@ -4184,6 +4237,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_15{ OnTestSendClusterTestClusterCommandReadAttribute_15_FailureResponse, this }; + bool mIsFailureExpected_15 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_15() @@ -4247,6 +4301,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_16{ OnTestSendClusterTestClusterCommandWriteAttribute_16_FailureResponse, this }; + bool mIsFailureExpected_16 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_16() @@ -4304,6 +4359,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_17{ OnTestSendClusterTestClusterCommandReadAttribute_17_FailureResponse, this }; + bool mIsFailureExpected_17 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_17() @@ -4367,6 +4423,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_18{ OnTestSendClusterTestClusterCommandWriteAttribute_18_FailureResponse, this }; + bool mIsFailureExpected_18 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_18() @@ -4424,6 +4481,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_19{ OnTestSendClusterTestClusterCommandReadAttribute_19_FailureResponse, this }; + bool mIsFailureExpected_19 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_19() @@ -4487,6 +4545,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_20{ OnTestSendClusterTestClusterCommandReadAttribute_20_FailureResponse, this }; + bool mIsFailureExpected_20 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_20() @@ -4550,6 +4609,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_21{ OnTestSendClusterTestClusterCommandWriteAttribute_21_FailureResponse, this }; + bool mIsFailureExpected_21 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_21() @@ -4607,6 +4667,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_22{ OnTestSendClusterTestClusterCommandReadAttribute_22_FailureResponse, this }; + bool mIsFailureExpected_22 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_22() @@ -4670,6 +4731,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_23{ OnTestSendClusterTestClusterCommandWriteAttribute_23_FailureResponse, this }; + bool mIsFailureExpected_23 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_23() @@ -4727,6 +4789,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_24{ OnTestSendClusterTestClusterCommandReadAttribute_24_FailureResponse, this }; + bool mIsFailureExpected_24 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_24() @@ -4790,6 +4853,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_25{ OnTestSendClusterTestClusterCommandReadAttribute_25_FailureResponse, this }; + bool mIsFailureExpected_25 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_25() @@ -4853,6 +4917,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_26{ OnTestSendClusterTestClusterCommandWriteAttribute_26_FailureResponse, this }; + bool mIsFailureExpected_26 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_26() @@ -4910,6 +4975,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_27{ OnTestSendClusterTestClusterCommandReadAttribute_27_FailureResponse, this }; + bool mIsFailureExpected_27 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_27() @@ -4973,6 +5039,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_28{ OnTestSendClusterTestClusterCommandWriteAttribute_28_FailureResponse, this }; + bool mIsFailureExpected_28 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_28() @@ -5030,6 +5097,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_29{ OnTestSendClusterTestClusterCommandReadAttribute_29_FailureResponse, this }; + bool mIsFailureExpected_29 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_29() @@ -5093,6 +5161,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_30{ OnTestSendClusterTestClusterCommandReadAttribute_30_FailureResponse, this }; + bool mIsFailureExpected_30 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_30() @@ -5156,6 +5225,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_31{ OnTestSendClusterTestClusterCommandWriteAttribute_31_FailureResponse, this }; + bool mIsFailureExpected_31 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_31() @@ -5213,6 +5283,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_32{ OnTestSendClusterTestClusterCommandReadAttribute_32_FailureResponse, this }; + bool mIsFailureExpected_32 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_32() @@ -5276,6 +5347,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_33{ OnTestSendClusterTestClusterCommandWriteAttribute_33_FailureResponse, this }; + bool mIsFailureExpected_33 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_33() @@ -5333,6 +5405,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_34{ OnTestSendClusterTestClusterCommandReadAttribute_34_FailureResponse, this }; + bool mIsFailureExpected_34 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_34() @@ -5396,6 +5469,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_35{ OnTestSendClusterTestClusterCommandReadAttribute_35_FailureResponse, this }; + bool mIsFailureExpected_35 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_35() @@ -5459,6 +5533,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_36{ OnTestSendClusterTestClusterCommandWriteAttribute_36_FailureResponse, this }; + bool mIsFailureExpected_36 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_36() @@ -5516,6 +5591,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_37{ OnTestSendClusterTestClusterCommandReadAttribute_37_FailureResponse, this }; + bool mIsFailureExpected_37 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_37() @@ -5579,6 +5655,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_38{ OnTestSendClusterTestClusterCommandWriteAttribute_38_FailureResponse, this }; + bool mIsFailureExpected_38 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_38() @@ -5636,6 +5713,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_39{ OnTestSendClusterTestClusterCommandReadAttribute_39_FailureResponse, this }; + bool mIsFailureExpected_39 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_39() @@ -5699,6 +5777,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_40{ OnTestSendClusterTestClusterCommandReadAttribute_40_FailureResponse, this }; + bool mIsFailureExpected_40 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_40() @@ -5762,6 +5841,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_41{ OnTestSendClusterTestClusterCommandWriteAttribute_41_FailureResponse, this }; + bool mIsFailureExpected_41 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_41() @@ -5819,6 +5899,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_42{ OnTestSendClusterTestClusterCommandReadAttribute_42_FailureResponse, this }; + bool mIsFailureExpected_42 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_42() @@ -5882,6 +5963,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_43{ OnTestSendClusterTestClusterCommandWriteAttribute_43_FailureResponse, this }; + bool mIsFailureExpected_43 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_43() @@ -5939,6 +6021,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_44{ OnTestSendClusterTestClusterCommandReadAttribute_44_FailureResponse, this }; + bool mIsFailureExpected_44 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_44() @@ -6002,6 +6085,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_45{ OnTestSendClusterTestClusterCommandReadAttribute_45_FailureResponse, this }; + bool mIsFailureExpected_45 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_45() @@ -6065,6 +6149,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_46{ OnTestSendClusterTestClusterCommandWriteAttribute_46_FailureResponse, this }; + bool mIsFailureExpected_46 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_46() @@ -6122,6 +6207,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_47{ OnTestSendClusterTestClusterCommandReadAttribute_47_FailureResponse, this }; + bool mIsFailureExpected_47 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_47() @@ -6185,6 +6271,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_48{ OnTestSendClusterTestClusterCommandWriteAttribute_48_FailureResponse, this }; + bool mIsFailureExpected_48 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_48() @@ -6242,6 +6329,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_49{ OnTestSendClusterTestClusterCommandReadAttribute_49_FailureResponse, this }; + bool mIsFailureExpected_49 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_49() @@ -6305,6 +6393,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_50{ OnTestSendClusterTestClusterCommandReadAttribute_50_FailureResponse, this }; + bool mIsFailureExpected_50 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_50() @@ -6368,6 +6457,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_51{ OnTestSendClusterTestClusterCommandWriteAttribute_51_FailureResponse, this }; + bool mIsFailureExpected_51 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_51() @@ -6425,6 +6515,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_52{ OnTestSendClusterTestClusterCommandReadAttribute_52_FailureResponse, this }; + bool mIsFailureExpected_52 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_52() @@ -6488,6 +6579,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_53{ OnTestSendClusterTestClusterCommandWriteAttribute_53_FailureResponse, this }; + bool mIsFailureExpected_53 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_53() @@ -6545,6 +6637,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_54{ OnTestSendClusterTestClusterCommandReadAttribute_54_FailureResponse, this }; + bool mIsFailureExpected_54 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_54() @@ -6608,6 +6701,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_55{ OnTestSendClusterTestClusterCommandWriteAttribute_55_FailureResponse, this }; + bool mIsFailureExpected_55 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_55() @@ -6665,6 +6759,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_56{ OnTestSendClusterTestClusterCommandReadAttribute_56_FailureResponse, this }; + bool mIsFailureExpected_56 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_56() @@ -6728,6 +6823,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_57{ OnTestSendClusterTestClusterCommandReadAttribute_57_FailureResponse, this }; + bool mIsFailureExpected_57 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_57() @@ -6791,6 +6887,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_58{ OnTestSendClusterTestClusterCommandWriteAttribute_58_FailureResponse, this }; + bool mIsFailureExpected_58 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_58() @@ -6848,6 +6945,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_59{ OnTestSendClusterTestClusterCommandReadAttribute_59_FailureResponse, this }; + bool mIsFailureExpected_59 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_59() @@ -6911,6 +7009,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_60{ OnTestSendClusterTestClusterCommandWriteAttribute_60_FailureResponse, this }; + bool mIsFailureExpected_60 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_60() @@ -6968,6 +7067,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_61{ OnTestSendClusterTestClusterCommandReadAttribute_61_FailureResponse, this }; + bool mIsFailureExpected_61 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_61() @@ -7031,6 +7131,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_62{ OnTestSendClusterTestClusterCommandWriteAttribute_62_FailureResponse, this }; + bool mIsFailureExpected_62 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_62() @@ -7088,6 +7189,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_63{ OnTestSendClusterTestClusterCommandReadAttribute_63_FailureResponse, this }; + bool mIsFailureExpected_63 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_63() @@ -7151,6 +7253,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_64{ OnTestSendClusterTestClusterCommandReadAttribute_64_FailureResponse, this }; + bool mIsFailureExpected_64 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_64() @@ -7214,6 +7317,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_65{ OnTestSendClusterTestClusterCommandWriteAttribute_65_FailureResponse, this }; + bool mIsFailureExpected_65 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_65() @@ -7271,6 +7375,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_66{ OnTestSendClusterTestClusterCommandReadAttribute_66_FailureResponse, this }; + bool mIsFailureExpected_66 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_66() @@ -7334,6 +7439,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_67{ OnTestSendClusterTestClusterCommandWriteAttribute_67_FailureResponse, this }; + bool mIsFailureExpected_67 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_67() @@ -7391,6 +7497,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_68{ OnTestSendClusterTestClusterCommandReadAttribute_68_FailureResponse, this }; + bool mIsFailureExpected_68 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_68() @@ -7454,6 +7561,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_69{ OnTestSendClusterTestClusterCommandWriteAttribute_69_FailureResponse, this }; + bool mIsFailureExpected_69 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_69() @@ -7511,6 +7619,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_70{ OnTestSendClusterTestClusterCommandReadAttribute_70_FailureResponse, this }; + bool mIsFailureExpected_70 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_70() @@ -7574,6 +7683,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_71{ OnTestSendClusterTestClusterCommandReadAttribute_71_FailureResponse, this }; + bool mIsFailureExpected_71 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_71() @@ -7637,6 +7747,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_72{ OnTestSendClusterTestClusterCommandWriteAttribute_72_FailureResponse, this }; + bool mIsFailureExpected_72 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_72() @@ -7694,6 +7805,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_73{ OnTestSendClusterTestClusterCommandReadAttribute_73_FailureResponse, this }; + bool mIsFailureExpected_73 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_73() @@ -7757,6 +7869,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_74{ OnTestSendClusterTestClusterCommandWriteAttribute_74_FailureResponse, this }; + bool mIsFailureExpected_74 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_74() @@ -7814,6 +7927,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_75{ OnTestSendClusterTestClusterCommandReadAttribute_75_FailureResponse, this }; + bool mIsFailureExpected_75 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_75() @@ -7877,6 +7991,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_76{ OnTestSendClusterTestClusterCommandWriteAttribute_76_FailureResponse, this }; + bool mIsFailureExpected_76 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_76() @@ -7934,6 +8049,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_77{ OnTestSendClusterTestClusterCommandReadAttribute_77_FailureResponse, this }; + bool mIsFailureExpected_77 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_77() @@ -7997,6 +8113,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_78{ OnTestSendClusterTestClusterCommandReadAttribute_78_FailureResponse, this }; + bool mIsFailureExpected_78 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_78() @@ -8060,6 +8177,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_79{ OnTestSendClusterTestClusterCommandWriteAttribute_79_FailureResponse, this }; + bool mIsFailureExpected_79 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_79() @@ -8117,6 +8235,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_80{ OnTestSendClusterTestClusterCommandReadAttribute_80_FailureResponse, this }; + bool mIsFailureExpected_80 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_80() @@ -8180,6 +8299,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_81{ OnTestSendClusterTestClusterCommandWriteAttribute_81_FailureResponse, this }; + bool mIsFailureExpected_81 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_81() @@ -8237,6 +8357,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_82{ OnTestSendClusterTestClusterCommandReadAttribute_82_FailureResponse, this }; + bool mIsFailureExpected_82 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_82() @@ -8300,6 +8421,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_83{ OnTestSendClusterTestClusterCommandReadAttribute_83_FailureResponse, this }; + bool mIsFailureExpected_83 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_83() @@ -8363,6 +8485,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_84{ OnTestSendClusterTestClusterCommandWriteAttribute_84_FailureResponse, this }; + bool mIsFailureExpected_84 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_84() @@ -8420,6 +8543,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_85{ OnTestSendClusterTestClusterCommandReadAttribute_85_FailureResponse, this }; + bool mIsFailureExpected_85 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_85() @@ -8483,6 +8607,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_86{ OnTestSendClusterTestClusterCommandWriteAttribute_86_FailureResponse, this }; + bool mIsFailureExpected_86 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_86() @@ -8540,6 +8665,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_87{ OnTestSendClusterTestClusterCommandReadAttribute_87_FailureResponse, this }; + bool mIsFailureExpected_87 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_87() @@ -8603,6 +8729,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_88{ OnTestSendClusterTestClusterCommandReadAttribute_88_FailureResponse, this }; + bool mIsFailureExpected_88 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_88() @@ -8667,6 +8794,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_89{ OnTestSendClusterTestClusterCommandWriteAttribute_89_FailureResponse, this }; + bool mIsFailureExpected_89 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_89() @@ -8725,6 +8853,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_90{ OnTestSendClusterTestClusterCommandReadAttribute_90_FailureResponse, this }; + bool mIsFailureExpected_90 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_90() @@ -8789,6 +8918,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_91{ OnTestSendClusterTestClusterCommandWriteAttribute_91_FailureResponse, this }; + bool mIsFailureExpected_91 = true; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_91() @@ -8848,6 +8978,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_92{ OnTestSendClusterTestClusterCommandReadAttribute_92_FailureResponse, this }; + bool mIsFailureExpected_92 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_92() @@ -8912,6 +9043,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_93{ OnTestSendClusterTestClusterCommandWriteAttribute_93_FailureResponse, this }; + bool mIsFailureExpected_93 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_93() @@ -8970,6 +9102,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_94{ OnTestSendClusterTestClusterCommandReadAttribute_94_FailureResponse, this }; + bool mIsFailureExpected_94 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_94() @@ -9034,6 +9167,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_95{ OnTestSendClusterTestClusterCommandWriteAttribute_95_FailureResponse, this }; + bool mIsFailureExpected_95 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_95() @@ -9099,6 +9233,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_96{ OnTestSendClusterTestClusterCommandReadAttribute_96_FailureResponse, this }; + bool mIsFailureExpected_96 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_96() @@ -9173,6 +9308,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_97{ OnTestSendClusterTestClusterCommandWriteAttribute_97_FailureResponse, this }; + bool mIsFailureExpected_97 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_97() @@ -9231,6 +9367,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_98{ OnTestSendClusterTestClusterCommandReadAttribute_98_FailureResponse, this }; + bool mIsFailureExpected_98 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_98() @@ -9295,6 +9432,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_99{ OnTestSendClusterTestClusterCommandWriteAttribute_99_FailureResponse, this }; + bool mIsFailureExpected_99 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_99() @@ -9352,6 +9490,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_100{ OnTestSendClusterTestClusterCommandWriteAttribute_100_FailureResponse, this }; + bool mIsFailureExpected_100 = true; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_100() @@ -9411,6 +9550,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_101{ OnTestSendClusterTestClusterCommandWriteAttribute_101_FailureResponse, this }; + bool mIsFailureExpected_101 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_101() @@ -9469,6 +9609,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_102{ OnTestSendClusterTestClusterCommandReadAttribute_102_FailureResponse, this }; + bool mIsFailureExpected_102 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_102() @@ -9533,6 +9674,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_103{ OnTestSendClusterTestClusterCommandWriteAttribute_103_FailureResponse, this }; + bool mIsFailureExpected_103 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_103() @@ -9598,6 +9740,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_104{ OnTestSendClusterTestClusterCommandReadAttribute_104_FailureResponse, this }; + bool mIsFailureExpected_104 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_104() @@ -9672,6 +9815,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_105{ OnTestSendClusterTestClusterCommandWriteAttribute_105_FailureResponse, this }; + bool mIsFailureExpected_105 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_105() @@ -9730,6 +9874,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_106{ OnTestSendClusterTestClusterCommandReadAttribute_106_FailureResponse, this }; + bool mIsFailureExpected_106 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_106() @@ -9794,6 +9939,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_107{ OnTestSendClusterTestClusterCommandReadAttribute_107_FailureResponse, this }; + bool mIsFailureExpected_107 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_107() @@ -9858,6 +10004,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_108{ OnTestSendClusterTestClusterCommandReadAttribute_108_FailureResponse, this }; + bool mIsFailureExpected_108 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_108() @@ -9923,6 +10070,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_109{ OnTestSendClusterTestClusterCommandReadAttribute_109_FailureResponse, this }; + bool mIsFailureExpected_109 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_109() @@ -9992,6 +10140,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_110{ OnTestSendClusterTestClusterCommandWriteAttribute_110_FailureResponse, this }; + bool mIsFailureExpected_110 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_110() @@ -10056,6 +10205,7 @@ class TestCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_111{ OnTestSendClusterTestClusterCommandTest_111_FailureResponse, this }; + bool mIsFailureExpected_111 = 1; CHIP_ERROR TestSendClusterTestClusterCommandTest_111() @@ -10164,6 +10314,7 @@ class TestConstraints : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterTestClusterCommandWriteAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterTestClusterCommandWriteAttribute_0() @@ -10221,6 +10372,7 @@ class TestConstraints : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterTestClusterCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_1() @@ -10284,6 +10436,7 @@ class TestConstraints : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterTestClusterCommandReadAttribute_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_2() @@ -10347,6 +10500,7 @@ class TestConstraints : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterTestClusterCommandReadAttribute_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterTestClusterCommandReadAttribute_3() @@ -10426,7 +10580,7 @@ class TestDelayCommands : public TestCommand switch (mTestIndex++) { case 0: - err = TestSendClusterDelayCommandsCommandWaitForMs_0(); + err = TestSendClusterTestSuiteCommandWaitForMs_0(); break; } @@ -10445,14 +10599,293 @@ class TestDelayCommands : public TestCommand // Tests methods // - CHIP_ERROR TestSendClusterDelayCommandsCommandWaitForMs_0() + CHIP_ERROR TestSendClusterTestSuiteCommandWaitForMs_0() { - ChipLogProgress(chipTool, "DelayCommands - Wait 100ms"); + ChipLogProgress(chipTool, "TestSuite - WaitForMs - Wait 100ms"); return WaitForMs(100); } }; +class TestSubscribe_OnOff : public TestCommand +{ +public: + TestSubscribe_OnOff() : TestCommand("TestSubscribe_OnOff"), mTestIndex(0) {} + + /////////// TestCommand Interface ///////// + void NextTest() override + { + CHIP_ERROR err = CHIP_NO_ERROR; + + if (mTestCount == mTestIndex) + { + ChipLogProgress(chipTool, "TestSubscribe_OnOff: Test complete"); + SetCommandExitStatus(CHIP_NO_ERROR); + } + + // Ensure we increment mTestIndex before we start running the relevant + // command. That way if we lose the timeslice after we send the message + // but before our function call returns, we won't end up with an + // incorrect mTestIndex value observed when we get the response. + switch (mTestIndex++) + { + case 0: + err = TestSendClusterOnOffCommandOff_0(); + break; + case 1: + err = TestSendClusterOnOffCommandSubscribeAttribute_1(); + break; + case 2: + err = TestSendClusterOnOffCommandOn_2(); + break; + case 3: + err = TestSendClusterTestSuiteCommandWaitForAttributeReport_3(); + break; + } + + if (CHIP_NO_ERROR != err) + { + ChipLogProgress(chipTool, "TestSubscribe_OnOff: %s", chip::ErrorStr(err)); + SetCommandExitStatus(err); + } + } + +private: + std::atomic_uint16_t mTestIndex; + const uint16_t mTestCount = 4; + + // + // Tests methods + // + + // Test Set OnOff Attribute to false + using SuccessCallback_0 = void (*)(void * context); + chip::Callback::Callback mOnSuccessCallback_0{ OnTestSendClusterOnOffCommandOff_0_SuccessResponse, this }; + chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterOnOffCommandOff_0_FailureResponse, + this }; + + bool mIsFailureExpected_0 = 0; + + CHIP_ERROR TestSendClusterOnOffCommandOff_0() + { + ChipLogProgress(chipTool, "On/Off - Set OnOff Attribute to false: Sending command..."); + + chip::Controller::OnOffCluster cluster; + cluster.Associate(mDevice, 1); + + CHIP_ERROR err = CHIP_NO_ERROR; + + err = cluster.Off(mOnSuccessCallback_0.Cancel(), mOnFailureCallback_0.Cancel()); + + return err; + } + + static void OnTestSendClusterOnOffCommandOff_0_FailureResponse(void * context, uint8_t status) + { + ChipLogProgress(chipTool, "On/Off - Set OnOff Attribute to false: Failure Response"); + + TestSubscribe_OnOff * runner = reinterpret_cast(context); + + if (runner->mIsFailureExpected_0 == false) + { + ChipLogError(chipTool, "Error: The test was expecting a success callback. Got failure callback"); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + runner->NextTest(); + } + + static void OnTestSendClusterOnOffCommandOff_0_SuccessResponse(void * context) + { + ChipLogProgress(chipTool, "On/Off - Set OnOff Attribute to false: Success Response"); + + TestSubscribe_OnOff * runner = reinterpret_cast(context); + + if (runner->mIsFailureExpected_0 == true) + { + ChipLogError(chipTool, "Error: The test was expecting a failure callback. Got success callback"); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + runner->NextTest(); + } + + // Test Subscribe OnOff Attribute + using SuccessCallback_1 = void (*)(void * context, bool onOff); + chip::Callback::Callback mOnSuccessCallback_1{ + OnTestSendClusterOnOffCommandSubscribeAttribute_1_SuccessResponse, this + }; + chip::Callback::Callback mOnFailureCallback_1{ + OnTestSendClusterOnOffCommandSubscribeAttribute_1_FailureResponse, this + }; + chip::Callback::Callback mOnSubscriptionEstablishedCallback_1{ + SubscribeAttribute_1_OnSubscriptionEstablishedCallback, this + }; + + bool mIsFailureExpected_1 = 0; + + bool mReceivedReport_1 = false; + + CHIP_ERROR TestSendClusterOnOffCommandSubscribeAttribute_1() + { + ChipLogProgress(chipTool, "On/Off - Subscribe OnOff Attribute: Sending command..."); + + chip::Controller::OnOffCluster cluster; + cluster.Associate(mDevice, 1); + + CHIP_ERROR err = CHIP_NO_ERROR; + + cluster.ReportAttributeOnOff(mOnSuccessCallback_1.Cancel()); + err = cluster.ConfigureAttributeOnOff(mOnSubscriptionEstablishedCallback_1.Cancel(), mOnFailureCallback_1.Cancel(), 2, 10); + + return err; + } + + static void SubscribeAttribute_1_OnSubscriptionEstablishedCallback(void * context) + { + TestSubscribe_OnOff * runner = reinterpret_cast(context); + if (!runner->mReceivedReport_1) + { + ChipLogError(chipTool, "Error: Initial report not received!"); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + runner->NextTest(); + } + + static void OnTestSendClusterOnOffCommandSubscribeAttribute_1_FailureResponse(void * context, uint8_t status) + { + ChipLogProgress(chipTool, "On/Off - Subscribe OnOff Attribute: Failure Response"); + + TestSubscribe_OnOff * runner = reinterpret_cast(context); + + if (runner->mIsFailureExpected_1 == false) + { + ChipLogError(chipTool, "Error: The test was expecting a success callback. Got failure callback"); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + runner->NextTest(); + } + + static void OnTestSendClusterOnOffCommandSubscribeAttribute_1_SuccessResponse(void * context, bool onOff) + { + ChipLogProgress(chipTool, "On/Off - Subscribe OnOff Attribute: Success Response"); + + TestSubscribe_OnOff * runner = reinterpret_cast(context); + + if (runner->mIsFailureExpected_1 == true) + { + ChipLogError(chipTool, "Error: The test was expecting a failure callback. Got success callback"); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + if (onOff != false) + { + ChipLogError(chipTool, "Error: Value mismatch. Expected: '%s'", "false"); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + runner->mReceivedReport_1 = true; + } + + // Test Turn On the light to see attribute change + using SuccessCallback_2 = void (*)(void * context); + chip::Callback::Callback mOnSuccessCallback_2{ OnTestSendClusterOnOffCommandOn_2_SuccessResponse, this }; + chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterOnOffCommandOn_2_FailureResponse, + this }; + + bool mIsFailureExpected_2 = 0; + + CHIP_ERROR TestSendClusterOnOffCommandOn_2() + { + ChipLogProgress(chipTool, "On/Off - Turn On the light to see attribute change: Sending command..."); + + chip::Controller::OnOffCluster cluster; + cluster.Associate(mDevice, 1); + + CHIP_ERROR err = CHIP_NO_ERROR; + + err = cluster.On(mOnSuccessCallback_2.Cancel(), mOnFailureCallback_2.Cancel()); + + return err; + } + + static void OnTestSendClusterOnOffCommandOn_2_FailureResponse(void * context, uint8_t status) + { + ChipLogProgress(chipTool, "On/Off - Turn On the light to see attribute change: Failure Response"); + + TestSubscribe_OnOff * runner = reinterpret_cast(context); + + if (runner->mIsFailureExpected_2 == false) + { + ChipLogError(chipTool, "Error: The test was expecting a success callback. Got failure callback"); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + runner->NextTest(); + } + + static void OnTestSendClusterOnOffCommandOn_2_SuccessResponse(void * context) + { + ChipLogProgress(chipTool, "On/Off - Turn On the light to see attribute change: Success Response"); + + TestSubscribe_OnOff * runner = reinterpret_cast(context); + + if (runner->mIsFailureExpected_2 == true) + { + ChipLogError(chipTool, "Error: The test was expecting a failure callback. Got success callback"); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + runner->NextTest(); + } + + // The callback should be called atleast once + using OnReportCallback_3 = void (*)(void * context, bool onOff); + chip::Callback::Callback mOnReportCallback_3{ SubscribeAttribute_3_OnReportCallback, this }; + + bool mReceivedReport_3 = false; + + CHIP_ERROR TestSendClusterTestSuiteCommandWaitForAttributeReport_3() + { + ChipLogProgress(chipTool, "TestSuite - WaitForAttributeReport - Check for attribute report"); + chip::Controller::OnOffCluster cluster; + cluster.Associate(mDevice, 1); + return cluster.ReportAttributeOnOff(mOnReportCallback_3.Cancel()); + } + + static void SubscribeAttribute_3_OnReportCallback(void * context, bool onOff) + { + ChipLogProgress(chipTool, "On/Off - Subscribe OnOff Attribute: Report Data"); + TestSubscribe_OnOff * runner = reinterpret_cast(context); + + if (runner->mReceivedReport_3) + { + // Receiving attribute more than once is not an issue, since the following handler will override previous handlers. + return; + } + + if (onOff != true) + { + ChipLogError(chipTool, "Error: Value mismatch. Expected: '%s'", "true"); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + runner->mReceivedReport_3 = true; + ChipLogProgress(chipTool, "On/Off - report received."); + runner->NextTest(); + } +}; + class Test_TC_OO_1_1 : public TestCommand { public: @@ -10511,6 +10944,7 @@ class Test_TC_OO_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterOnOffCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_0() @@ -10573,6 +11007,7 @@ class Test_TC_OO_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterOnOffCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_1() @@ -10635,6 +11070,7 @@ class Test_TC_OO_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterOnOffCommandReadAttribute_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_2() @@ -10697,6 +11133,7 @@ class Test_TC_OO_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterOnOffCommandReadAttribute_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_3() @@ -10835,6 +11272,7 @@ class Test_TC_OO_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterOnOffCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_0() @@ -10897,6 +11335,7 @@ class Test_TC_OO_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterOnOffCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_1() @@ -10959,6 +11398,7 @@ class Test_TC_OO_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterOnOffCommandReadAttribute_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_2() @@ -11021,6 +11461,7 @@ class Test_TC_OO_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterOnOffCommandReadAttribute_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_3() @@ -11083,6 +11524,7 @@ class Test_TC_OO_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_4{ OnTestSendClusterOnOffCommandReadAttribute_4_FailureResponse, this }; + bool mIsFailureExpected_4 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_4() @@ -11145,6 +11587,7 @@ class Test_TC_OO_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_5{ OnTestSendClusterOnOffCommandReadAttribute_5_FailureResponse, this }; + bool mIsFailureExpected_5 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_5() @@ -11207,6 +11650,7 @@ class Test_TC_OO_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_6{ OnTestSendClusterOnOffCommandWriteAttribute_6_FailureResponse, this }; + bool mIsFailureExpected_6 = 0; CHIP_ERROR TestSendClusterOnOffCommandWriteAttribute_6() @@ -11263,6 +11707,7 @@ class Test_TC_OO_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_7{ OnTestSendClusterOnOffCommandWriteAttribute_7_FailureResponse, this }; + bool mIsFailureExpected_7 = 0; CHIP_ERROR TestSendClusterOnOffCommandWriteAttribute_7() @@ -11319,6 +11764,7 @@ class Test_TC_OO_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_8{ OnTestSendClusterOnOffCommandWriteAttribute_8_FailureResponse, this }; + bool mIsFailureExpected_8 = 0; CHIP_ERROR TestSendClusterOnOffCommandWriteAttribute_8() @@ -11376,6 +11822,7 @@ class Test_TC_OO_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_9{ OnTestSendClusterOnOffCommandReadAttribute_9_FailureResponse, this }; + bool mIsFailureExpected_9 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_9() @@ -11439,6 +11886,7 @@ class Test_TC_OO_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_10{ OnTestSendClusterOnOffCommandReadAttribute_10_FailureResponse, this }; + bool mIsFailureExpected_10 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_10() @@ -11502,6 +11950,7 @@ class Test_TC_OO_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_11{ OnTestSendClusterOnOffCommandReadAttribute_11_FailureResponse, this }; + bool mIsFailureExpected_11 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_11() @@ -11644,6 +12093,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnSuccessCallback_0{ OnTestSendClusterOnOffCommandOff_0_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterOnOffCommandOff_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterOnOffCommandOff_0() @@ -11699,6 +12149,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterOnOffCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_1() @@ -11759,6 +12210,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnSuccessCallback_2{ OnTestSendClusterOnOffCommandOn_2_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterOnOffCommandOn_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterOnOffCommandOn_2() @@ -11814,6 +12266,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterOnOffCommandReadAttribute_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_3() @@ -11874,6 +12327,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnSuccessCallback_4{ OnTestSendClusterOnOffCommandOff_4_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_4{ OnTestSendClusterOnOffCommandOff_4_FailureResponse, this }; + bool mIsFailureExpected_4 = 0; CHIP_ERROR TestSendClusterOnOffCommandOff_4() @@ -11929,6 +12383,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnFailureCallback_5{ OnTestSendClusterOnOffCommandReadAttribute_5_FailureResponse, this }; + bool mIsFailureExpected_5 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_5() @@ -11989,6 +12444,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnSuccessCallback_6{ OnTestSendClusterOnOffCommandToggle_6_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_6{ OnTestSendClusterOnOffCommandToggle_6_FailureResponse, this }; + bool mIsFailureExpected_6 = 0; CHIP_ERROR TestSendClusterOnOffCommandToggle_6() @@ -12044,6 +12500,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnFailureCallback_7{ OnTestSendClusterOnOffCommandReadAttribute_7_FailureResponse, this }; + bool mIsFailureExpected_7 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_7() @@ -12104,6 +12561,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnSuccessCallback_8{ OnTestSendClusterOnOffCommandToggle_8_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_8{ OnTestSendClusterOnOffCommandToggle_8_FailureResponse, this }; + bool mIsFailureExpected_8 = 0; CHIP_ERROR TestSendClusterOnOffCommandToggle_8() @@ -12159,6 +12617,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnFailureCallback_9{ OnTestSendClusterOnOffCommandReadAttribute_9_FailureResponse, this }; + bool mIsFailureExpected_9 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_9() @@ -12219,6 +12678,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnSuccessCallback_10{ OnTestSendClusterOnOffCommandOn_10_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_10{ OnTestSendClusterOnOffCommandOn_10_FailureResponse, this }; + bool mIsFailureExpected_10 = 0; CHIP_ERROR TestSendClusterOnOffCommandOn_10() @@ -12275,6 +12735,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnFailureCallback_11{ OnTestSendClusterOnOffCommandReadAttribute_11_FailureResponse, this }; + bool mIsFailureExpected_11 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_11() @@ -12335,6 +12796,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnSuccessCallback_12{ OnTestSendClusterOnOffCommandOff_12_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_12{ OnTestSendClusterOnOffCommandOff_12_FailureResponse, this }; + bool mIsFailureExpected_12 = 0; CHIP_ERROR TestSendClusterOnOffCommandOff_12() @@ -12391,6 +12853,7 @@ class Test_TC_OO_2_2 : public TestCommand chip::Callback::Callback mOnFailureCallback_13{ OnTestSendClusterOnOffCommandReadAttribute_13_FailureResponse, this }; + bool mIsFailureExpected_13 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_13() @@ -12547,6 +13010,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterBasicCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_0() @@ -12605,6 +13069,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterBasicCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_1() @@ -12669,6 +13134,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterBasicCommandReadAttribute_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_2() @@ -12726,6 +13192,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterBasicCommandReadAttribute_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_3() @@ -12790,6 +13257,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_4{ OnTestSendClusterBasicCommandReadAttribute_4_FailureResponse, this }; + bool mIsFailureExpected_4 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_4() @@ -12847,6 +13315,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_5{ OnTestSendClusterBasicCommandReadAttribute_5_FailureResponse, this }; + bool mIsFailureExpected_5 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_5() @@ -12911,6 +13380,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_6{ OnTestSendClusterBasicCommandReadAttribute_6_FailureResponse, this }; + bool mIsFailureExpected_6 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_6() @@ -12978,6 +13448,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_7{ OnTestSendClusterBasicCommandReadAttribute_7_FailureResponse, this }; + bool mIsFailureExpected_7 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_7() @@ -13035,6 +13506,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_8{ OnTestSendClusterBasicCommandReadAttribute_8_FailureResponse, this }; + bool mIsFailureExpected_8 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_8() @@ -13109,6 +13581,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_9{ OnTestSendClusterBasicCommandReadAttribute_9_FailureResponse, this }; + bool mIsFailureExpected_9 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_9() @@ -13167,6 +13640,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_10{ OnTestSendClusterBasicCommandReadAttribute_10_FailureResponse, this }; + bool mIsFailureExpected_10 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_10() @@ -13245,6 +13719,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_11{ OnTestSendClusterBasicCommandReadAttribute_11_FailureResponse, this }; + bool mIsFailureExpected_11 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_11() @@ -13326,6 +13801,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_12{ OnTestSendClusterBasicCommandReadAttribute_12_FailureResponse, this }; + bool mIsFailureExpected_12 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_12() @@ -13397,6 +13873,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_13{ OnTestSendClusterBasicCommandReadAttribute_13_FailureResponse, this }; + bool mIsFailureExpected_13 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_13() @@ -13470,6 +13947,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_14{ OnTestSendClusterBasicCommandReadAttribute_14_FailureResponse, this }; + bool mIsFailureExpected_14 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_14() @@ -13541,6 +14019,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_15{ OnTestSendClusterBasicCommandReadAttribute_15_FailureResponse, this }; + bool mIsFailureExpected_15 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_15() @@ -13612,6 +14091,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_16{ OnTestSendClusterBasicCommandReadAttribute_16_FailureResponse, this }; + bool mIsFailureExpected_16 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_16() @@ -13676,6 +14156,7 @@ class Test_TC_DM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_17{ OnTestSendClusterBasicCommandReadAttribute_17_FailureResponse, this }; + bool mIsFailureExpected_17 = 0; CHIP_ERROR TestSendClusterBasicCommandReadAttribute_17() @@ -13877,6 +14358,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnSuccessCallback_0{ OnTestSendClusterOnOffCommandOn_0_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterOnOffCommandOn_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterOnOffCommandOn_0() @@ -13932,6 +14414,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterOnOffCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_1() @@ -13995,6 +14478,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterColorControlCommandMoveToHue_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveToHue_2() @@ -14057,6 +14541,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterColorControlCommandMoveToHue_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveToHue_3() @@ -14119,6 +14604,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_4{ OnTestSendClusterColorControlCommandMoveToHue_4_FailureResponse, this }; + bool mIsFailureExpected_4 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveToHue_4() @@ -14181,6 +14667,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_5{ OnTestSendClusterColorControlCommandMoveToHue_5_FailureResponse, this }; + bool mIsFailureExpected_5 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveToHue_5() @@ -14242,6 +14729,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_6{ OnTestSendClusterColorControlCommandMoveHue_6_FailureResponse, this }; + bool mIsFailureExpected_6 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveHue_6() @@ -14302,6 +14790,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_7{ OnTestSendClusterColorControlCommandMoveHue_7_FailureResponse, this }; + bool mIsFailureExpected_7 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveHue_7() @@ -14362,6 +14851,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_8{ OnTestSendClusterColorControlCommandMoveHue_8_FailureResponse, this }; + bool mIsFailureExpected_8 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveHue_8() @@ -14422,6 +14912,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_9{ OnTestSendClusterColorControlCommandMoveHue_9_FailureResponse, this }; + bool mIsFailureExpected_9 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveHue_9() @@ -14483,6 +14974,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_10{ OnTestSendClusterColorControlCommandStepHue_10_FailureResponse, this }; + bool mIsFailureExpected_10 = 0; CHIP_ERROR TestSendClusterColorControlCommandStepHue_10() @@ -14545,6 +15037,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_11{ OnTestSendClusterColorControlCommandStepHue_11_FailureResponse, this }; + bool mIsFailureExpected_11 = 0; CHIP_ERROR TestSendClusterColorControlCommandStepHue_11() @@ -14607,6 +15100,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_12{ OnTestSendClusterColorControlCommandMoveToSaturation_12_FailureResponse, this }; + bool mIsFailureExpected_12 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveToSaturation_12() @@ -14668,6 +15162,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_13{ OnTestSendClusterColorControlCommandMoveSaturation_13_FailureResponse, this }; + bool mIsFailureExpected_13 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveSaturation_13() @@ -14729,6 +15224,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_14{ OnTestSendClusterColorControlCommandMoveSaturation_14_FailureResponse, this }; + bool mIsFailureExpected_14 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveSaturation_14() @@ -14790,6 +15286,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_15{ OnTestSendClusterColorControlCommandStepSaturation_15_FailureResponse, this }; + bool mIsFailureExpected_15 = 0; CHIP_ERROR TestSendClusterColorControlCommandStepSaturation_15() @@ -14852,6 +15349,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_16{ OnTestSendClusterColorControlCommandStepSaturation_16_FailureResponse, this }; + bool mIsFailureExpected_16 = 0; CHIP_ERROR TestSendClusterColorControlCommandStepSaturation_16() @@ -14914,6 +15412,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_17{ OnTestSendClusterColorControlCommandMoveToHueAndSaturation_17_FailureResponse, this }; + bool mIsFailureExpected_17 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveToHueAndSaturation_17() @@ -14974,6 +15473,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnSuccessCallback_18{ OnTestSendClusterOnOffCommandOff_18_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_18{ OnTestSendClusterOnOffCommandOff_18_FailureResponse, this }; + bool mIsFailureExpected_18 = 0; CHIP_ERROR TestSendClusterOnOffCommandOff_18() @@ -15030,6 +15530,7 @@ class Test_TC_CC_3_4 : public TestCommand chip::Callback::Callback mOnFailureCallback_19{ OnTestSendClusterOnOffCommandReadAttribute_19_FailureResponse, this }; + bool mIsFailureExpected_19 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_19() @@ -15154,6 +15655,7 @@ class Test_TC_CC_5 : public TestCommand chip::Callback::Callback mOnSuccessCallback_0{ OnTestSendClusterOnOffCommandOn_0_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterOnOffCommandOn_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterOnOffCommandOn_0() @@ -15209,6 +15711,7 @@ class Test_TC_CC_5 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterOnOffCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_1() @@ -15272,6 +15775,7 @@ class Test_TC_CC_5 : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterColorControlCommandMoveToColor_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveToColor_2() @@ -15334,6 +15838,7 @@ class Test_TC_CC_5 : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterColorControlCommandMoveColor_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveColor_3() @@ -15395,6 +15900,7 @@ class Test_TC_CC_5 : public TestCommand chip::Callback::Callback mOnFailureCallback_4{ OnTestSendClusterColorControlCommandStopMoveStep_4_FailureResponse, this }; + bool mIsFailureExpected_4 = 0; CHIP_ERROR TestSendClusterColorControlCommandStopMoveStep_4() @@ -15454,6 +15960,7 @@ class Test_TC_CC_5 : public TestCommand chip::Callback::Callback mOnFailureCallback_5{ OnTestSendClusterColorControlCommandStepColor_5_FailureResponse, this }; + bool mIsFailureExpected_5 = 0; CHIP_ERROR TestSendClusterColorControlCommandStepColor_5() @@ -15513,6 +16020,7 @@ class Test_TC_CC_5 : public TestCommand chip::Callback::Callback mOnSuccessCallback_6{ OnTestSendClusterOnOffCommandOff_6_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_6{ OnTestSendClusterOnOffCommandOff_6_FailureResponse, this }; + bool mIsFailureExpected_6 = 0; CHIP_ERROR TestSendClusterOnOffCommandOff_6() @@ -15568,6 +16076,7 @@ class Test_TC_CC_5 : public TestCommand chip::Callback::Callback mOnFailureCallback_7{ OnTestSendClusterOnOffCommandReadAttribute_7_FailureResponse, this }; + bool mIsFailureExpected_7 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_7() @@ -15698,6 +16207,7 @@ class Test_TC_CC_6 : public TestCommand chip::Callback::Callback mOnSuccessCallback_0{ OnTestSendClusterOnOffCommandOn_0_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterOnOffCommandOn_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterOnOffCommandOn_0() @@ -15753,6 +16263,7 @@ class Test_TC_CC_6 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterOnOffCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_1() @@ -15816,6 +16327,7 @@ class Test_TC_CC_6 : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterColorControlCommandMoveToColorTemperature_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveToColorTemperature_2() @@ -15877,6 +16389,7 @@ class Test_TC_CC_6 : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterColorControlCommandMoveColorTemperature_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveColorTemperature_3() @@ -15941,6 +16454,7 @@ class Test_TC_CC_6 : public TestCommand chip::Callback::Callback mOnFailureCallback_4{ OnTestSendClusterColorControlCommandMoveColorTemperature_4_FailureResponse, this }; + bool mIsFailureExpected_4 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveColorTemperature_4() @@ -16005,6 +16519,7 @@ class Test_TC_CC_6 : public TestCommand chip::Callback::Callback mOnFailureCallback_5{ OnTestSendClusterColorControlCommandMoveColorTemperature_5_FailureResponse, this }; + bool mIsFailureExpected_5 = 0; CHIP_ERROR TestSendClusterColorControlCommandMoveColorTemperature_5() @@ -16069,6 +16584,7 @@ class Test_TC_CC_6 : public TestCommand chip::Callback::Callback mOnFailureCallback_6{ OnTestSendClusterColorControlCommandStepColorTemperature_6_FailureResponse, this }; + bool mIsFailureExpected_6 = 0; CHIP_ERROR TestSendClusterColorControlCommandStepColorTemperature_6() @@ -16134,6 +16650,7 @@ class Test_TC_CC_6 : public TestCommand chip::Callback::Callback mOnFailureCallback_7{ OnTestSendClusterColorControlCommandStepColorTemperature_7_FailureResponse, this }; + bool mIsFailureExpected_7 = 0; CHIP_ERROR TestSendClusterColorControlCommandStepColorTemperature_7() @@ -16196,6 +16713,7 @@ class Test_TC_CC_6 : public TestCommand chip::Callback::Callback mOnSuccessCallback_8{ OnTestSendClusterOnOffCommandOff_8_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_8{ OnTestSendClusterOnOffCommandOff_8_FailureResponse, this }; + bool mIsFailureExpected_8 = 0; CHIP_ERROR TestSendClusterOnOffCommandOff_8() @@ -16251,6 +16769,7 @@ class Test_TC_CC_6 : public TestCommand chip::Callback::Callback mOnFailureCallback_9{ OnTestSendClusterOnOffCommandReadAttribute_9_FailureResponse, this }; + bool mIsFailureExpected_9 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_9() @@ -16390,6 +16909,7 @@ class Test_TC_CC_7 : public TestCommand chip::Callback::Callback mOnSuccessCallback_0{ OnTestSendClusterOnOffCommandOn_0_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterOnOffCommandOn_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterOnOffCommandOn_0() @@ -16445,6 +16965,7 @@ class Test_TC_CC_7 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterOnOffCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_1() @@ -16508,6 +17029,7 @@ class Test_TC_CC_7 : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterColorControlCommandEnhancedMoveToHue_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterColorControlCommandEnhancedMoveToHue_2() @@ -16570,6 +17092,7 @@ class Test_TC_CC_7 : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterColorControlCommandReadAttribute_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterColorControlCommandReadAttribute_3() @@ -16639,6 +17162,7 @@ class Test_TC_CC_7 : public TestCommand chip::Callback::Callback mOnFailureCallback_4{ OnTestSendClusterColorControlCommandEnhancedMoveHue_4_FailureResponse, this }; + bool mIsFailureExpected_4 = 0; CHIP_ERROR TestSendClusterColorControlCommandEnhancedMoveHue_4() @@ -16700,6 +17224,7 @@ class Test_TC_CC_7 : public TestCommand chip::Callback::Callback mOnFailureCallback_5{ OnTestSendClusterColorControlCommandEnhancedMoveHue_5_FailureResponse, this }; + bool mIsFailureExpected_5 = 0; CHIP_ERROR TestSendClusterColorControlCommandEnhancedMoveHue_5() @@ -16761,6 +17286,7 @@ class Test_TC_CC_7 : public TestCommand chip::Callback::Callback mOnFailureCallback_6{ OnTestSendClusterColorControlCommandEnhancedMoveHue_6_FailureResponse, this }; + bool mIsFailureExpected_6 = 0; CHIP_ERROR TestSendClusterColorControlCommandEnhancedMoveHue_6() @@ -16822,6 +17348,7 @@ class Test_TC_CC_7 : public TestCommand chip::Callback::Callback mOnFailureCallback_7{ OnTestSendClusterColorControlCommandEnhancedMoveHue_7_FailureResponse, this }; + bool mIsFailureExpected_7 = 0; CHIP_ERROR TestSendClusterColorControlCommandEnhancedMoveHue_7() @@ -16883,6 +17410,7 @@ class Test_TC_CC_7 : public TestCommand chip::Callback::Callback mOnFailureCallback_8{ OnTestSendClusterColorControlCommandEnhancedStepHue_8_FailureResponse, this }; + bool mIsFailureExpected_8 = 0; CHIP_ERROR TestSendClusterColorControlCommandEnhancedStepHue_8() @@ -16945,6 +17473,7 @@ class Test_TC_CC_7 : public TestCommand chip::Callback::Callback mOnFailureCallback_9{ OnTestSendClusterColorControlCommandEnhancedStepHue_9_FailureResponse, this }; + bool mIsFailureExpected_9 = 0; CHIP_ERROR TestSendClusterColorControlCommandEnhancedStepHue_9() @@ -17007,6 +17536,7 @@ class Test_TC_CC_7 : public TestCommand chip::Callback::Callback mOnFailureCallback_10{ OnTestSendClusterColorControlCommandEnhancedMoveToHueAndSaturation_10_FailureResponse, this }; + bool mIsFailureExpected_10 = 0; CHIP_ERROR TestSendClusterColorControlCommandEnhancedMoveToHueAndSaturation_10() @@ -17068,6 +17598,7 @@ class Test_TC_CC_7 : public TestCommand chip::Callback::Callback mOnSuccessCallback_11{ OnTestSendClusterOnOffCommandOff_11_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_11{ OnTestSendClusterOnOffCommandOff_11_FailureResponse, this }; + bool mIsFailureExpected_11 = 0; CHIP_ERROR TestSendClusterOnOffCommandOff_11() @@ -17124,6 +17655,7 @@ class Test_TC_CC_7 : public TestCommand chip::Callback::Callback mOnFailureCallback_12{ OnTestSendClusterOnOffCommandReadAttribute_12_FailureResponse, this }; + bool mIsFailureExpected_12 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_12() @@ -17272,6 +17804,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnSuccessCallback_0{ OnTestSendClusterOnOffCommandOn_0_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterOnOffCommandOn_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterOnOffCommandOn_0() @@ -17327,6 +17860,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterOnOffCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_1() @@ -17390,6 +17924,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterColorControlCommandColorLoopSet_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterColorControlCommandColorLoopSet_2() @@ -17455,6 +17990,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterColorControlCommandReadAttribute_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterColorControlCommandReadAttribute_3() @@ -17518,6 +18054,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_4{ OnTestSendClusterColorControlCommandReadAttribute_4_FailureResponse, this }; + bool mIsFailureExpected_4 = 0; CHIP_ERROR TestSendClusterColorControlCommandReadAttribute_4() @@ -17581,6 +18118,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_5{ OnTestSendClusterColorControlCommandReadAttribute_5_FailureResponse, this }; + bool mIsFailureExpected_5 = 0; CHIP_ERROR TestSendClusterColorControlCommandReadAttribute_5() @@ -17645,6 +18183,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_6{ OnTestSendClusterColorControlCommandReadAttribute_6_FailureResponse, this }; + bool mIsFailureExpected_6 = 0; CHIP_ERROR TestSendClusterColorControlCommandReadAttribute_6() @@ -17708,6 +18247,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_7{ OnTestSendClusterColorControlCommandColorLoopSet_7_FailureResponse, this }; + bool mIsFailureExpected_7 = 0; CHIP_ERROR TestSendClusterColorControlCommandColorLoopSet_7() @@ -17773,6 +18313,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_8{ OnTestSendClusterColorControlCommandReadAttribute_8_FailureResponse, this }; + bool mIsFailureExpected_8 = 0; CHIP_ERROR TestSendClusterColorControlCommandReadAttribute_8() @@ -17836,6 +18377,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_9{ OnTestSendClusterColorControlCommandColorLoopSet_9_FailureResponse, this }; + bool mIsFailureExpected_9 = 0; CHIP_ERROR TestSendClusterColorControlCommandColorLoopSet_9() @@ -17904,6 +18446,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_10{ OnTestSendClusterColorControlCommandReadAttribute_10_FailureResponse, this }; + bool mIsFailureExpected_10 = 0; CHIP_ERROR TestSendClusterColorControlCommandReadAttribute_10() @@ -17967,6 +18510,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_11{ OnTestSendClusterColorControlCommandReadAttribute_11_FailureResponse, this }; + bool mIsFailureExpected_11 = 0; CHIP_ERROR TestSendClusterColorControlCommandReadAttribute_11() @@ -18030,6 +18574,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_12{ OnTestSendClusterColorControlCommandColorLoopSet_12_FailureResponse, this }; + bool mIsFailureExpected_12 = 0; CHIP_ERROR TestSendClusterColorControlCommandColorLoopSet_12() @@ -18095,6 +18640,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_13{ OnTestSendClusterColorControlCommandReadAttribute_13_FailureResponse, this }; + bool mIsFailureExpected_13 = 0; CHIP_ERROR TestSendClusterColorControlCommandReadAttribute_13() @@ -18155,6 +18701,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnSuccessCallback_14{ OnTestSendClusterOnOffCommandOff_14_SuccessResponse, this }; chip::Callback::Callback mOnFailureCallback_14{ OnTestSendClusterOnOffCommandOff_14_FailureResponse, this }; + bool mIsFailureExpected_14 = 0; CHIP_ERROR TestSendClusterOnOffCommandOff_14() @@ -18211,6 +18758,7 @@ class Test_TC_CC_8 : public TestCommand chip::Callback::Callback mOnFailureCallback_15{ OnTestSendClusterOnOffCommandReadAttribute_15_FailureResponse, this }; + bool mIsFailureExpected_15 = 0; CHIP_ERROR TestSendClusterOnOffCommandReadAttribute_15() @@ -18320,6 +18868,7 @@ class Test_TC_WNCV_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterWindowCoveringCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterWindowCoveringCommandReadAttribute_0() @@ -18383,6 +18932,7 @@ class Test_TC_WNCV_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterWindowCoveringCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterWindowCoveringCommandReadAttribute_1() @@ -18519,6 +19069,7 @@ class Test_TC_WNCV_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterWindowCoveringCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterWindowCoveringCommandReadAttribute_0() @@ -18582,6 +19133,7 @@ class Test_TC_WNCV_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterWindowCoveringCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterWindowCoveringCommandReadAttribute_1() @@ -18645,6 +19197,7 @@ class Test_TC_WNCV_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_2{ OnTestSendClusterWindowCoveringCommandReadAttribute_2_FailureResponse, this }; + bool mIsFailureExpected_2 = 0; CHIP_ERROR TestSendClusterWindowCoveringCommandReadAttribute_2() @@ -18708,6 +19261,7 @@ class Test_TC_WNCV_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_3{ OnTestSendClusterWindowCoveringCommandReadAttribute_3_FailureResponse, this }; + bool mIsFailureExpected_3 = 0; CHIP_ERROR TestSendClusterWindowCoveringCommandReadAttribute_3() @@ -18771,6 +19325,7 @@ class Test_TC_WNCV_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_4{ OnTestSendClusterWindowCoveringCommandReadAttribute_4_FailureResponse, this }; + bool mIsFailureExpected_4 = 0; CHIP_ERROR TestSendClusterWindowCoveringCommandReadAttribute_4() @@ -18835,6 +19390,7 @@ class Test_TC_WNCV_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_5{ OnTestSendClusterWindowCoveringCommandReadAttribute_5_FailureResponse, this }; + bool mIsFailureExpected_5 = 0; CHIP_ERROR TestSendClusterWindowCoveringCommandReadAttribute_5() @@ -18898,6 +19454,7 @@ class Test_TC_WNCV_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_6{ OnTestSendClusterWindowCoveringCommandReadAttribute_6_FailureResponse, this }; + bool mIsFailureExpected_6 = 0; CHIP_ERROR TestSendClusterWindowCoveringCommandReadAttribute_6() @@ -18961,6 +19518,7 @@ class Test_TC_WNCV_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_7{ OnTestSendClusterWindowCoveringCommandReadAttribute_7_FailureResponse, this }; + bool mIsFailureExpected_7 = 0; CHIP_ERROR TestSendClusterWindowCoveringCommandReadAttribute_7() @@ -19024,6 +19582,7 @@ class Test_TC_WNCV_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_8{ OnTestSendClusterWindowCoveringCommandReadAttribute_8_FailureResponse, this }; + bool mIsFailureExpected_8 = 0; CHIP_ERROR TestSendClusterWindowCoveringCommandReadAttribute_8() @@ -19087,6 +19646,7 @@ class Test_TC_WNCV_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_9{ OnTestSendClusterWindowCoveringCommandWriteAttribute_9_FailureResponse, this }; + bool mIsFailureExpected_9 = 0; CHIP_ERROR TestSendClusterWindowCoveringCommandWriteAttribute_9() @@ -19144,6 +19704,7 @@ class Test_TC_WNCV_2_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_10{ OnTestSendClusterWindowCoveringCommandReadAttribute_10_FailureResponse, this }; + bool mIsFailureExpected_10 = 0; CHIP_ERROR TestSendClusterWindowCoveringCommandReadAttribute_10() @@ -19253,6 +19814,7 @@ class Test_TC_BI_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterBinaryInputBasicCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterBinaryInputBasicCommandReadAttribute_0() @@ -19316,6 +19878,7 @@ class Test_TC_BI_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterBinaryInputBasicCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterBinaryInputBasicCommandReadAttribute_1() @@ -19465,6 +20028,7 @@ class Test_TC_TM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterTemperatureMeasurementCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterTemperatureMeasurementCommandReadAttribute_0() @@ -19529,6 +20093,7 @@ class Test_TC_TM_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterTemperatureMeasurementCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterTemperatureMeasurementCommandReadAttribute_1() @@ -19639,6 +20204,7 @@ class Test_TC_OCC_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterOccupancySensingCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterOccupancySensingCommandReadAttribute_0() @@ -19702,6 +20268,7 @@ class Test_TC_OCC_1_1 : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterOccupancySensingCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterOccupancySensingCommandReadAttribute_1() @@ -19811,6 +20378,7 @@ class OperationalCredentialsCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_0{ OnTestSendClusterOperationalCredentialsCommandReadAttribute_0_FailureResponse, this }; + bool mIsFailureExpected_0 = 0; CHIP_ERROR TestSendClusterOperationalCredentialsCommandReadAttribute_0() @@ -19877,6 +20445,7 @@ class OperationalCredentialsCluster : public TestCommand chip::Callback::Callback mOnFailureCallback_1{ OnTestSendClusterOperationalCredentialsCommandReadAttribute_1_FailureResponse, this }; + bool mIsFailureExpected_1 = 0; CHIP_ERROR TestSendClusterOperationalCredentialsCommandReadAttribute_1() @@ -19956,6 +20525,7 @@ void registerCommandsTests(Commands & commands) make_unique(), make_unique(), make_unique(), + make_unique(), make_unique(), make_unique(), make_unique(), diff --git a/zzz_generated/controller-clusters/zap-generated/CHIPClientCallbacks.cpp b/zzz_generated/controller-clusters/zap-generated/CHIPClientCallbacks.cpp index a76a63307a3f64..79f8dbc0c43d6a 100644 --- a/zzz_generated/controller-clusters/zap-generated/CHIPClientCallbacks.cpp +++ b/zzz_generated/controller-clusters/zap-generated/CHIPClientCallbacks.cpp @@ -361,9 +361,12 @@ void ApplicationLauncherClusterApplicationLauncherListListAttributeFilter(TLV::T EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -393,9 +396,12 @@ void AudioOutputClusterAudioOutputListListAttributeFilter(TLV::TLVReader * tlvDa EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -431,9 +437,12 @@ void ContentLauncherClusterAcceptsHeaderListListAttributeFilter(TLV::TLVReader * EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -465,9 +474,12 @@ void ContentLauncherClusterSupportedStreamingTypesListAttributeFilter(TLV::TLVRe EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -497,9 +509,12 @@ void DescriptorClusterDeviceListListAttributeFilter(TLV::TLVReader * tlvData, Ca EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -532,9 +547,12 @@ void DescriptorClusterServerListListAttributeFilter(TLV::TLVReader * tlvData, Ca EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -564,9 +582,12 @@ void DescriptorClusterClientListListAttributeFilter(TLV::TLVReader * tlvData, Ca EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -596,9 +617,12 @@ void DescriptorClusterPartsListListAttributeFilter(TLV::TLVReader * tlvData, Cal EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -628,9 +652,12 @@ void FixedLabelClusterLabelListListAttributeFilter(TLV::TLVReader * tlvData, Cal EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -664,9 +691,12 @@ void GeneralCommissioningClusterBasicCommissioningInfoListListAttributeFilter(TL EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -697,9 +727,12 @@ void GeneralDiagnosticsClusterNetworkInterfacesListAttributeFilter(TLV::TLVReade EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -744,9 +777,12 @@ void GroupKeyManagementClusterGroupsListAttributeFilter(TLV::TLVReader * tlvData EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -782,9 +818,12 @@ void GroupKeyManagementClusterGroupKeysListAttributeFilter(TLV::TLVReader * tlvD EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -826,9 +865,12 @@ void MediaInputClusterMediaInputListListAttributeFilter(TLV::TLVReader * tlvData EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -867,9 +909,12 @@ void OperationalCredentialsClusterFabricsListListAttributeFilter(TLV::TLVReader EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -914,9 +959,12 @@ void TvChannelClusterTvChannelListListAttributeFilter(TLV::TLVReader * tlvData, EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -959,9 +1007,12 @@ void TargetNavigatorClusterTargetNavigatorListListAttributeFilter(TLV::TLVReader EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -994,9 +1045,12 @@ void TestClusterClusterListInt8uListAttributeFilter(TLV::TLVReader * tlvData, Ca EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -1026,9 +1080,12 @@ void TestClusterClusterListOctetStringListAttributeFilter(TLV::TLVReader * tlvDa EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -1059,9 +1116,12 @@ void TestClusterClusterListStructOctetStringListAttributeFilter(TLV::TLVReader * EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -1095,9 +1155,12 @@ void ThreadNetworkDiagnosticsClusterNeighborTableListListAttributeFilter(TLV::TL EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -1167,9 +1230,12 @@ void ThreadNetworkDiagnosticsClusterRouteTableListListAttributeFilter(TLV::TLVRe EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -1227,9 +1293,12 @@ void ThreadNetworkDiagnosticsClusterSecurityPolicyListAttributeFilter(TLV::TLVRe EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -1263,9 +1332,12 @@ void ThreadNetworkDiagnosticsClusterOperationalDatasetComponentsListAttributeFil EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -1330,9 +1402,12 @@ void ThreadNetworkDiagnosticsClusterActiveNetworkFaultsListListAttributeFilter(T EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -2417,252 +2492,3 @@ bool emberAfTestClusterClusterTestSpecificResponseCallback(EndpointId endpoint, cb->mCall(cb->mContext, returnValue); return true; } - -bool emberAfReportAttributesCallback(ClusterId clusterId, uint8_t * message, uint16_t messageLen) -{ - ChipLogProgress(Zcl, "emberAfReportAttributeCallback:"); - ChipLogProgress(Zcl, " ClusterId: " ChipLogFormatMEI, ChipLogValueMEI(clusterId)); - - NodeId sourceId = emberAfCurrentCommand()->SourceNodeId(); - ChipLogProgress(Zcl, " Source NodeId: %" PRIu64, sourceId); - - EndpointId endpointId = emberAfCurrentCommand()->apsFrame->sourceEndpoint; - ChipLogProgress(Zcl, " Source EndpointId: 0x%04x", endpointId); - - // TODO onFailureCallback is just here because of the CHECK_MESSAGE_LENGTH macro. It needs to be removed. - Callback::Cancelable * onFailureCallback = nullptr; - - while (messageLen) - { - CHECK_MESSAGE_LENGTH(4); - AttributeId attributeId = Encoding::LittleEndian::Read32(message); // attribId - ChipLogProgress(Zcl, " attributeId: " ChipLogFormatMEI, ChipLogValueMEI(attributeId)); - - GET_REPORT_CALLBACK("emberAfReportAttributesCallback"); - - CHECK_MESSAGE_LENGTH(1); - uint8_t attributeType = Encoding::Read8(message); - ChipLogProgress(Zcl, " attributeType: 0x%02x", attributeType); - - switch (attributeType) - { - case 0x00: // nodata / No data - case 0x0A: // data24 / 24-bit data - case 0x0C: // data40 / 40-bit data - case 0x0D: // data48 / 48-bit data - case 0x0E: // data56 / 56-bit data - case 0x1A: // map24 / 24-bit bitmap - case 0x1C: // map40 / 40-bit bitmap - case 0x1D: // map48 / 48-bit bitmap - case 0x1E: // map56 / 56-bit bitmap - case 0x22: // uint24 / Unsigned 24-bit integer - case 0x24: // uint40 / Unsigned 40-bit integer - case 0x25: // uint48 / Unsigned 48-bit integer - case 0x26: // uint56 / Unsigned 56-bit integer - case 0x2A: // int24 / Signed 24-bit integer - case 0x2C: // int40 / Signed 40-bit integer - case 0x2D: // int48 / Signed 48-bit integer - case 0x2E: // int56 / Signed 56-bit integer - case 0x38: // semi / Semi-precision - case 0x39: // single / Single precision - case 0x3A: // double / Double precision - case 0x48: // array / Array - case 0x49: // struct / Structure - case 0x50: // set / Set - case 0x51: // bag / Bag - case 0xE0: // ToD / Time of day - { - ChipLogError(Zcl, "attributeType 0x%02x is not supported", attributeType); - return true; - } - - case 0x41: // octstr / Octet string - case 0x42: // string / Character string - { - // Short Strings must contains at least one byte for the length - CHECK_MESSAGE_LENGTH(1); - uint8_t length = Encoding::Read8(message); - ChipLogProgress(Zcl, " length: 0x%02x", length); - - // When the length is set to 0xFF, it represents a non-value. In this case the data field is zero length. - if (length == 0xFF) - { - length = 0; - } - - CHECK_MESSAGE_LENGTH(length); - if (attributeType == 0x41) - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - else - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - break; - } - - case 0x43: // octstr16 / Long octet string - case 0x44: // string16 / Long character string - { - // Long Strings must contains at least two bytes for the length - CHECK_MESSAGE_LENGTH(2); - uint16_t length = Encoding::LittleEndian::Read16(message); - ChipLogProgress(Zcl, " length: 0x%02x", length); - - // When the length is set to 0xFFFF, it represents a non-value. In this case the data field is zero length. - if (length == 0xFFFF) - { - length = 0; - } - - CHECK_MESSAGE_LENGTH(length); - if (attributeType == 0x43) - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - else - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - break; - } - - case 0x08: // data8 / 8-bit data - case 0x18: // map8 / 8-bit bitmap - case 0x20: // uint8 / Unsigned 8-bit integer - case 0x30: // enum8 / 8-bit enumeration - { - CHECK_MESSAGE_LENGTH(1); - uint8_t value = Encoding::Read8(message); - ChipLogProgress(Zcl, " value: 0x%02x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x09: // data16 / 16-bit data - case 0x19: // map16 / 16-bit bitmap - case 0x21: // uint16 / Unsigned 16-bit integer - case 0x31: // enum16 / 16-bit enumeration - case 0xE8: // clusterId / Cluster ID - case 0xE9: // attribId / Attribute ID - case 0xEA: // bacOID / BACnet OID - case 0xF1: // key128 / 128-bit security key - case 0xFF: // unk / Unknown - { - CHECK_MESSAGE_LENGTH(2); - uint16_t value = Encoding::LittleEndian::Read16(message); - ChipLogProgress(Zcl, " value: 0x%04x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x0B: // data32 / 32-bit data - case 0x1B: // map32 / 32-bit bitmap - case 0x23: // uint32 / Unsigned 32-bit integer - case 0xE1: // date / Date - case 0xE2: // UTC / UTCTime - { - CHECK_MESSAGE_LENGTH(4); - uint32_t value = Encoding::LittleEndian::Read32(message); - ChipLogProgress(Zcl, " value: 0x%08x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x0F: // data64 / 64-bit data - case 0x1F: // map64 / 64-bit bitmap - case 0x27: // uint64 / Unsigned 64-bit integer - case 0xF0: // EUI64 / IEEE address - { - CHECK_MESSAGE_LENGTH(8); - uint64_t value = Encoding::LittleEndian::Read64(message); - ChipLogProgress(Zcl, " value: 0x" ChipLogFormatX64, ChipLogValueX64(value)); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x10: // bool / Boolean - { - CHECK_MESSAGE_LENGTH(1); - uint8_t value = Encoding::Read8(message); - ChipLogProgress(Zcl, " value: %d", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x28: // int8 / Signed 8-bit integer - { - CHECK_MESSAGE_LENGTH(1); - int8_t value = CastToSigned(Encoding::Read8(message)); - ChipLogProgress(Zcl, " value: %" PRId8, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x29: // int16 / Signed 16-bit integer - { - CHECK_MESSAGE_LENGTH(2); - int16_t value = CastToSigned(Encoding::LittleEndian::Read16(message)); - ChipLogProgress(Zcl, " value: %" PRId16, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x2B: // int32 / Signed 32-bit integer - { - CHECK_MESSAGE_LENGTH(4); - int32_t value = CastToSigned(Encoding::LittleEndian::Read32(message)); - ChipLogProgress(Zcl, " value: %" PRId32, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x2F: // int64 / Signed 64-bit integer - { - CHECK_MESSAGE_LENGTH(8); - int64_t value = CastToSigned(Encoding::LittleEndian::Read64(message)); - ChipLogProgress(Zcl, " value: %" PRId64, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - } - } - - return true; -} diff --git a/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp b/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp index c305dd1925b096..1beb29f92d5fe1 100644 --- a/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp +++ b/zzz_generated/controller-clusters/zap-generated/CHIPClusters.cpp @@ -67,8 +67,6 @@ constexpr uint8_t kFrameControlGlobalCommand = 0x00; // Pick source endpoint as 1 for now constexpr EndpointId kSourceEndpoint = 1; - -[[maybe_unused]] const uint8_t kReportingDirectionReported = 0x00; } // namespace using namespace app::Clusters; @@ -1268,21 +1266,19 @@ CHIP_ERROR BinaryInputBasicCluster::ConfigureAttributePresentValue(Callback::Can Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval) { - COMMAND_HEADER("ReportBinaryInputBasicPresentValue", BinaryInputBasic::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(BinaryInputBasic::Attributes::Ids::PresentValue) - .Put8(16) - .Put16(minInterval) - .Put16(maxInterval); - COMMAND_FOOTER(); + + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = BinaryInputBasic::Attributes::Ids::PresentValue; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR BinaryInputBasicCluster::ReportAttributePresentValue(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0055, onReportCallback); + return RequestAttributeReporting(BinaryInputBasic::Attributes::Ids::PresentValue, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR BinaryInputBasicCluster::ReadAttributeStatusFlags(Callback::Cancelable * onSuccessCallback, @@ -1301,21 +1297,19 @@ CHIP_ERROR BinaryInputBasicCluster::ConfigureAttributeStatusFlags(Callback::Canc Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval) { - COMMAND_HEADER("ReportBinaryInputBasicStatusFlags", BinaryInputBasic::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(BinaryInputBasic::Attributes::Ids::StatusFlags) - .Put8(24) - .Put16(minInterval) - .Put16(maxInterval); - COMMAND_FOOTER(); + + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = BinaryInputBasic::Attributes::Ids::StatusFlags; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR BinaryInputBasicCluster::ReportAttributeStatusFlags(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x006F, onReportCallback); + return RequestAttributeReporting(BinaryInputBasic::Attributes::Ids::StatusFlags, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR BinaryInputBasicCluster::ReadAttributeClusterRevision(Callback::Cancelable * onSuccessCallback, @@ -2622,22 +2616,19 @@ CHIP_ERROR ColorControlCluster::ConfigureAttributeCurrentHue(Callback::Cancelabl Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, uint8_t change) { - COMMAND_HEADER("ReportColorControlCurrentHue", ColorControl::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(ColorControl::Attributes::Ids::CurrentHue) - .Put8(32) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put8(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = ColorControl::Attributes::Ids::CurrentHue; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR ColorControlCluster::ReportAttributeCurrentHue(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(ColorControl::Attributes::Ids::CurrentHue, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR ColorControlCluster::ReadAttributeCurrentSaturation(Callback::Cancelable * onSuccessCallback, @@ -2656,22 +2647,19 @@ CHIP_ERROR ColorControlCluster::ConfigureAttributeCurrentSaturation(Callback::Ca Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, uint8_t change) { - COMMAND_HEADER("ReportColorControlCurrentSaturation", ColorControl::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(ColorControl::Attributes::Ids::CurrentSaturation) - .Put8(32) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put8(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = ColorControl::Attributes::Ids::CurrentSaturation; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR ColorControlCluster::ReportAttributeCurrentSaturation(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0001, onReportCallback); + return RequestAttributeReporting(ColorControl::Attributes::Ids::CurrentSaturation, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR ColorControlCluster::ReadAttributeRemainingTime(Callback::Cancelable * onSuccessCallback, @@ -2702,22 +2690,19 @@ CHIP_ERROR ColorControlCluster::ConfigureAttributeCurrentX(Callback::Cancelable Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, uint16_t change) { - COMMAND_HEADER("ReportColorControlCurrentX", ColorControl::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(ColorControl::Attributes::Ids::CurrentX) - .Put8(33) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = ColorControl::Attributes::Ids::CurrentX; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR ColorControlCluster::ReportAttributeCurrentX(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0003, onReportCallback); + return RequestAttributeReporting(ColorControl::Attributes::Ids::CurrentX, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR ColorControlCluster::ReadAttributeCurrentY(Callback::Cancelable * onSuccessCallback, @@ -2736,22 +2721,19 @@ CHIP_ERROR ColorControlCluster::ConfigureAttributeCurrentY(Callback::Cancelable Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, uint16_t change) { - COMMAND_HEADER("ReportColorControlCurrentY", ColorControl::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(ColorControl::Attributes::Ids::CurrentY) - .Put8(33) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = ColorControl::Attributes::Ids::CurrentY; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR ColorControlCluster::ReportAttributeCurrentY(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0004, onReportCallback); + return RequestAttributeReporting(ColorControl::Attributes::Ids::CurrentY, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR ColorControlCluster::ReadAttributeDriftCompensation(Callback::Cancelable * onSuccessCallback, @@ -2794,22 +2776,19 @@ CHIP_ERROR ColorControlCluster::ConfigureAttributeColorTemperature(Callback::Can Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, uint16_t change) { - COMMAND_HEADER("ReportColorControlColorTemperature", ColorControl::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(ColorControl::Attributes::Ids::ColorTemperature) - .Put8(33) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = ColorControl::Attributes::Ids::ColorTemperature; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR ColorControlCluster::ReportAttributeColorTemperature(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0007, onReportCallback); + return RequestAttributeReporting(ColorControl::Attributes::Ids::ColorTemperature, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR ColorControlCluster::ReadAttributeColorMode(Callback::Cancelable * onSuccessCallback, @@ -4844,21 +4823,19 @@ CHIP_ERROR DoorLockCluster::ConfigureAttributeLockState(Callback::Cancelable * o Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval) { - COMMAND_HEADER("ReportDoorLockLockState", DoorLock::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(DoorLock::Attributes::Ids::LockState) - .Put8(48) - .Put16(minInterval) - .Put16(maxInterval); - COMMAND_FOOTER(); + + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = DoorLock::Attributes::Ids::LockState; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR DoorLockCluster::ReportAttributeLockState(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(DoorLock::Attributes::Ids::LockState, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR DoorLockCluster::ReadAttributeLockType(Callback::Cancelable * onSuccessCallback, @@ -6411,22 +6388,19 @@ CHIP_ERROR LevelControlCluster::ConfigureAttributeCurrentLevel(Callback::Cancela Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, uint8_t change) { - COMMAND_HEADER("ReportLevelControlCurrentLevel", LevelControl::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(LevelControl::Attributes::Ids::CurrentLevel) - .Put8(32) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put8(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = LevelControl::Attributes::Ids::CurrentLevel; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR LevelControlCluster::ReportAttributeCurrentLevel(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(LevelControl::Attributes::Ids::CurrentLevel, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR LevelControlCluster::ReadAttributeClusterRevision(Callback::Cancelable * onSuccessCallback, @@ -7812,21 +7786,19 @@ CHIP_ERROR OccupancySensingCluster::ConfigureAttributeOccupancy(Callback::Cancel Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval) { - COMMAND_HEADER("ReportOccupancySensingOccupancy", OccupancySensing::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(OccupancySensing::Attributes::Ids::Occupancy) - .Put8(24) - .Put16(minInterval) - .Put16(maxInterval); - COMMAND_FOOTER(); + + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = OccupancySensing::Attributes::Ids::Occupancy; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR OccupancySensingCluster::ReportAttributeOccupancy(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(OccupancySensing::Attributes::Ids::Occupancy, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR OccupancySensingCluster::ReadAttributeOccupancySensorType(Callback::Cancelable * onSuccessCallback, @@ -8128,21 +8100,19 @@ CHIP_ERROR OnOffCluster::ReadAttributeOnOff(Callback::Cancelable * onSuccessCall CHIP_ERROR OnOffCluster::ConfigureAttributeOnOff(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval) { - COMMAND_HEADER("ReportOnOffOnOff", OnOff::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(OnOff::Attributes::Ids::OnOff) - .Put8(16) - .Put16(minInterval) - .Put16(maxInterval); - COMMAND_FOOTER(); + + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = OnOff::Attributes::Ids::OnOff; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR OnOffCluster::ReportAttributeOnOff(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(OnOff::Attributes::Ids::OnOff, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR OnOffCluster::ReadAttributeGlobalSceneControl(Callback::Cancelable * onSuccessCallback, @@ -8714,22 +8684,19 @@ CHIP_ERROR PressureMeasurementCluster::ConfigureAttributeMeasuredValue(Callback: Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, int16_t change) { - COMMAND_HEADER("ReportPressureMeasurementMeasuredValue", PressureMeasurement::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(PressureMeasurement::Attributes::Ids::MeasuredValue) - .Put8(41) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = PressureMeasurement::Attributes::Ids::MeasuredValue; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR PressureMeasurementCluster::ReportAttributeMeasuredValue(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(PressureMeasurement::Attributes::Ids::MeasuredValue, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR PressureMeasurementCluster::ReadAttributeMinMeasuredValue(Callback::Cancelable * onSuccessCallback, @@ -8855,22 +8822,19 @@ CHIP_ERROR PumpConfigurationAndControlCluster::ConfigureAttributeCapacity(Callba uint16_t minInterval, uint16_t maxInterval, int16_t change) { - COMMAND_HEADER("ReportPumpConfigurationAndControlCapacity", PumpConfigurationAndControl::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(PumpConfigurationAndControl::Attributes::Ids::Capacity) - .Put8(41) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = PumpConfigurationAndControl::Attributes::Ids::Capacity; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR PumpConfigurationAndControlCluster::ReportAttributeCapacity(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0013, onReportCallback); + return RequestAttributeReporting(PumpConfigurationAndControl::Attributes::Ids::Capacity, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR PumpConfigurationAndControlCluster::ReadAttributeOperationMode(Callback::Cancelable * onSuccessCallback, @@ -8941,22 +8905,19 @@ CHIP_ERROR RelativeHumidityMeasurementCluster::ConfigureAttributeMeasuredValue(C uint16_t minInterval, uint16_t maxInterval, uint16_t change) { - COMMAND_HEADER("ReportRelativeHumidityMeasurementMeasuredValue", RelativeHumidityMeasurement::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(RelativeHumidityMeasurement::Attributes::Ids::MeasuredValue) - .Put8(33) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = RelativeHumidityMeasurement::Attributes::Ids::MeasuredValue; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR RelativeHumidityMeasurementCluster::ReportAttributeMeasuredValue(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(RelativeHumidityMeasurement::Attributes::Ids::MeasuredValue, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR RelativeHumidityMeasurementCluster::ReadAttributeMinMeasuredValue(Callback::Cancelable * onSuccessCallback, @@ -9497,22 +9458,19 @@ CHIP_ERROR SwitchCluster::ConfigureAttributeCurrentPosition(Callback::Cancelable Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, uint8_t change) { - COMMAND_HEADER("ReportSwitchCurrentPosition", Switch::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(Switch::Attributes::Ids::CurrentPosition) - .Put8(32) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put8(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = Switch::Attributes::Ids::CurrentPosition; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR SwitchCluster::ReportAttributeCurrentPosition(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0001, onReportCallback); + return RequestAttributeReporting(Switch::Attributes::Ids::CurrentPosition, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR SwitchCluster::ReadAttributeClusterRevision(Callback::Cancelable * onSuccessCallback, @@ -9814,22 +9772,19 @@ CHIP_ERROR TemperatureMeasurementCluster::ConfigureAttributeMeasuredValue(Callba uint16_t minInterval, uint16_t maxInterval, int16_t change) { - COMMAND_HEADER("ReportTemperatureMeasurementMeasuredValue", TemperatureMeasurement::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(TemperatureMeasurement::Attributes::Ids::MeasuredValue) - .Put8(41) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = TemperatureMeasurement::Attributes::Ids::MeasuredValue; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR TemperatureMeasurementCluster::ReportAttributeMeasuredValue(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(TemperatureMeasurement::Attributes::Ids::MeasuredValue, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR TemperatureMeasurementCluster::ReadAttributeMinMeasuredValue(Callback::Cancelable * onSuccessCallback, @@ -10938,22 +10893,19 @@ CHIP_ERROR ThermostatCluster::ConfigureAttributeLocalTemperature(Callback::Cance Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, int16_t change) { - COMMAND_HEADER("ReportThermostatLocalTemperature", Thermostat::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(Thermostat::Attributes::Ids::LocalTemperature) - .Put8(41) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = Thermostat::Attributes::Ids::LocalTemperature; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR ThermostatCluster::ReportAttributeLocalTemperature(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(Thermostat::Attributes::Ids::LocalTemperature, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR ThermostatCluster::ReadAttributeAbsMinHeatSetpointLimit(Callback::Cancelable * onSuccessCallback, @@ -12704,22 +12656,19 @@ CHIP_ERROR WindowCoveringCluster::ConfigureAttributeCurrentPositionLiftPercentag uint16_t minInterval, uint16_t maxInterval, uint8_t change) { - COMMAND_HEADER("ReportWindowCoveringCurrentPositionLiftPercentage", WindowCovering::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(WindowCovering::Attributes::Ids::CurrentPositionLiftPercentage) - .Put8(32) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put8(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = WindowCovering::Attributes::Ids::CurrentPositionLiftPercentage; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR WindowCoveringCluster::ReportAttributeCurrentPositionLiftPercentage(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0008, onReportCallback); + return RequestAttributeReporting(WindowCovering::Attributes::Ids::CurrentPositionLiftPercentage, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR WindowCoveringCluster::ReadAttributeCurrentPositionTiltPercentage(Callback::Cancelable * onSuccessCallback, @@ -12739,22 +12688,19 @@ CHIP_ERROR WindowCoveringCluster::ConfigureAttributeCurrentPositionTiltPercentag uint16_t minInterval, uint16_t maxInterval, uint8_t change) { - COMMAND_HEADER("ReportWindowCoveringCurrentPositionTiltPercentage", WindowCovering::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(WindowCovering::Attributes::Ids::CurrentPositionTiltPercentage) - .Put8(32) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put8(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = WindowCovering::Attributes::Ids::CurrentPositionTiltPercentage; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR WindowCoveringCluster::ReportAttributeCurrentPositionTiltPercentage(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0009, onReportCallback); + return RequestAttributeReporting(WindowCovering::Attributes::Ids::CurrentPositionTiltPercentage, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR WindowCoveringCluster::ReadAttributeOperationalStatus(Callback::Cancelable * onSuccessCallback, @@ -12773,21 +12719,19 @@ CHIP_ERROR WindowCoveringCluster::ConfigureAttributeOperationalStatus(Callback:: Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval) { - COMMAND_HEADER("ReportWindowCoveringOperationalStatus", WindowCovering::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(WindowCovering::Attributes::Ids::OperationalStatus) - .Put8(24) - .Put16(minInterval) - .Put16(maxInterval); - COMMAND_FOOTER(); + + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = WindowCovering::Attributes::Ids::OperationalStatus; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR WindowCoveringCluster::ReportAttributeOperationalStatus(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x000A, onReportCallback); + return RequestAttributeReporting(WindowCovering::Attributes::Ids::OperationalStatus, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR WindowCoveringCluster::ReadAttributeTargetPositionLiftPercent100ths(Callback::Cancelable * onSuccessCallback, @@ -12807,22 +12751,19 @@ CHIP_ERROR WindowCoveringCluster::ConfigureAttributeTargetPositionLiftPercent100 uint16_t minInterval, uint16_t maxInterval, uint16_t change) { - COMMAND_HEADER("ReportWindowCoveringTargetPositionLiftPercent100ths", WindowCovering::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(WindowCovering::Attributes::Ids::TargetPositionLiftPercent100ths) - .Put8(33) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = WindowCovering::Attributes::Ids::TargetPositionLiftPercent100ths; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR WindowCoveringCluster::ReportAttributeTargetPositionLiftPercent100ths(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x000B, onReportCallback); + return RequestAttributeReporting(WindowCovering::Attributes::Ids::TargetPositionLiftPercent100ths, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR WindowCoveringCluster::ReadAttributeTargetPositionTiltPercent100ths(Callback::Cancelable * onSuccessCallback, @@ -12842,22 +12783,19 @@ CHIP_ERROR WindowCoveringCluster::ConfigureAttributeTargetPositionTiltPercent100 uint16_t minInterval, uint16_t maxInterval, uint16_t change) { - COMMAND_HEADER("ReportWindowCoveringTargetPositionTiltPercent100ths", WindowCovering::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(WindowCovering::Attributes::Ids::TargetPositionTiltPercent100ths) - .Put8(33) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = WindowCovering::Attributes::Ids::TargetPositionTiltPercent100ths; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR WindowCoveringCluster::ReportAttributeTargetPositionTiltPercent100ths(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x000C, onReportCallback); + return RequestAttributeReporting(WindowCovering::Attributes::Ids::TargetPositionTiltPercent100ths, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR WindowCoveringCluster::ReadAttributeEndProductType(Callback::Cancelable * onSuccessCallback, @@ -12889,22 +12827,19 @@ CHIP_ERROR WindowCoveringCluster::ConfigureAttributeCurrentPositionLiftPercent10 uint16_t minInterval, uint16_t maxInterval, uint16_t change) { - COMMAND_HEADER("ReportWindowCoveringCurrentPositionLiftPercent100ths", WindowCovering::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(WindowCovering::Attributes::Ids::CurrentPositionLiftPercent100ths) - .Put8(33) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = WindowCovering::Attributes::Ids::CurrentPositionLiftPercent100ths; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR WindowCoveringCluster::ReportAttributeCurrentPositionLiftPercent100ths(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x000E, onReportCallback); + return RequestAttributeReporting(WindowCovering::Attributes::Ids::CurrentPositionLiftPercent100ths, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR WindowCoveringCluster::ReadAttributeCurrentPositionTiltPercent100ths(Callback::Cancelable * onSuccessCallback, @@ -12924,22 +12859,19 @@ CHIP_ERROR WindowCoveringCluster::ConfigureAttributeCurrentPositionTiltPercent10 uint16_t minInterval, uint16_t maxInterval, uint16_t change) { - COMMAND_HEADER("ReportWindowCoveringCurrentPositionTiltPercent100ths", WindowCovering::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(WindowCovering::Attributes::Ids::CurrentPositionTiltPercent100ths) - .Put8(33) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = WindowCovering::Attributes::Ids::CurrentPositionTiltPercent100ths; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR WindowCoveringCluster::ReportAttributeCurrentPositionTiltPercent100ths(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x000F, onReportCallback); + return RequestAttributeReporting(WindowCovering::Attributes::Ids::CurrentPositionTiltPercent100ths, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR WindowCoveringCluster::ReadAttributeInstalledOpenLimitLift(Callback::Cancelable * onSuccessCallback, @@ -13035,21 +12967,19 @@ CHIP_ERROR WindowCoveringCluster::ConfigureAttributeSafetyStatus(Callback::Cance Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval) { - COMMAND_HEADER("ReportWindowCoveringSafetyStatus", WindowCovering::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(WindowCovering::Attributes::Ids::SafetyStatus) - .Put8(25) - .Put16(minInterval) - .Put16(maxInterval); - COMMAND_FOOTER(); + + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = WindowCovering::Attributes::Ids::SafetyStatus; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR WindowCoveringCluster::ReportAttributeSafetyStatus(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x001A, onReportCallback); + return RequestAttributeReporting(WindowCovering::Attributes::Ids::SafetyStatus, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR WindowCoveringCluster::ReadAttributeClusterRevision(Callback::Cancelable * onSuccessCallback, diff --git a/zzz_generated/lighting-app/zap-generated/CHIPClientCallbacks.cpp b/zzz_generated/lighting-app/zap-generated/CHIPClientCallbacks.cpp index e5c220dd2c98b9..33694badf51838 100644 --- a/zzz_generated/lighting-app/zap-generated/CHIPClientCallbacks.cpp +++ b/zzz_generated/lighting-app/zap-generated/CHIPClientCallbacks.cpp @@ -350,252 +350,3 @@ bool emberAfDiscoverCommandsReceivedResponseCallback(ClusterId clusterId, uint16 cb->mCall(cb->mContext); return true; } - -bool emberAfReportAttributesCallback(ClusterId clusterId, uint8_t * message, uint16_t messageLen) -{ - ChipLogProgress(Zcl, "emberAfReportAttributeCallback:"); - ChipLogProgress(Zcl, " ClusterId: " ChipLogFormatMEI, ChipLogValueMEI(clusterId)); - - NodeId sourceId = emberAfCurrentCommand()->SourceNodeId(); - ChipLogProgress(Zcl, " Source NodeId: %" PRIu64, sourceId); - - EndpointId endpointId = emberAfCurrentCommand()->apsFrame->sourceEndpoint; - ChipLogProgress(Zcl, " Source EndpointId: 0x%04x", endpointId); - - // TODO onFailureCallback is just here because of the CHECK_MESSAGE_LENGTH macro. It needs to be removed. - Callback::Cancelable * onFailureCallback = nullptr; - - while (messageLen) - { - CHECK_MESSAGE_LENGTH(4); - AttributeId attributeId = Encoding::LittleEndian::Read32(message); // attribId - ChipLogProgress(Zcl, " attributeId: " ChipLogFormatMEI, ChipLogValueMEI(attributeId)); - - GET_REPORT_CALLBACK("emberAfReportAttributesCallback"); - - CHECK_MESSAGE_LENGTH(1); - uint8_t attributeType = Encoding::Read8(message); - ChipLogProgress(Zcl, " attributeType: 0x%02x", attributeType); - - switch (attributeType) - { - case 0x00: // nodata / No data - case 0x0A: // data24 / 24-bit data - case 0x0C: // data40 / 40-bit data - case 0x0D: // data48 / 48-bit data - case 0x0E: // data56 / 56-bit data - case 0x1A: // map24 / 24-bit bitmap - case 0x1C: // map40 / 40-bit bitmap - case 0x1D: // map48 / 48-bit bitmap - case 0x1E: // map56 / 56-bit bitmap - case 0x22: // uint24 / Unsigned 24-bit integer - case 0x24: // uint40 / Unsigned 40-bit integer - case 0x25: // uint48 / Unsigned 48-bit integer - case 0x26: // uint56 / Unsigned 56-bit integer - case 0x2A: // int24 / Signed 24-bit integer - case 0x2C: // int40 / Signed 40-bit integer - case 0x2D: // int48 / Signed 48-bit integer - case 0x2E: // int56 / Signed 56-bit integer - case 0x38: // semi / Semi-precision - case 0x39: // single / Single precision - case 0x3A: // double / Double precision - case 0x48: // array / Array - case 0x49: // struct / Structure - case 0x50: // set / Set - case 0x51: // bag / Bag - case 0xE0: // ToD / Time of day - { - ChipLogError(Zcl, "attributeType 0x%02x is not supported", attributeType); - return true; - } - - case 0x41: // octstr / Octet string - case 0x42: // string / Character string - { - // Short Strings must contains at least one byte for the length - CHECK_MESSAGE_LENGTH(1); - uint8_t length = Encoding::Read8(message); - ChipLogProgress(Zcl, " length: 0x%02x", length); - - // When the length is set to 0xFF, it represents a non-value. In this case the data field is zero length. - if (length == 0xFF) - { - length = 0; - } - - CHECK_MESSAGE_LENGTH(length); - if (attributeType == 0x41) - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - else - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - break; - } - - case 0x43: // octstr16 / Long octet string - case 0x44: // string16 / Long character string - { - // Long Strings must contains at least two bytes for the length - CHECK_MESSAGE_LENGTH(2); - uint16_t length = Encoding::LittleEndian::Read16(message); - ChipLogProgress(Zcl, " length: 0x%02x", length); - - // When the length is set to 0xFFFF, it represents a non-value. In this case the data field is zero length. - if (length == 0xFFFF) - { - length = 0; - } - - CHECK_MESSAGE_LENGTH(length); - if (attributeType == 0x43) - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - else - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - break; - } - - case 0x08: // data8 / 8-bit data - case 0x18: // map8 / 8-bit bitmap - case 0x20: // uint8 / Unsigned 8-bit integer - case 0x30: // enum8 / 8-bit enumeration - { - CHECK_MESSAGE_LENGTH(1); - uint8_t value = Encoding::Read8(message); - ChipLogProgress(Zcl, " value: 0x%02x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x09: // data16 / 16-bit data - case 0x19: // map16 / 16-bit bitmap - case 0x21: // uint16 / Unsigned 16-bit integer - case 0x31: // enum16 / 16-bit enumeration - case 0xE8: // clusterId / Cluster ID - case 0xE9: // attribId / Attribute ID - case 0xEA: // bacOID / BACnet OID - case 0xF1: // key128 / 128-bit security key - case 0xFF: // unk / Unknown - { - CHECK_MESSAGE_LENGTH(2); - uint16_t value = Encoding::LittleEndian::Read16(message); - ChipLogProgress(Zcl, " value: 0x%04x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x0B: // data32 / 32-bit data - case 0x1B: // map32 / 32-bit bitmap - case 0x23: // uint32 / Unsigned 32-bit integer - case 0xE1: // date / Date - case 0xE2: // UTC / UTCTime - { - CHECK_MESSAGE_LENGTH(4); - uint32_t value = Encoding::LittleEndian::Read32(message); - ChipLogProgress(Zcl, " value: 0x%08x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x0F: // data64 / 64-bit data - case 0x1F: // map64 / 64-bit bitmap - case 0x27: // uint64 / Unsigned 64-bit integer - case 0xF0: // EUI64 / IEEE address - { - CHECK_MESSAGE_LENGTH(8); - uint64_t value = Encoding::LittleEndian::Read64(message); - ChipLogProgress(Zcl, " value: 0x" ChipLogFormatX64, ChipLogValueX64(value)); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x10: // bool / Boolean - { - CHECK_MESSAGE_LENGTH(1); - uint8_t value = Encoding::Read8(message); - ChipLogProgress(Zcl, " value: %d", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x28: // int8 / Signed 8-bit integer - { - CHECK_MESSAGE_LENGTH(1); - int8_t value = CastToSigned(Encoding::Read8(message)); - ChipLogProgress(Zcl, " value: %" PRId8, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x29: // int16 / Signed 16-bit integer - { - CHECK_MESSAGE_LENGTH(2); - int16_t value = CastToSigned(Encoding::LittleEndian::Read16(message)); - ChipLogProgress(Zcl, " value: %" PRId16, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x2B: // int32 / Signed 32-bit integer - { - CHECK_MESSAGE_LENGTH(4); - int32_t value = CastToSigned(Encoding::LittleEndian::Read32(message)); - ChipLogProgress(Zcl, " value: %" PRId32, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x2F: // int64 / Signed 64-bit integer - { - CHECK_MESSAGE_LENGTH(8); - int64_t value = CastToSigned(Encoding::LittleEndian::Read64(message)); - ChipLogProgress(Zcl, " value: %" PRId64, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - } - } - - return true; -} diff --git a/zzz_generated/lighting-app/zap-generated/CHIPClusters.cpp b/zzz_generated/lighting-app/zap-generated/CHIPClusters.cpp index 541efcc26190ca..85c9e30b60229c 100644 --- a/zzz_generated/lighting-app/zap-generated/CHIPClusters.cpp +++ b/zzz_generated/lighting-app/zap-generated/CHIPClusters.cpp @@ -67,8 +67,6 @@ constexpr uint8_t kFrameControlGlobalCommand = 0x00; // Pick source endpoint as 1 for now constexpr EndpointId kSourceEndpoint = 1; - -[[maybe_unused]] const uint8_t kReportingDirectionReported = 0x00; } // namespace using namespace app::Clusters; diff --git a/zzz_generated/pump-app/zap-generated/CHIPClientCallbacks.cpp b/zzz_generated/pump-app/zap-generated/CHIPClientCallbacks.cpp index e5c220dd2c98b9..33694badf51838 100644 --- a/zzz_generated/pump-app/zap-generated/CHIPClientCallbacks.cpp +++ b/zzz_generated/pump-app/zap-generated/CHIPClientCallbacks.cpp @@ -350,252 +350,3 @@ bool emberAfDiscoverCommandsReceivedResponseCallback(ClusterId clusterId, uint16 cb->mCall(cb->mContext); return true; } - -bool emberAfReportAttributesCallback(ClusterId clusterId, uint8_t * message, uint16_t messageLen) -{ - ChipLogProgress(Zcl, "emberAfReportAttributeCallback:"); - ChipLogProgress(Zcl, " ClusterId: " ChipLogFormatMEI, ChipLogValueMEI(clusterId)); - - NodeId sourceId = emberAfCurrentCommand()->SourceNodeId(); - ChipLogProgress(Zcl, " Source NodeId: %" PRIu64, sourceId); - - EndpointId endpointId = emberAfCurrentCommand()->apsFrame->sourceEndpoint; - ChipLogProgress(Zcl, " Source EndpointId: 0x%04x", endpointId); - - // TODO onFailureCallback is just here because of the CHECK_MESSAGE_LENGTH macro. It needs to be removed. - Callback::Cancelable * onFailureCallback = nullptr; - - while (messageLen) - { - CHECK_MESSAGE_LENGTH(4); - AttributeId attributeId = Encoding::LittleEndian::Read32(message); // attribId - ChipLogProgress(Zcl, " attributeId: " ChipLogFormatMEI, ChipLogValueMEI(attributeId)); - - GET_REPORT_CALLBACK("emberAfReportAttributesCallback"); - - CHECK_MESSAGE_LENGTH(1); - uint8_t attributeType = Encoding::Read8(message); - ChipLogProgress(Zcl, " attributeType: 0x%02x", attributeType); - - switch (attributeType) - { - case 0x00: // nodata / No data - case 0x0A: // data24 / 24-bit data - case 0x0C: // data40 / 40-bit data - case 0x0D: // data48 / 48-bit data - case 0x0E: // data56 / 56-bit data - case 0x1A: // map24 / 24-bit bitmap - case 0x1C: // map40 / 40-bit bitmap - case 0x1D: // map48 / 48-bit bitmap - case 0x1E: // map56 / 56-bit bitmap - case 0x22: // uint24 / Unsigned 24-bit integer - case 0x24: // uint40 / Unsigned 40-bit integer - case 0x25: // uint48 / Unsigned 48-bit integer - case 0x26: // uint56 / Unsigned 56-bit integer - case 0x2A: // int24 / Signed 24-bit integer - case 0x2C: // int40 / Signed 40-bit integer - case 0x2D: // int48 / Signed 48-bit integer - case 0x2E: // int56 / Signed 56-bit integer - case 0x38: // semi / Semi-precision - case 0x39: // single / Single precision - case 0x3A: // double / Double precision - case 0x48: // array / Array - case 0x49: // struct / Structure - case 0x50: // set / Set - case 0x51: // bag / Bag - case 0xE0: // ToD / Time of day - { - ChipLogError(Zcl, "attributeType 0x%02x is not supported", attributeType); - return true; - } - - case 0x41: // octstr / Octet string - case 0x42: // string / Character string - { - // Short Strings must contains at least one byte for the length - CHECK_MESSAGE_LENGTH(1); - uint8_t length = Encoding::Read8(message); - ChipLogProgress(Zcl, " length: 0x%02x", length); - - // When the length is set to 0xFF, it represents a non-value. In this case the data field is zero length. - if (length == 0xFF) - { - length = 0; - } - - CHECK_MESSAGE_LENGTH(length); - if (attributeType == 0x41) - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - else - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - break; - } - - case 0x43: // octstr16 / Long octet string - case 0x44: // string16 / Long character string - { - // Long Strings must contains at least two bytes for the length - CHECK_MESSAGE_LENGTH(2); - uint16_t length = Encoding::LittleEndian::Read16(message); - ChipLogProgress(Zcl, " length: 0x%02x", length); - - // When the length is set to 0xFFFF, it represents a non-value. In this case the data field is zero length. - if (length == 0xFFFF) - { - length = 0; - } - - CHECK_MESSAGE_LENGTH(length); - if (attributeType == 0x43) - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - else - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - break; - } - - case 0x08: // data8 / 8-bit data - case 0x18: // map8 / 8-bit bitmap - case 0x20: // uint8 / Unsigned 8-bit integer - case 0x30: // enum8 / 8-bit enumeration - { - CHECK_MESSAGE_LENGTH(1); - uint8_t value = Encoding::Read8(message); - ChipLogProgress(Zcl, " value: 0x%02x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x09: // data16 / 16-bit data - case 0x19: // map16 / 16-bit bitmap - case 0x21: // uint16 / Unsigned 16-bit integer - case 0x31: // enum16 / 16-bit enumeration - case 0xE8: // clusterId / Cluster ID - case 0xE9: // attribId / Attribute ID - case 0xEA: // bacOID / BACnet OID - case 0xF1: // key128 / 128-bit security key - case 0xFF: // unk / Unknown - { - CHECK_MESSAGE_LENGTH(2); - uint16_t value = Encoding::LittleEndian::Read16(message); - ChipLogProgress(Zcl, " value: 0x%04x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x0B: // data32 / 32-bit data - case 0x1B: // map32 / 32-bit bitmap - case 0x23: // uint32 / Unsigned 32-bit integer - case 0xE1: // date / Date - case 0xE2: // UTC / UTCTime - { - CHECK_MESSAGE_LENGTH(4); - uint32_t value = Encoding::LittleEndian::Read32(message); - ChipLogProgress(Zcl, " value: 0x%08x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x0F: // data64 / 64-bit data - case 0x1F: // map64 / 64-bit bitmap - case 0x27: // uint64 / Unsigned 64-bit integer - case 0xF0: // EUI64 / IEEE address - { - CHECK_MESSAGE_LENGTH(8); - uint64_t value = Encoding::LittleEndian::Read64(message); - ChipLogProgress(Zcl, " value: 0x" ChipLogFormatX64, ChipLogValueX64(value)); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x10: // bool / Boolean - { - CHECK_MESSAGE_LENGTH(1); - uint8_t value = Encoding::Read8(message); - ChipLogProgress(Zcl, " value: %d", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x28: // int8 / Signed 8-bit integer - { - CHECK_MESSAGE_LENGTH(1); - int8_t value = CastToSigned(Encoding::Read8(message)); - ChipLogProgress(Zcl, " value: %" PRId8, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x29: // int16 / Signed 16-bit integer - { - CHECK_MESSAGE_LENGTH(2); - int16_t value = CastToSigned(Encoding::LittleEndian::Read16(message)); - ChipLogProgress(Zcl, " value: %" PRId16, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x2B: // int32 / Signed 32-bit integer - { - CHECK_MESSAGE_LENGTH(4); - int32_t value = CastToSigned(Encoding::LittleEndian::Read32(message)); - ChipLogProgress(Zcl, " value: %" PRId32, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x2F: // int64 / Signed 64-bit integer - { - CHECK_MESSAGE_LENGTH(8); - int64_t value = CastToSigned(Encoding::LittleEndian::Read64(message)); - ChipLogProgress(Zcl, " value: %" PRId64, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - } - } - - return true; -} diff --git a/zzz_generated/pump-app/zap-generated/CHIPClusters.cpp b/zzz_generated/pump-app/zap-generated/CHIPClusters.cpp index a5cbbc3f366b40..45de1d65c879d2 100644 --- a/zzz_generated/pump-app/zap-generated/CHIPClusters.cpp +++ b/zzz_generated/pump-app/zap-generated/CHIPClusters.cpp @@ -67,8 +67,6 @@ constexpr uint8_t kFrameControlGlobalCommand = 0x00; // Pick source endpoint as 1 for now constexpr EndpointId kSourceEndpoint = 1; - -[[maybe_unused]] const uint8_t kReportingDirectionReported = 0x00; } // namespace using namespace app::Clusters; @@ -107,22 +105,19 @@ CHIP_ERROR FlowMeasurementCluster::ConfigureAttributeMeasuredValue(Callback::Can Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, int16_t change) { - COMMAND_HEADER("ReportFlowMeasurementMeasuredValue", FlowMeasurement::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(FlowMeasurement::Attributes::Ids::MeasuredValue) - .Put8(41) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = FlowMeasurement::Attributes::Ids::MeasuredValue; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR FlowMeasurementCluster::ReportAttributeMeasuredValue(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(FlowMeasurement::Attributes::Ids::MeasuredValue, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR FlowMeasurementCluster::ReadAttributeMinMeasuredValue(Callback::Cancelable * onSuccessCallback, @@ -187,22 +182,19 @@ CHIP_ERROR PressureMeasurementCluster::ConfigureAttributeMeasuredValue(Callback: Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, int16_t change) { - COMMAND_HEADER("ReportPressureMeasurementMeasuredValue", PressureMeasurement::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(PressureMeasurement::Attributes::Ids::MeasuredValue) - .Put8(41) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = PressureMeasurement::Attributes::Ids::MeasuredValue; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR PressureMeasurementCluster::ReportAttributeMeasuredValue(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(PressureMeasurement::Attributes::Ids::MeasuredValue, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR PressureMeasurementCluster::ReadAttributeMinMeasuredValue(Callback::Cancelable * onSuccessCallback, @@ -268,22 +260,19 @@ CHIP_ERROR TemperatureMeasurementCluster::ConfigureAttributeMeasuredValue(Callba uint16_t minInterval, uint16_t maxInterval, int16_t change) { - COMMAND_HEADER("ReportTemperatureMeasurementMeasuredValue", TemperatureMeasurement::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(TemperatureMeasurement::Attributes::Ids::MeasuredValue) - .Put8(41) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = TemperatureMeasurement::Attributes::Ids::MeasuredValue; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR TemperatureMeasurementCluster::ReportAttributeMeasuredValue(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(TemperatureMeasurement::Attributes::Ids::MeasuredValue, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR TemperatureMeasurementCluster::ReadAttributeMinMeasuredValue(Callback::Cancelable * onSuccessCallback, diff --git a/zzz_generated/pump-controller-app/zap-generated/CHIPClientCallbacks.cpp b/zzz_generated/pump-controller-app/zap-generated/CHIPClientCallbacks.cpp index e5c220dd2c98b9..33694badf51838 100644 --- a/zzz_generated/pump-controller-app/zap-generated/CHIPClientCallbacks.cpp +++ b/zzz_generated/pump-controller-app/zap-generated/CHIPClientCallbacks.cpp @@ -350,252 +350,3 @@ bool emberAfDiscoverCommandsReceivedResponseCallback(ClusterId clusterId, uint16 cb->mCall(cb->mContext); return true; } - -bool emberAfReportAttributesCallback(ClusterId clusterId, uint8_t * message, uint16_t messageLen) -{ - ChipLogProgress(Zcl, "emberAfReportAttributeCallback:"); - ChipLogProgress(Zcl, " ClusterId: " ChipLogFormatMEI, ChipLogValueMEI(clusterId)); - - NodeId sourceId = emberAfCurrentCommand()->SourceNodeId(); - ChipLogProgress(Zcl, " Source NodeId: %" PRIu64, sourceId); - - EndpointId endpointId = emberAfCurrentCommand()->apsFrame->sourceEndpoint; - ChipLogProgress(Zcl, " Source EndpointId: 0x%04x", endpointId); - - // TODO onFailureCallback is just here because of the CHECK_MESSAGE_LENGTH macro. It needs to be removed. - Callback::Cancelable * onFailureCallback = nullptr; - - while (messageLen) - { - CHECK_MESSAGE_LENGTH(4); - AttributeId attributeId = Encoding::LittleEndian::Read32(message); // attribId - ChipLogProgress(Zcl, " attributeId: " ChipLogFormatMEI, ChipLogValueMEI(attributeId)); - - GET_REPORT_CALLBACK("emberAfReportAttributesCallback"); - - CHECK_MESSAGE_LENGTH(1); - uint8_t attributeType = Encoding::Read8(message); - ChipLogProgress(Zcl, " attributeType: 0x%02x", attributeType); - - switch (attributeType) - { - case 0x00: // nodata / No data - case 0x0A: // data24 / 24-bit data - case 0x0C: // data40 / 40-bit data - case 0x0D: // data48 / 48-bit data - case 0x0E: // data56 / 56-bit data - case 0x1A: // map24 / 24-bit bitmap - case 0x1C: // map40 / 40-bit bitmap - case 0x1D: // map48 / 48-bit bitmap - case 0x1E: // map56 / 56-bit bitmap - case 0x22: // uint24 / Unsigned 24-bit integer - case 0x24: // uint40 / Unsigned 40-bit integer - case 0x25: // uint48 / Unsigned 48-bit integer - case 0x26: // uint56 / Unsigned 56-bit integer - case 0x2A: // int24 / Signed 24-bit integer - case 0x2C: // int40 / Signed 40-bit integer - case 0x2D: // int48 / Signed 48-bit integer - case 0x2E: // int56 / Signed 56-bit integer - case 0x38: // semi / Semi-precision - case 0x39: // single / Single precision - case 0x3A: // double / Double precision - case 0x48: // array / Array - case 0x49: // struct / Structure - case 0x50: // set / Set - case 0x51: // bag / Bag - case 0xE0: // ToD / Time of day - { - ChipLogError(Zcl, "attributeType 0x%02x is not supported", attributeType); - return true; - } - - case 0x41: // octstr / Octet string - case 0x42: // string / Character string - { - // Short Strings must contains at least one byte for the length - CHECK_MESSAGE_LENGTH(1); - uint8_t length = Encoding::Read8(message); - ChipLogProgress(Zcl, " length: 0x%02x", length); - - // When the length is set to 0xFF, it represents a non-value. In this case the data field is zero length. - if (length == 0xFF) - { - length = 0; - } - - CHECK_MESSAGE_LENGTH(length); - if (attributeType == 0x41) - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - else - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - break; - } - - case 0x43: // octstr16 / Long octet string - case 0x44: // string16 / Long character string - { - // Long Strings must contains at least two bytes for the length - CHECK_MESSAGE_LENGTH(2); - uint16_t length = Encoding::LittleEndian::Read16(message); - ChipLogProgress(Zcl, " length: 0x%02x", length); - - // When the length is set to 0xFFFF, it represents a non-value. In this case the data field is zero length. - if (length == 0xFFFF) - { - length = 0; - } - - CHECK_MESSAGE_LENGTH(length); - if (attributeType == 0x43) - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - else - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - break; - } - - case 0x08: // data8 / 8-bit data - case 0x18: // map8 / 8-bit bitmap - case 0x20: // uint8 / Unsigned 8-bit integer - case 0x30: // enum8 / 8-bit enumeration - { - CHECK_MESSAGE_LENGTH(1); - uint8_t value = Encoding::Read8(message); - ChipLogProgress(Zcl, " value: 0x%02x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x09: // data16 / 16-bit data - case 0x19: // map16 / 16-bit bitmap - case 0x21: // uint16 / Unsigned 16-bit integer - case 0x31: // enum16 / 16-bit enumeration - case 0xE8: // clusterId / Cluster ID - case 0xE9: // attribId / Attribute ID - case 0xEA: // bacOID / BACnet OID - case 0xF1: // key128 / 128-bit security key - case 0xFF: // unk / Unknown - { - CHECK_MESSAGE_LENGTH(2); - uint16_t value = Encoding::LittleEndian::Read16(message); - ChipLogProgress(Zcl, " value: 0x%04x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x0B: // data32 / 32-bit data - case 0x1B: // map32 / 32-bit bitmap - case 0x23: // uint32 / Unsigned 32-bit integer - case 0xE1: // date / Date - case 0xE2: // UTC / UTCTime - { - CHECK_MESSAGE_LENGTH(4); - uint32_t value = Encoding::LittleEndian::Read32(message); - ChipLogProgress(Zcl, " value: 0x%08x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x0F: // data64 / 64-bit data - case 0x1F: // map64 / 64-bit bitmap - case 0x27: // uint64 / Unsigned 64-bit integer - case 0xF0: // EUI64 / IEEE address - { - CHECK_MESSAGE_LENGTH(8); - uint64_t value = Encoding::LittleEndian::Read64(message); - ChipLogProgress(Zcl, " value: 0x" ChipLogFormatX64, ChipLogValueX64(value)); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x10: // bool / Boolean - { - CHECK_MESSAGE_LENGTH(1); - uint8_t value = Encoding::Read8(message); - ChipLogProgress(Zcl, " value: %d", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x28: // int8 / Signed 8-bit integer - { - CHECK_MESSAGE_LENGTH(1); - int8_t value = CastToSigned(Encoding::Read8(message)); - ChipLogProgress(Zcl, " value: %" PRId8, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x29: // int16 / Signed 16-bit integer - { - CHECK_MESSAGE_LENGTH(2); - int16_t value = CastToSigned(Encoding::LittleEndian::Read16(message)); - ChipLogProgress(Zcl, " value: %" PRId16, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x2B: // int32 / Signed 32-bit integer - { - CHECK_MESSAGE_LENGTH(4); - int32_t value = CastToSigned(Encoding::LittleEndian::Read32(message)); - ChipLogProgress(Zcl, " value: %" PRId32, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x2F: // int64 / Signed 64-bit integer - { - CHECK_MESSAGE_LENGTH(8); - int64_t value = CastToSigned(Encoding::LittleEndian::Read64(message)); - ChipLogProgress(Zcl, " value: %" PRId64, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - } - } - - return true; -} diff --git a/zzz_generated/pump-controller-app/zap-generated/CHIPClusters.cpp b/zzz_generated/pump-controller-app/zap-generated/CHIPClusters.cpp index ae4250cbaaefc6..acc03904772d3d 100644 --- a/zzz_generated/pump-controller-app/zap-generated/CHIPClusters.cpp +++ b/zzz_generated/pump-controller-app/zap-generated/CHIPClusters.cpp @@ -67,8 +67,6 @@ constexpr uint8_t kFrameControlGlobalCommand = 0x00; // Pick source endpoint as 1 for now constexpr EndpointId kSourceEndpoint = 1; - -[[maybe_unused]] const uint8_t kReportingDirectionReported = 0x00; } // namespace using namespace app::Clusters; @@ -107,22 +105,19 @@ CHIP_ERROR FlowMeasurementCluster::ConfigureAttributeMeasuredValue(Callback::Can Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, int16_t change) { - COMMAND_HEADER("ReportFlowMeasurementMeasuredValue", FlowMeasurement::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(FlowMeasurement::Attributes::Ids::MeasuredValue) - .Put8(41) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = FlowMeasurement::Attributes::Ids::MeasuredValue; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR FlowMeasurementCluster::ReportAttributeMeasuredValue(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(FlowMeasurement::Attributes::Ids::MeasuredValue, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR FlowMeasurementCluster::ReadAttributeMinMeasuredValue(Callback::Cancelable * onSuccessCallback, @@ -544,22 +539,19 @@ CHIP_ERROR LevelControlCluster::ConfigureAttributeCurrentLevel(Callback::Cancela Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, uint8_t change) { - COMMAND_HEADER("ReportLevelControlCurrentLevel", LevelControl::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(LevelControl::Attributes::Ids::CurrentLevel) - .Put8(32) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put8(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = LevelControl::Attributes::Ids::CurrentLevel; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR LevelControlCluster::ReportAttributeCurrentLevel(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(LevelControl::Attributes::Ids::CurrentLevel, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR LevelControlCluster::ReadAttributeClusterRevision(Callback::Cancelable * onSuccessCallback, @@ -746,22 +738,19 @@ CHIP_ERROR PressureMeasurementCluster::ConfigureAttributeMeasuredValue(Callback: Callback::Cancelable * onFailureCallback, uint16_t minInterval, uint16_t maxInterval, int16_t change) { - COMMAND_HEADER("ReportPressureMeasurementMeasuredValue", PressureMeasurement::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(PressureMeasurement::Attributes::Ids::MeasuredValue) - .Put8(41) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = PressureMeasurement::Attributes::Ids::MeasuredValue; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR PressureMeasurementCluster::ReportAttributeMeasuredValue(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(PressureMeasurement::Attributes::Ids::MeasuredValue, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR PressureMeasurementCluster::ReadAttributeMinMeasuredValue(Callback::Cancelable * onSuccessCallback, @@ -887,22 +876,19 @@ CHIP_ERROR PumpConfigurationAndControlCluster::ConfigureAttributeCapacity(Callba uint16_t minInterval, uint16_t maxInterval, int16_t change) { - COMMAND_HEADER("ReportPumpConfigurationAndControlCapacity", PumpConfigurationAndControl::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(PumpConfigurationAndControl::Attributes::Ids::Capacity) - .Put8(41) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = PumpConfigurationAndControl::Attributes::Ids::Capacity; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR PumpConfigurationAndControlCluster::ReportAttributeCapacity(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0013, onReportCallback); + return RequestAttributeReporting(PumpConfigurationAndControl::Attributes::Ids::Capacity, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR PumpConfigurationAndControlCluster::ReadAttributeOperationMode(Callback::Cancelable * onSuccessCallback, @@ -973,22 +959,19 @@ CHIP_ERROR TemperatureMeasurementCluster::ConfigureAttributeMeasuredValue(Callba uint16_t minInterval, uint16_t maxInterval, int16_t change) { - COMMAND_HEADER("ReportTemperatureMeasurementMeasuredValue", TemperatureMeasurement::Id); - buf.Put8(kFrameControlGlobalCommand) - .Put8(seqNum) - .Put32(Globals::Commands::Ids::ConfigureReporting) - .Put8(kReportingDirectionReported) - .Put32(TemperatureMeasurement::Attributes::Ids::MeasuredValue) - .Put8(41) - .Put16(minInterval) - .Put16(maxInterval); - buf.Put16(static_cast(change)); - COMMAND_FOOTER(); + IgnoreUnusedVariable(change); + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = TemperatureMeasurement::Attributes::Ids::MeasuredValue; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendSubscribeAttributeRequest(attributePath, minInterval, maxInterval, onSuccessCallback, onFailureCallback); } CHIP_ERROR TemperatureMeasurementCluster::ReportAttributeMeasuredValue(Callback::Cancelable * onReportCallback) { - return RequestAttributeReporting(0x0000, onReportCallback); + return RequestAttributeReporting(TemperatureMeasurement::Attributes::Ids::MeasuredValue, onReportCallback, + BasicAttributeFilter); } CHIP_ERROR TemperatureMeasurementCluster::ReadAttributeMinMeasuredValue(Callback::Cancelable * onSuccessCallback, diff --git a/zzz_generated/tv-app/zap-generated/CHIPClientCallbacks.cpp b/zzz_generated/tv-app/zap-generated/CHIPClientCallbacks.cpp index 0f98252f959355..971247ed1da5d8 100644 --- a/zzz_generated/tv-app/zap-generated/CHIPClientCallbacks.cpp +++ b/zzz_generated/tv-app/zap-generated/CHIPClientCallbacks.cpp @@ -361,9 +361,12 @@ void GeneralCommissioningClusterBasicCommissioningInfoListListAttributeFilter(TL EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -393,9 +396,12 @@ void OperationalCredentialsClusterFabricsListListAttributeFilter(TLV::TLVReader EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -441,9 +447,12 @@ void OperationalCredentialsClusterTrustedRootCertificatesListAttributeFilter(TLV EmberAfStatus res = PrepareListFromTLV(tlvData, message, messageLen); if (res != EMBER_ZCL_STATUS_SUCCESS) { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onFailureCallback); - cb->mCall(cb->mContext, res); + if (onFailureCallback != nullptr) + { + Callback::Callback * cb = + Callback::Callback::FromCancelable(onFailureCallback); + cb->mCall(cb->mContext, res); + } return; } @@ -675,252 +684,3 @@ bool emberAfOperationalCredentialsClusterOpCSRResponseCallback(EndpointId endpoi cb->mCall(cb->mContext, NOCSRElements, AttestationSignature); return true; } - -bool emberAfReportAttributesCallback(ClusterId clusterId, uint8_t * message, uint16_t messageLen) -{ - ChipLogProgress(Zcl, "emberAfReportAttributeCallback:"); - ChipLogProgress(Zcl, " ClusterId: " ChipLogFormatMEI, ChipLogValueMEI(clusterId)); - - NodeId sourceId = emberAfCurrentCommand()->SourceNodeId(); - ChipLogProgress(Zcl, " Source NodeId: %" PRIu64, sourceId); - - EndpointId endpointId = emberAfCurrentCommand()->apsFrame->sourceEndpoint; - ChipLogProgress(Zcl, " Source EndpointId: 0x%04x", endpointId); - - // TODO onFailureCallback is just here because of the CHECK_MESSAGE_LENGTH macro. It needs to be removed. - Callback::Cancelable * onFailureCallback = nullptr; - - while (messageLen) - { - CHECK_MESSAGE_LENGTH(4); - AttributeId attributeId = Encoding::LittleEndian::Read32(message); // attribId - ChipLogProgress(Zcl, " attributeId: " ChipLogFormatMEI, ChipLogValueMEI(attributeId)); - - GET_REPORT_CALLBACK("emberAfReportAttributesCallback"); - - CHECK_MESSAGE_LENGTH(1); - uint8_t attributeType = Encoding::Read8(message); - ChipLogProgress(Zcl, " attributeType: 0x%02x", attributeType); - - switch (attributeType) - { - case 0x00: // nodata / No data - case 0x0A: // data24 / 24-bit data - case 0x0C: // data40 / 40-bit data - case 0x0D: // data48 / 48-bit data - case 0x0E: // data56 / 56-bit data - case 0x1A: // map24 / 24-bit bitmap - case 0x1C: // map40 / 40-bit bitmap - case 0x1D: // map48 / 48-bit bitmap - case 0x1E: // map56 / 56-bit bitmap - case 0x22: // uint24 / Unsigned 24-bit integer - case 0x24: // uint40 / Unsigned 40-bit integer - case 0x25: // uint48 / Unsigned 48-bit integer - case 0x26: // uint56 / Unsigned 56-bit integer - case 0x2A: // int24 / Signed 24-bit integer - case 0x2C: // int40 / Signed 40-bit integer - case 0x2D: // int48 / Signed 48-bit integer - case 0x2E: // int56 / Signed 56-bit integer - case 0x38: // semi / Semi-precision - case 0x39: // single / Single precision - case 0x3A: // double / Double precision - case 0x48: // array / Array - case 0x49: // struct / Structure - case 0x50: // set / Set - case 0x51: // bag / Bag - case 0xE0: // ToD / Time of day - { - ChipLogError(Zcl, "attributeType 0x%02x is not supported", attributeType); - return true; - } - - case 0x41: // octstr / Octet string - case 0x42: // string / Character string - { - // Short Strings must contains at least one byte for the length - CHECK_MESSAGE_LENGTH(1); - uint8_t length = Encoding::Read8(message); - ChipLogProgress(Zcl, " length: 0x%02x", length); - - // When the length is set to 0xFF, it represents a non-value. In this case the data field is zero length. - if (length == 0xFF) - { - length = 0; - } - - CHECK_MESSAGE_LENGTH(length); - if (attributeType == 0x41) - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - else - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - break; - } - - case 0x43: // octstr16 / Long octet string - case 0x44: // string16 / Long character string - { - // Long Strings must contains at least two bytes for the length - CHECK_MESSAGE_LENGTH(2); - uint16_t length = Encoding::LittleEndian::Read16(message); - ChipLogProgress(Zcl, " length: 0x%02x", length); - - // When the length is set to 0xFFFF, it represents a non-value. In this case the data field is zero length. - if (length == 0xFFFF) - { - length = 0; - } - - CHECK_MESSAGE_LENGTH(length); - if (attributeType == 0x43) - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - else - { - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, ByteSpan(message, length)); - } - break; - } - - case 0x08: // data8 / 8-bit data - case 0x18: // map8 / 8-bit bitmap - case 0x20: // uint8 / Unsigned 8-bit integer - case 0x30: // enum8 / 8-bit enumeration - { - CHECK_MESSAGE_LENGTH(1); - uint8_t value = Encoding::Read8(message); - ChipLogProgress(Zcl, " value: 0x%02x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x09: // data16 / 16-bit data - case 0x19: // map16 / 16-bit bitmap - case 0x21: // uint16 / Unsigned 16-bit integer - case 0x31: // enum16 / 16-bit enumeration - case 0xE8: // clusterId / Cluster ID - case 0xE9: // attribId / Attribute ID - case 0xEA: // bacOID / BACnet OID - case 0xF1: // key128 / 128-bit security key - case 0xFF: // unk / Unknown - { - CHECK_MESSAGE_LENGTH(2); - uint16_t value = Encoding::LittleEndian::Read16(message); - ChipLogProgress(Zcl, " value: 0x%04x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x0B: // data32 / 32-bit data - case 0x1B: // map32 / 32-bit bitmap - case 0x23: // uint32 / Unsigned 32-bit integer - case 0xE1: // date / Date - case 0xE2: // UTC / UTCTime - { - CHECK_MESSAGE_LENGTH(4); - uint32_t value = Encoding::LittleEndian::Read32(message); - ChipLogProgress(Zcl, " value: 0x%08x", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x0F: // data64 / 64-bit data - case 0x1F: // map64 / 64-bit bitmap - case 0x27: // uint64 / Unsigned 64-bit integer - case 0xF0: // EUI64 / IEEE address - { - CHECK_MESSAGE_LENGTH(8); - uint64_t value = Encoding::LittleEndian::Read64(message); - ChipLogProgress(Zcl, " value: 0x" ChipLogFormatX64, ChipLogValueX64(value)); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x10: // bool / Boolean - { - CHECK_MESSAGE_LENGTH(1); - uint8_t value = Encoding::Read8(message); - ChipLogProgress(Zcl, " value: %d", value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x28: // int8 / Signed 8-bit integer - { - CHECK_MESSAGE_LENGTH(1); - int8_t value = CastToSigned(Encoding::Read8(message)); - ChipLogProgress(Zcl, " value: %" PRId8, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x29: // int16 / Signed 16-bit integer - { - CHECK_MESSAGE_LENGTH(2); - int16_t value = CastToSigned(Encoding::LittleEndian::Read16(message)); - ChipLogProgress(Zcl, " value: %" PRId16, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x2B: // int32 / Signed 32-bit integer - { - CHECK_MESSAGE_LENGTH(4); - int32_t value = CastToSigned(Encoding::LittleEndian::Read32(message)); - ChipLogProgress(Zcl, " value: %" PRId32, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - - case 0x2F: // int64 / Signed 64-bit integer - { - CHECK_MESSAGE_LENGTH(8); - int64_t value = CastToSigned(Encoding::LittleEndian::Read64(message)); - ChipLogProgress(Zcl, " value: %" PRId64, value); - - Callback::Callback * cb = - Callback::Callback::FromCancelable(onReportCallback); - cb->mCall(cb->mContext, value); - break; - } - } - } - - return true; -} diff --git a/zzz_generated/tv-app/zap-generated/CHIPClusters.cpp b/zzz_generated/tv-app/zap-generated/CHIPClusters.cpp index 7cd10f89033f1b..a4757924ee49a0 100644 --- a/zzz_generated/tv-app/zap-generated/CHIPClusters.cpp +++ b/zzz_generated/tv-app/zap-generated/CHIPClusters.cpp @@ -67,8 +67,6 @@ constexpr uint8_t kFrameControlGlobalCommand = 0x00; // Pick source endpoint as 1 for now constexpr EndpointId kSourceEndpoint = 1; - -[[maybe_unused]] const uint8_t kReportingDirectionReported = 0x00; } // namespace using namespace app::Clusters;