@@ -253,15 +253,23 @@ - (oneway void)deviceConfigurationChanged:(NSNumber *)nodeID
253
253
}];
254
254
}
255
255
256
- static const auto * requiredInternalStateKeys = @[ kMTRDeviceInternalPropertyDeviceState , kMTRDeviceInternalPropertyLastSubscriptionAttemptWait ];
257
- static const auto * optionalInternalStateKeys = @[ kMTRDeviceInternalPropertyKeyVendorID , kMTRDeviceInternalPropertyKeyProductID , kMTRDeviceInternalPropertyNetworkFeatures , kMTRDeviceInternalPropertyMostRecentReportTime , kMTRDeviceInternalPropertyLastSubscriptionFailureTime ];
258
-
259
- - (BOOL )_internalState: (NSDictionary *)dictionary hasValidValuesForKeys: (const NSArray <NSString *> *)keys valueRequired: (BOOL )required
256
+ static const auto * requiredInternalStateKeys = @{
257
+ kMTRDeviceInternalPropertyDeviceState : NSNumber .class ,
258
+ kMTRDeviceInternalPropertyLastSubscriptionAttemptWait : NSNumber .class ,
259
+ };
260
+
261
+ static const auto * optionalInternalStateKeys = @{
262
+ kMTRDeviceInternalPropertyKeyVendorID : NSNumber .class ,
263
+ kMTRDeviceInternalPropertyKeyProductID : NSNumber .class ,
264
+ kMTRDeviceInternalPropertyNetworkFeatures : NSNumber .class ,
265
+ kMTRDeviceInternalPropertyMostRecentReportTime : NSDate .class ,
266
+ kMTRDeviceInternalPropertyLastSubscriptionFailureTime : NSDate .class ,
267
+ };
268
+
269
+ - (BOOL )_ensureValidValuesForKeys: (const NSDictionary <NSString *, Class > *)keys inInternalState: (NSMutableDictionary *)internalState valueRequired: (BOOL )required
260
270
{
261
- // At one point, all keys were NSNumber valued; now there are also NSDates.
262
- // TODO: Create a mapping between keys and their expected types and use that in the type check below.
263
271
for (NSString * key in keys) {
264
- id value = dictionary [key];
272
+ id value = internalState [key];
265
273
if (!value) {
266
274
if (required) {
267
275
MTR_LOG_ERROR (" %@ device:internalStateUpdated: handed state with no value for \" %@\" : %@" , self, key, value);
@@ -270,10 +278,17 @@ - (BOOL)_internalState:(NSDictionary *)dictionary hasValidValuesForKeys:(const N
270
278
271
279
continue ;
272
280
}
273
- if (!MTR_SAFE_CAST ( value, NSNumber ) && ! MTR_SAFE_CAST (value, NSDate ) ) {
281
+ if (![ value isKindOfClass: keys[key]] ) {
274
282
MTR_LOG_ERROR (" %@ device:internalStateUpdated: handed state with invalid value of type %@ for \" %@\" : %@" , self,
275
283
NSStringFromClass ([value class ]), key, value);
276
- return NO ;
284
+ if (required) {
285
+ return NO ;
286
+ }
287
+
288
+ // If an optional value is invalid, just drop it and press on with
289
+ // the other parts of the state, so we don't break those pieces
290
+ // just because something optional has gone awry.
291
+ [internalState removeObjectForKey: key];
277
292
}
278
293
}
279
294
@@ -293,13 +308,21 @@ - (oneway void)device:(NSNumber *)nodeID internalStateUpdated:(NSDictionary *)di
293
308
return ;
294
309
}
295
310
311
+ [self _updateInternalState: [dictionary mutableCopy ]];
312
+ }
313
+
314
+ - (void )_updateInternalState: (NSMutableDictionary *)newState
315
+ {
316
+ VerifyOrReturn ([self _ensureValidValuesForKeys: requiredInternalStateKeys inInternalState: newState valueRequired: YES ]);
317
+ VerifyOrReturn ([self _ensureValidValuesForKeys: optionalInternalStateKeys inInternalState: newState valueRequired: NO ]);
318
+
296
319
NSNumber * oldStateNumber = MTR_SAFE_CAST (self._internalState [kMTRDeviceInternalPropertyDeviceState ], NSNumber );
297
- NSNumber * newStateNumber = MTR_SAFE_CAST (dictionary [kMTRDeviceInternalPropertyDeviceState ], NSNumber );
320
+ NSNumber * newStateNumber = MTR_SAFE_CAST (newState [kMTRDeviceInternalPropertyDeviceState ], NSNumber );
298
321
299
- VerifyOrReturn ([ self _internalState: dictionary hasValidValuesForKeys: requiredInternalStateKeys valueRequired: YES ] );
300
- VerifyOrReturn ([ self _internalState: dictionary hasValidValuesForKeys: optionalInternalStateKeys valueRequired: NO ] );
322
+ NSNumber * oldPrimedState = MTR_SAFE_CAST (self. _internalState [ kMTRDeviceInternalPropertyDeviceCachePrimed ], NSNumber );
323
+ NSNumber * newPrimedState = MTR_SAFE_CAST (newState[ kMTRDeviceInternalPropertyDeviceCachePrimed ], NSNumber );
301
324
302
- [self _setInternalState: dictionary ];
325
+ [self _setInternalState: newState ];
303
326
304
327
if (!MTREqualObjects (oldStateNumber, newStateNumber)) {
305
328
MTRDeviceState state = self.state ;
@@ -308,9 +331,6 @@ - (oneway void)device:(NSNumber *)nodeID internalStateUpdated:(NSDictionary *)di
308
331
}];
309
332
}
310
333
311
- NSNumber * oldPrimedState = MTR_SAFE_CAST (self._internalState [kMTRDeviceInternalPropertyDeviceCachePrimed ], NSNumber );
312
- NSNumber * newPrimedState = MTR_SAFE_CAST (dictionary[kMTRDeviceInternalPropertyDeviceCachePrimed ], NSNumber );
313
-
314
334
if (!MTREqualObjects (oldPrimedState, newPrimedState)) {
315
335
[self _lockAndCallDelegatesWithBlock: ^(id <MTRDeviceDelegate> delegate) {
316
336
if ([delegate respondsToSelector: @selector (deviceCachePrimed: )]) {
0 commit comments