Skip to content

Commit 6ee4e23

Browse files
wqx6restyled-commitsbzbarsky-appleandy31415
authored
data-model-provider: Add an interface to report attribute changes which are not caused by WriteAttribute. (#36364)
* data-model-provider: Add an interface to report attribute changes which are not caused by WriteAttribute * review changes * Restyled by clang-format * Update src/app/data-model-provider/Provider.h Co-authored-by: Boris Zbarsky <bzbarsky@apple.com> * Update src/app/data-model-provider/Provider.h Co-authored-by: Boris Zbarsky <bzbarsky@apple.com> * review changes * remove the deprecated mark to fix CI issue * review changes * Restyled by clang-format * fix java build * move the report change callback to metadatatree * fix CI build --------- Co-authored-by: Restyled.io <commits@restyled.io> Co-authored-by: Boris Zbarsky <bzbarsky@apple.com> Co-authored-by: Andrei Litvin <andy314@gmail.com>
1 parent b0fd385 commit 6ee4e23

File tree

8 files changed

+54
-4
lines changed

8 files changed

+54
-4
lines changed

src/app/codegen-data-model-provider/CodegenDataModelProvider.h

+2
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ class CodegenDataModelProvider : public chip::app::DataModel::Provider
179179
ConcreteCommandPath FirstGeneratedCommand(const ConcreteClusterPath & cluster) override;
180180
ConcreteCommandPath NextGeneratedCommand(const ConcreteCommandPath & before) override;
181181

182+
void Temporary_ReportAttributeChanged(const AttributePathParams & path) override;
183+
182184
private:
183185
// Iteration is often done in a tight loop going through all values.
184186
// To avoid N^2 iterations, cache a hint of where something is positioned

src/app/codegen-data-model-provider/CodegenDataModelProvider_Write.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -261,5 +261,21 @@ DataModel::ActionReturnStatus CodegenDataModelProvider::WriteAttribute(const Dat
261261
return CHIP_NO_ERROR;
262262
}
263263

264+
void CodegenDataModelProvider::Temporary_ReportAttributeChanged(const AttributePathParams & path)
265+
{
266+
ContextAttributesChangeListener change_listener(CurrentContext());
267+
if (path.mClusterId != kInvalidClusterId)
268+
{
269+
emberAfAttributeChanged(path.mEndpointId, path.mClusterId, path.mAttributeId, &change_listener);
270+
}
271+
else
272+
{
273+
// When the path has wildcard cluster Id, call the emberAfEndpointChanged to mark attributes on the given endpoint
274+
// as having changing, but do NOT increase/alter any cluster data versions, as this happens when a bridged endpoint is
275+
// added or removed from a bridge and the cluster data is not changed during the process.
276+
emberAfEndpointChanged(path.mEndpointId, &change_listener);
277+
}
278+
}
279+
264280
} // namespace app
265281
} // namespace chip

src/app/data-model-provider/MetadataTypes.h

+19
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <access/Privilege.h>
2323
#include <app-common/zap-generated/cluster-objects.h>
24+
#include <app/AttributePathParams.h>
2425
#include <app/ConcreteAttributePath.h>
2526
#include <app/ConcreteClusterPath.h>
2627
#include <app/ConcreteCommandPath.h>
@@ -220,6 +221,24 @@ class ProviderMetadataTree
220221
// returned as responses.
221222
virtual ConcreteCommandPath FirstGeneratedCommand(const ConcreteClusterPath & cluster) = 0;
222223
virtual ConcreteCommandPath NextGeneratedCommand(const ConcreteCommandPath & before) = 0;
224+
225+
/// Workaround function to report attribute change.
226+
///
227+
/// When this is invoked, the caller is expected to increment the cluster data version, and the attribute path
228+
/// should be marked as `dirty` by the data model provider listener so that the reporter can notify the subscriber
229+
/// of attribute changes.
230+
/// This function should be invoked when attribute managed by attribute access interface is modified but not
231+
/// through an actual Write interaction.
232+
/// For example, if the LastNetworkingStatus attribute changes because the NetworkCommissioning driver detects a
233+
/// network connection status change and calls SetLastNetworkingStatusValue(). The data model provider can recognize
234+
/// this change by invoking this function at the point of change.
235+
///
236+
/// This is a workaround function as we cannot notify the attribute change to the data model provider. The provider
237+
/// should own its data and versions.
238+
///
239+
/// TODO: We should remove this function when the AttributeAccessInterface/CommandHandlerInterface is able to report
240+
/// the attribute changes.
241+
virtual void Temporary_ReportAttributeChanged(const AttributePathParams & path) = 0;
223242
};
224243

225244
} // namespace DataModel

src/app/dynamic_server/DynamicDispatcher.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@ void emberAfAttributeChanged(EndpointId endpoint, ClusterId clusterId, Attribute
304304
listener->MarkDirty(AttributePathParams(endpoint, clusterId, attributeId));
305305
}
306306

307+
void emberAfEndpointChanged(EndpointId endpoint, AttributesChangedListener * listener)
308+
{
309+
listener->MarkDirty(AttributePathParams(endpoint));
310+
}
311+
307312
DataVersion * emberAfDataVersionStorage(const ConcreteClusterPath & aConcreteClusterPath)
308313
{
309314
return &gMockDataVersion;

src/app/reporting/reporting.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ void MatterReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clust
3030
// applications notifying about changes from their end.
3131
assertChipStackLockedByCurrentThread();
3232

33-
emberAfAttributeChanged(endpoint, clusterId, attributeId, emberAfGlobalInteractionModelAttributesChangedListener());
33+
InteractionModelEngine::GetInstance()->GetDataModelProvider()->Temporary_ReportAttributeChanged(
34+
AttributePathParams(endpoint, clusterId, attributeId));
3435
}
3536

3637
void MatterReportingAttributeChangeCallback(const ConcreteAttributePath & aPath)
@@ -39,8 +40,8 @@ void MatterReportingAttributeChangeCallback(const ConcreteAttributePath & aPath)
3940
// applications notifying about changes from their end.
4041
assertChipStackLockedByCurrentThread();
4142

42-
emberAfAttributeChanged(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId,
43-
emberAfGlobalInteractionModelAttributesChangedListener());
43+
InteractionModelEngine::GetInstance()->GetDataModelProvider()->Temporary_ReportAttributeChanged(
44+
AttributePathParams(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId));
4445
}
4546

4647
void MatterReportingAttributeChangeCallback(EndpointId endpoint)
@@ -49,5 +50,5 @@ void MatterReportingAttributeChangeCallback(EndpointId endpoint)
4950
// applications notifying about changes from their end.
5051
assertChipStackLockedByCurrentThread();
5152

52-
emberAfEndpointChanged(endpoint, emberAfGlobalInteractionModelAttributesChangedListener());
53+
InteractionModelEngine::GetInstance()->GetDataModelProvider()->Temporary_ReportAttributeChanged(AttributePathParams(endpoint));
5354
}

src/app/tests/test-interaction-model-api.h

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ class TestImCustomDataModel : public DataModel::Provider
131131
std::optional<DataModel::CommandInfo> GetAcceptedCommandInfo(const ConcreteCommandPath & path) override;
132132
ConcreteCommandPath FirstGeneratedCommand(const ConcreteClusterPath & cluster) override;
133133
ConcreteCommandPath NextGeneratedCommand(const ConcreteCommandPath & before) override;
134+
void Temporary_ReportAttributeChanged(const AttributePathParams & path) override {}
134135
};
135136

136137
} // namespace app

src/app/util/mock/attribute-storage.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,11 @@ void emberAfAttributeChanged(EndpointId endpoint, ClusterId clusterId, Attribute
376376
listener->MarkDirty(AttributePathParams(endpoint, clusterId, attributeId));
377377
}
378378

379+
void emberAfEndpointChanged(EndpointId endpoint, AttributesChangedListener * listener)
380+
{
381+
listener->MarkDirty(AttributePathParams(endpoint));
382+
}
383+
379384
unsigned emberAfMetadataStructureGeneration()
380385
{
381386
return metadataStructureGeneration;

src/controller/tests/data_model/DataModelFixtures.h

+1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ class CustomDataModel : public DataModel::Provider
143143
std::optional<DataModel::CommandInfo> GetAcceptedCommandInfo(const ConcreteCommandPath & path) override;
144144
ConcreteCommandPath FirstGeneratedCommand(const ConcreteClusterPath & cluster) override;
145145
ConcreteCommandPath NextGeneratedCommand(const ConcreteCommandPath & before) override;
146+
void Temporary_ReportAttributeChanged(const AttributePathParams & path) override {}
146147
};
147148

148149
} // namespace DataModelTests

0 commit comments

Comments
 (0)