@@ -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,9 +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 )) {
274
- MTR_LOG_ERROR (" %@ device:internalStateUpdated: handed state with invalid value for \" %@\" : %@" , self, key, value);
275
- return NO ;
281
+ if (![value isKindOfClass: keys[key]]) {
282
+ MTR_LOG_ERROR (" %@ device:internalStateUpdated: handed state with invalid value of type %@ for \" %@\" : %@" , self,
283
+ NSStringFromClass ([value class ]), key, value);
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];
276
292
}
277
293
}
278
294
@@ -292,13 +308,21 @@ - (oneway void)device:(NSNumber *)nodeID internalStateUpdated:(NSDictionary *)di
292
308
return ;
293
309
}
294
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
+
295
319
NSNumber * oldStateNumber = MTR_SAFE_CAST (self._internalState [kMTRDeviceInternalPropertyDeviceState ], NSNumber );
296
- NSNumber * newStateNumber = MTR_SAFE_CAST (dictionary [kMTRDeviceInternalPropertyDeviceState ], NSNumber );
320
+ NSNumber * newStateNumber = MTR_SAFE_CAST (newState [kMTRDeviceInternalPropertyDeviceState ], NSNumber );
297
321
298
- VerifyOrReturn ([ self _internalState: dictionary hasValidValuesForKeys: requiredInternalStateKeys valueRequired: YES ] );
299
- 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 );
300
324
301
- [self _setInternalState: dictionary ];
325
+ [self _setInternalState: newState ];
302
326
303
327
if (!MTREqualObjects (oldStateNumber, newStateNumber)) {
304
328
MTRDeviceState state = self.state ;
@@ -307,9 +331,6 @@ - (oneway void)device:(NSNumber *)nodeID internalStateUpdated:(NSDictionary *)di
307
331
}];
308
332
}
309
333
310
- NSNumber * oldPrimedState = MTR_SAFE_CAST (self._internalState [kMTRDeviceInternalPropertyDeviceCachePrimed ], NSNumber );
311
- NSNumber * newPrimedState = MTR_SAFE_CAST (dictionary[kMTRDeviceInternalPropertyDeviceCachePrimed ], NSNumber );
312
-
313
334
if (!MTREqualObjects (oldPrimedState, newPrimedState)) {
314
335
[self _lockAndCallDelegatesWithBlock: ^(id <MTRDeviceDelegate> delegate) {
315
336
if ([delegate respondsToSelector: @selector (deviceCachePrimed: )]) {
0 commit comments