@@ -102,6 +102,55 @@ static bool IsNullValue(const uint8_t * data, uint16_t dataLen, bool isAttribute
102
102
return false ;
103
103
}
104
104
105
+ namespace {
106
+ /* *
107
+ * Helper function to determine whether the attribute value for the given
108
+ * attribute is changing. On success, the isChanging outparam will be set to
109
+ * whether the value is changing.
110
+ */
111
+ Status AttributeValueIsChanging (EndpointId endpoint, ClusterId cluster, AttributeId attributeID, uint8_t * newValueData,
112
+ EmberAfAttributeType dataType, bool * isChanging)
113
+ {
114
+ size_t valueSize = AttributeTypeSize (dataType);
115
+
116
+ constexpr size_t maxValueSize = 16 ; // ipv6adr
117
+ if (valueSize > maxValueSize)
118
+ {
119
+ // Very much unexpected
120
+ ChipLogError (Zcl, " Attribute type %d has too-large size %u" , dataType, static_cast <unsigned >(valueSize));
121
+ return Status::ConstraintError;
122
+ }
123
+
124
+ // valueSize will be 0 when we have no size information for dataType.
125
+ // In that case, we can't usefully read the current value, since we
126
+ // don't know how big it is.
127
+ if (valueSize == 0 )
128
+ {
129
+ // To be safe, claim changing.
130
+ *isChanging = true ;
131
+ return Status::Success;
132
+ }
133
+
134
+ uint8_t oldValueBuffer[maxValueSize];
135
+ // Cast to uint16_t is safe, because we checked valueSize <= maxValueSize above.
136
+ if (emberAfReadAttribute (endpoint, cluster, attributeID, oldValueBuffer, static_cast <uint16_t >(valueSize)) == Status::Success)
137
+ {
138
+ if (memcmp (newValueData, oldValueBuffer, valueSize) == 0 )
139
+ {
140
+ // Value has not changed.
141
+ *isChanging = false ;
142
+ return Status::Success;
143
+ }
144
+ }
145
+
146
+ // We failed to read the old value, or the value is changing. Either way,
147
+ // flag the value as changing to be safe.
148
+ *isChanging = true ;
149
+ return Status::Success;
150
+ }
151
+
152
+ } // anonymous namespace
153
+
105
154
Status emAfWriteAttribute (EndpointId endpoint, ClusterId cluster, AttributeId attributeID, uint8_t * data,
106
155
EmberAfAttributeType dataType, bool overrideReadOnlyAndDataType, MarkAttributeDirty markDirty)
107
156
{
@@ -182,40 +231,24 @@ Status emAfWriteAttribute(EndpointId endpoint, ClusterId cluster, AttributeId at
182
231
}
183
232
184
233
// 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)
234
+ bool valueChanging;
235
+ Status imStatus = AttributeValueIsChanging (endpoint, cluster, attributeID, data, dataType, &valueChanging);
236
+ if (imStatus != Status::Success)
189
237
{
190
- // Very much unexpected
191
- ChipLogError (Zcl, " Attribute type %d has too-large size %u" , dataType, static_cast <unsigned >(valueSize));
192
- return Status::ConstraintError;
238
+ return imStatus;
193
239
}
194
240
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 )
241
+ if (!valueChanging)
199
242
{
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
- }
243
+ // Just do nothing.
244
+ return Status::Success;
211
245
}
212
246
213
247
const app::ConcreteAttributePath attributePath (endpoint, cluster, attributeID);
214
248
215
249
// Pre write attribute callback for all attribute changes,
216
250
// regardless of cluster.
217
- Protocols::InteractionModel::Status imStatus =
218
- MatterPreAttributeChangeCallback (attributePath, dataType, emberAfAttributeSize (metadata), data);
251
+ imStatus = MatterPreAttributeChangeCallback (attributePath, dataType, emberAfAttributeSize (metadata), data);
219
252
if (imStatus != Protocols::InteractionModel::Status::Success)
220
253
{
221
254
return imStatus;
@@ -252,7 +285,7 @@ Status emAfWriteAttribute(EndpointId endpoint, ClusterId cluster, AttributeId at
252
285
// The callee will weed out attributes that do not need to be stored.
253
286
emAfSaveAttributeToStorageIfNeeded (data, endpoint, cluster, metadata);
254
287
255
- if (markDirty != MarkAttributeDirty::No )
288
+ if (markDirty != MarkAttributeDirty::kNo )
256
289
{
257
290
MatterReportingAttributeChangeCallback (endpoint, cluster, attributeID);
258
291
}
0 commit comments