16
16
*/
17
17
#include < app/util/attribute-table.h>
18
18
19
+ #include < app-common/zap-generated/attribute-type.h>
19
20
#include < app/util/attribute-storage.h>
20
21
#include < app/util/config.h>
21
22
#include < app/util/generic-callbacks.h>
28
29
using chip::Protocols::InteractionModel::Status;
29
30
30
31
using namespace chip ;
32
+ using namespace chip ::app;
31
33
32
34
Status emAfWriteAttributeExternal (EndpointId endpoint, ClusterId cluster, AttributeId attributeID, uint8_t * dataPtr,
33
35
EmberAfAttributeType dataType)
@@ -36,9 +38,9 @@ Status emAfWriteAttributeExternal(EndpointId endpoint, ClusterId cluster, Attrib
36
38
}
37
39
38
40
Status emberAfWriteAttribute (EndpointId endpoint, ClusterId cluster, AttributeId attributeID, uint8_t * dataPtr,
39
- EmberAfAttributeType dataType)
41
+ EmberAfAttributeType dataType, MarkAttributeDirty markDirty )
40
42
{
41
- return emAfWriteAttribute (endpoint, cluster, attributeID, dataPtr, dataType, true /* override read-only */ );
43
+ return emAfWriteAttribute (endpoint, cluster, attributeID, dataPtr, dataType, true /* override read-only */ , markDirty );
42
44
}
43
45
44
46
// ------------------------------------------------------------------------------
@@ -101,7 +103,7 @@ static bool IsNullValue(const uint8_t * data, uint16_t dataLen, bool isAttribute
101
103
}
102
104
103
105
Status emAfWriteAttribute (EndpointId endpoint, ClusterId cluster, AttributeId attributeID, uint8_t * data,
104
- EmberAfAttributeType dataType, bool overrideReadOnlyAndDataType)
106
+ EmberAfAttributeType dataType, bool overrideReadOnlyAndDataType, MarkAttributeDirty markDirty )
105
107
{
106
108
const EmberAfAttributeMetadata * metadata = nullptr ;
107
109
EmberAfAttributeSearchRecord record;
@@ -179,6 +181,35 @@ Status emAfWriteAttribute(EndpointId endpoint, ClusterId cluster, AttributeId at
179
181
}
180
182
}
181
183
184
+ // Check whether anything is actually changing, before we do any work here.
185
+ size_t valueSize = AttributeTypeSize (dataType);
186
+
187
+ constexpr size_t maxValueSize = 16 ; // ipv6adr
188
+ if (valueSize > maxValueSize)
189
+ {
190
+ // Very much unexpected
191
+ ChipLogError (Zcl, " Attribute type %d has too-large size %u" , dataType, static_cast <unsigned >(valueSize));
192
+ return Status::ConstraintError;
193
+ }
194
+
195
+ // valueSize will be 0 when we have no size information for dataType.
196
+ // In that case, we can't usefully read the current value, since we
197
+ // don't know how big it is.
198
+ if (valueSize != 0 )
199
+ {
200
+ uint8_t oldValueBuffer[maxValueSize];
201
+ // Cast to uint16_t is safe, because we checked valueSize <= maxValueSize above.
202
+ if (emberAfReadAttribute (endpoint, cluster, attributeID, oldValueBuffer, static_cast <uint16_t >(valueSize)) ==
203
+ Status::Success)
204
+ {
205
+ if (memcmp (data, oldValueBuffer, valueSize) == 0 )
206
+ {
207
+ // Value has not changed. Just do nothing.
208
+ return Status::Success;
209
+ }
210
+ }
211
+ }
212
+
182
213
const app::ConcreteAttributePath attributePath (endpoint, cluster, attributeID);
183
214
184
215
// Pre write attribute callback for all attribute changes,
@@ -221,7 +252,10 @@ Status emAfWriteAttribute(EndpointId endpoint, ClusterId cluster, AttributeId at
221
252
// The callee will weed out attributes that do not need to be stored.
222
253
emAfSaveAttributeToStorageIfNeeded (data, endpoint, cluster, metadata);
223
254
224
- MatterReportingAttributeChangeCallback (endpoint, cluster, attributeID);
255
+ if (markDirty != MarkAttributeDirty::No)
256
+ {
257
+ MatterReportingAttributeChangeCallback (endpoint, cluster, attributeID);
258
+ }
225
259
226
260
// Post write attribute callback for all attributes changes, regardless
227
261
// of cluster.
0 commit comments