@@ -2963,6 +2963,79 @@ - (void)writeAttributeWithEndpointID:(NSNumber *)endpointID
2963
2963
[_asyncWorkQueue enqueueWorkItem:workItem descriptionWithFormat:@"write %@ 0x%llx 0x%llx", endpointID, clusterID.unsignedLongLongValue, attributeID.unsignedLongLongValue];
2964
2964
}
2965
2965
2966
+ - (NSArray<NSDictionary<NSString *, id> *> *)readAttributePaths:(NSArray<MTRAttributeRequestPath *> *)attributePaths
2967
+ {
2968
+ // Determine the set of what the spec calls "existent paths" that correspond
2969
+ // to the request paths. Building the whole set in-memory is OK, because
2970
+ // we're going to need all those paths for our return value anyway.
2971
+ NSMutableSet<MTRAttributePath *> * existentPaths = [[NSMutableSet alloc] init];
2972
+ {
2973
+ std::lock_guard lock(_lock);
2974
+ for (MTRAttributeRequestPath * path in attributePaths) {
2975
+ [self _addExistentPathsFor:path to:existentPaths];
2976
+ }
2977
+ }
2978
+
2979
+ NSMutableArray<NSDictionary<NSString *, id> *> * result = [NSMutableArray arrayWithCapacity:existentPaths.count];
2980
+ for (MTRAttributePath * path in existentPaths) {
2981
+ auto * value = [self readAttributeWithEndpointID:path.endpoint clusterID:path.cluster attributeID:path.attribute params:nil];
2982
+ if (!value) {
2983
+ continue;
2984
+ }
2985
+ [result addObject:@{
2986
+ MTRAttributePathKey : path,
2987
+ MTRDataKey : value,
2988
+ }];
2989
+ }
2990
+
2991
+ return result;
2992
+ }
2993
+
2994
+ - (void)_addExistentPathsFor:(MTRAttributeRequestPath *)path to:(NSMutableSet<MTRAttributePath *> *)set
2995
+ {
2996
+ os_unfair_lock_assert_owner(&_lock);
2997
+
2998
+ if (path.endpoint != nil) {
2999
+ [self _addExistentPathsForEndpoint:path.endpoint path:path to:set];
3000
+ return;
3001
+ }
3002
+
3003
+ NSArray<NSNumber *> * endpointList = [self _endpointList];
3004
+ for (NSNumber * endpoint in endpointList) {
3005
+ [self _addExistentPathsForEndpoint:endpoint path:path to:set];
3006
+ }
3007
+ }
3008
+
3009
+ - (void)_addExistentPathsForEndpoint:(NSNumber *)endpoint path:(MTRAttributeRequestPath *)path to:(NSMutableSet<MTRAttributePath *> *)set
3010
+ {
3011
+ os_unfair_lock_assert_owner(&_lock);
3012
+
3013
+ if (path.cluster != nil) {
3014
+ [self _addExistentPathsForEndpoint:endpoint cluster:path.cluster attribute:path.attribute to:set];
3015
+ return;
3016
+ }
3017
+
3018
+ auto * clusterList = [self _serverListForEndpointID:endpoint];
3019
+ for (NSNumber * cluster in clusterList) {
3020
+ [self _addExistentPathsForEndpoint:endpoint cluster:cluster attribute:path.attribute to:set];
3021
+ }
3022
+ }
3023
+
3024
+ - (void)_addExistentPathsForEndpoint:(NSNumber *)endpoint cluster:(NSNumber *)cluster attribute:(NSNumber * _Nullable)attribute to:(NSMutableSet<MTRAttributePath *> *)set
3025
+ {
3026
+ os_unfair_lock_assert_owner(&_lock);
3027
+
3028
+ if (attribute != nil) {
3029
+ [set addObject:[MTRAttributePath attributePathWithEndpointID:endpoint clusterID:cluster attributeID:attribute]];
3030
+ return;
3031
+ }
3032
+
3033
+ auto * attributeList = [self _attributeListForEndpointID:endpoint clusterID:cluster];
3034
+ for (NSNumber * existentAttribute in attributeList) {
3035
+ [set addObject:[MTRAttributePath attributePathWithEndpointID:endpoint clusterID:cluster attributeID:existentAttribute]];
3036
+ }
3037
+ }
3038
+
2966
3039
- (void)_invokeCommandWithEndpointID:(NSNumber *)endpointID
2967
3040
clusterID:(NSNumber *)clusterID
2968
3041
commandID:(NSNumber *)commandID
@@ -3968,19 +4041,55 @@ - (void)_updateAttributeDependentDescriptionData
3968
4041
{
3969
4042
os_unfair_lock_assert_owner(&_lock);
3970
4043
3971
- auto * partsListPath = [MTRAttributePath attributePathWithEndpointID:@(kRootEndpointId)
3972
- clusterID:@(MTRClusterIDTypeDescriptorID)
3973
- attributeID:@(MTRAttributeIDTypeClusterDescriptorAttributePartsListID)];
3974
- auto * partsList = [self _cachedAttributeValueForPath:partsListPath];
3975
- NSMutableArray<NSNumber *> * endpointsOnDevice = [self arrayOfNumbersFromAttributeValue:partsList];
3976
- if (!endpointsOnDevice) {
3977
- endpointsOnDevice = [[NSMutableArray<NSNumber *> alloc] init];
3978
- }
3979
- // Add Root node!
3980
- [endpointsOnDevice addObject:@(0)];
4044
+ auto * partsList = [self _cachedListOfNumbersValueForEndpointID:@(kRootEndpointId)
4045
+ clusterID:@(MTRClusterIDTypeDescriptorID)
4046
+ attributeID:@(MTRAttributeIDTypeClusterDescriptorAttributePartsListID)];
4047
+ NSMutableArray<NSNumber *> * endpointsOnDevice = [partsList mutableCopy];
4048
+ // Add Root Node endpoint.
4049
+ [endpointsOnDevice addObject:@(kRootEndpointId)];
3981
4050
return endpointsOnDevice;
3982
4051
}
3983
4052
4053
+ /**
4054
+ * Returns the cached value of the relevant attribute as a list of numbers.
4055
+ * Returns an empty list if the value does not exist or can't be converted to a
4056
+ * list of numbers.
4057
+ */
4058
+ - (NSArray<NSNumber *> *)_cachedListOfNumbersValueForEndpointID:(NSNumber *)endpointID
4059
+ clusterID:(NSNumber *)clusterID
4060
+ attributeID:(NSNumber *)attributeID
4061
+ {
4062
+ os_unfair_lock_assert_owner(&_lock);
4063
+
4064
+ auto * path = [MTRAttributePath attributePathWithEndpointID:endpointID
4065
+ clusterID:clusterID
4066
+ attributeID:attributeID];
4067
+ auto * value = [self _cachedAttributeValueForPath:path];
4068
+ NSArray<NSNumber *> * arrayValue = [self arrayOfNumbersFromAttributeValue:value];
4069
+ if (arrayValue) {
4070
+ return arrayValue;
4071
+ }
4072
+ return [NSArray array];
4073
+ }
4074
+
4075
+ - (NSArray<NSNumber *> *)_serverListForEndpointID:(NSNumber *)endpointID
4076
+ {
4077
+ os_unfair_lock_assert_owner(&_lock);
4078
+
4079
+ return [self _cachedListOfNumbersValueForEndpointID:endpointID
4080
+ clusterID:@(MTRClusterIDTypeDescriptorID)
4081
+ attributeID:@(MTRAttributeIDTypeClusterDescriptorAttributeServerListID)];
4082
+ }
4083
+
4084
+ - (NSArray<NSNumber *> *)_attributeListForEndpointID:(NSNumber *)endpointID clusterID:(NSNumber *)clusterID
4085
+ {
4086
+ os_unfair_lock_assert_owner(&_lock);
4087
+
4088
+ return [self _cachedListOfNumbersValueForEndpointID:endpointID
4089
+ clusterID:clusterID
4090
+ attributeID:@(MTRAttributeIDTypeGlobalAttributeAttributeListID)];
4091
+ }
4092
+
3984
4093
- (NSNumber * _Nullable)_networkFeatures
3985
4094
{
3986
4095
NSNumber * _Nullable result = nil;
0 commit comments