diff --git a/src/darwin/Framework/CHIP/MTRDevice.h b/src/darwin/Framework/CHIP/MTRDevice.h index 52399e7fd9f078..0dc1a1097ef0e7 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.h +++ b/src/darwin/Framework/CHIP/MTRDevice.h @@ -240,6 +240,90 @@ typedef NS_ENUM(NSUInteger, MTRDeviceState) { completion:(MTRDeviceOpenCommissioningWindowHandler)completion MTR_AVAILABLE(ios(17.0), macos(14.0), watchos(10.0), tvos(17.0)); +/** + * + * This set of functions allows clients to store metadata for either an entire device or for a specific endpoint. + * + * Notes: + * • Client data will be removed automatically when devices are deleted from the fabric + * • Supported client data object types are currently only: + * NSData, NSString, NSArray, NSDictionary, NSNumber + */ + +/** + * + * List of all client data types supported + * + */ +- (NSArray *)supportedClientDataClasses MTR_NEWLY_AVAILABLE; + +/** + * + * List of all client data keys stored + * + */ +- (NSArray * _Nullable)clientDataKeys MTR_NEWLY_AVAILABLE; + +/** + * + * Retrieve client metadata for a key, returns nil if no value is set + * + * @param key NSString * for the key to store the value as + */ +- (id _Nullable)clientDataForKey:(NSString *)key MTR_NEWLY_AVAILABLE; + +/** + * + * Set client metadata for a key. The value must conform to NSSecureCoding + * + * @param key NSString * for the key to store the value as + * @param value id for the value to store + */ +- (void)setClientDataForKey:(NSString *)key value:(id)value MTR_NEWLY_AVAILABLE; + +/** + * + * Remove client metadata for a key. + * + * @param key NSString * for the key to store the value as + */ +- (void)removeClientDataForKey:(NSString *)key MTR_NEWLY_AVAILABLE; + +/** + * + * List of all client data keys stored + * + */ +- (NSArray * _Nullable)clientDataKeysForEndpointID:(NSNumber *)endpointID MTR_NEWLY_AVAILABLE; + +/** + * + * Retrieve client metadata for a key, returns nil if no value is set + * + * @param key NSString * for the key to store the value as + * @param endpointID NSNumber * for the endpoint to associate the metadata with + */ +- (id _Nullable)clientDataForKey:(NSString *)key endpointID:(NSNumber *)endpointID MTR_NEWLY_AVAILABLE; + +/** + * + * Set client metadata for a key. The value must conform to NSSecureCoding. + * + * @param key NSString * for the key to store the value as. + * @param endpointID NSNumber * for the endpoint to associate the metadata with + * @param value id for the value to store + */ +- (void)setClientDataForKey:(NSString *)key endpointID:(NSNumber *)endpointID value:(id)value MTR_NEWLY_AVAILABLE; + +/** + * + * Remove client metadata for a key. + * + * @param key NSString * for the key to store the value as + * @param endpointID NSNumber * for the endpoint to associate the metadata with + */ +- (void)removeClientDataForKey:(NSString *)key endpointID:(NSNumber *)endpointID MTR_NEWLY_AVAILABLE; + @end @protocol MTRDeviceDelegate diff --git a/src/darwin/Framework/CHIP/MTRDevice.mm b/src/darwin/Framework/CHIP/MTRDevice.mm index 1ce1ff183457fc..116f70f5bec235 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.mm +++ b/src/darwin/Framework/CHIP/MTRDevice.mm @@ -190,6 +190,8 @@ @interface MTRDevice () @property (nonatomic) NSDate * estimatedStartTimeFromGeneralDiagnosticsUpTime; +@property (nonatomic) NSMutableDictionary * temporaryMetaDataCache; + /** * If currentReadClient is non-null, that means that we successfully * called SendAutoResubscribeRequest on the ReadClient and have not yet gotten @@ -1725,6 +1727,86 @@ - (MTRBaseDevice *)newBaseDevice return [MTRBaseDevice deviceWithNodeID:self.nodeID controller:self.deviceController]; } +// Client Metadata Storage + +- (NSArray *)supportedClientDataClasses +{ + return @[ [NSData class], [NSString class], [NSNumber class], [NSDictionary class], [NSArray class] ]; +} + +- (NSArray * _Nullable)clientDataKeys +{ + return [self.temporaryMetaDataCache allKeys]; +} + +- (id _Nullable)clientDataForKey:(NSString *)key +{ + if (key == nil) + return nil; + + return [self.temporaryMetaDataCache objectForKey:[NSString stringWithFormat:@"%@:-1", key]]; +} + +- (void)setClientDataForKey:(NSString *)key value:(id)value +{ + // TODO: Check supported data types, and also if they conform to NSSecureCoding, when we store these + // TODO: Need to add a delegate method, so when this value changes we call back to the client + + if (key == nil || value == nil) + return; + + if (self.temporaryMetaDataCache == nil) { + self.temporaryMetaDataCache = [NSMutableDictionary dictionary]; + } + + [self.temporaryMetaDataCache setObject:value forKey:[NSString stringWithFormat:@"%@:-1", key]]; +} + +- (void)removeClientDataForKey:(NSString *)key +{ + if (key == nil) + return; + + [self.temporaryMetaDataCache removeObjectForKey:[NSString stringWithFormat:@"%@:-1", key]]; +} + +- (NSArray * _Nullable)clientDataKeysForEndpointID:(NSNumber *)endpointID +{ + if (endpointID == nil) + return nil; + // TODO: When hooked up to storage, enumerate this better + + return [self.temporaryMetaDataCache allKeys]; +} + +- (id _Nullable)clientDataForKey:(NSString *)key endpointID:(NSNumber *)endpointID +{ + if (key == nil || endpointID == nil) + return nil; + + return [self.temporaryMetaDataCache objectForKey:[NSString stringWithFormat:@"%@:%@", key, endpointID]]; +} + +- (void)setClientDataForKey:(NSString *)key endpointID:(NSNumber *)endpointID value:(id)value +{ + if (key == nil || value == nil || endpointID == nil) + return; + + if (self.temporaryMetaDataCache == nil) { + self.temporaryMetaDataCache = [NSMutableDictionary dictionary]; + } + + [self.temporaryMetaDataCache setObject:value forKey:[NSString stringWithFormat:@"%@:%@", key, endpointID]]; +} + +- (void)removeClientDataForKey:(NSString *)key endpointID:(NSNumber *)endpointID +{ + if (key == nil || endpointID == nil) + return; + + [self.temporaryMetaDataCache removeObjectForKey:[NSString stringWithFormat:@"%@:%@", key, endpointID]]; +} + @end @implementation MTRDevice (Deprecated)