Skip to content

Commit 2695601

Browse files
Remove readAttributeWithEndpointID implementation from MTRDevice. (project-chip#35150)
This is implemented (differently) by the different subclasses. Once this implementation is removed, the following become unreachable and can be removed: * _attributeValueDictionaryForAttributePath * _subscriptionAbleToReport * _readThroughSkipped At that point _subscriptionsAllowed becomes unreachable and can be removed.
1 parent ae5d75c commit 2695601

File tree

1 file changed

+7
-222
lines changed

1 file changed

+7
-222
lines changed

src/darwin/Framework/CHIP/MTRDevice.mm

+7-222
Original file line numberDiff line numberDiff line change
@@ -649,21 +649,7 @@ - (void)_setDSTOffsets:(NSArray<MTRTimeSynchronizationClusterDSTOffsetStruct *>
649649
return outputArray;
650650
}
651651

652-
#pragma mark Subscription and delegate handling
653-
654-
// subscription intervals are in seconds
655-
#define MTR_DEVICE_SUBSCRIPTION_MAX_INTERVAL_MIN (10 * 60) // 10 minutes (for now)
656-
#define MTR_DEVICE_SUBSCRIPTION_MAX_INTERVAL_MAX (60 * 60) // 60 minutes
657-
658-
- (BOOL)_subscriptionsAllowed
659-
{
660-
os_unfair_lock_assert_owner(&self->_lock);
661-
662-
// TODO: XPC: This function and all its callsites should go away from this class.
663-
664-
// We should not allow a subscription for device controllers over XPC.
665-
return ![_deviceController isKindOfClass:MTRDeviceControllerOverXPC.class];
666-
}
652+
#pragma mark Delegate handling
667653

668654
- (void)setDelegate:(id<MTRDeviceDelegate>)delegate queue:(dispatch_queue_t)queue
669655
{
@@ -757,41 +743,6 @@ - (void)nodeMayBeAdvertisingOperational
757743
MTR_LOG("%@ saw new operational advertisement", self);
758744
}
759745

760-
// Return YES if we are in a state where, apart from communication issues with
761-
// the device, we will be able to get reports via our subscription.
762-
- (BOOL)_subscriptionAbleToReport
763-
{
764-
std::lock_guard lock(_lock);
765-
if (![self _delegateExists]) {
766-
// No delegate definitely means no subscription.
767-
return NO;
768-
}
769-
770-
// For unit testing only, matching logic in setDelegate
771-
#ifdef DEBUG
772-
__block BOOL useTestDelegateOverride = NO;
773-
__block BOOL testDelegateShouldSetUpSubscriptionForDevice = NO;
774-
[self _callFirstDelegateSynchronouslyWithBlock:^(id testDelegate) {
775-
if ([testDelegate respondsToSelector:@selector(unitTestShouldSetUpSubscriptionForDevice:)]) {
776-
useTestDelegateOverride = YES;
777-
testDelegateShouldSetUpSubscriptionForDevice = [testDelegate unitTestShouldSetUpSubscriptionForDevice:self];
778-
}
779-
}];
780-
if (useTestDelegateOverride && !testDelegateShouldSetUpSubscriptionForDevice) {
781-
return NO;
782-
}
783-
784-
#endif
785-
786-
// Subscriptions are not able to report if they are not allowed.
787-
return [self _subscriptionsAllowed];
788-
}
789-
790-
// Notification that read-through was skipped for an attribute read.
791-
- (void)_readThroughSkipped
792-
{
793-
}
794-
795746
- (BOOL)_delegateExists
796747
{
797748
os_unfair_lock_assert_owner(&self->_lock);
@@ -1880,147 +1831,12 @@ static BOOL AttributeHasChangesOmittedQuality(MTRAttributePath * attributePath)
18801831
attributeID:(NSNumber *)attributeID
18811832
params:(MTRReadParams * _Nullable)params
18821833
{
1883-
MTRAttributePath * attributePath = [MTRAttributePath attributePathWithEndpointID:endpointID
1884-
clusterID:clusterID
1885-
attributeID:attributeID];
1886-
1887-
BOOL attributeIsSpecified = MTRAttributeIsSpecified(clusterID.unsignedIntValue, attributeID.unsignedIntValue);
1888-
BOOL hasChangesOmittedQuality;
1889-
if (attributeIsSpecified) {
1890-
hasChangesOmittedQuality = AttributeHasChangesOmittedQuality(attributePath);
1891-
} else {
1892-
if (params == nil) {
1893-
hasChangesOmittedQuality = NO;
1894-
} else {
1895-
hasChangesOmittedQuality = !params.assumeUnknownAttributesReportable;
1896-
}
1897-
}
1898-
1899-
// Return current known / expected value right away
1900-
NSDictionary<NSString *, id> * attributeValueToReturn = [self _attributeValueDictionaryForAttributePath:attributePath];
1901-
1902-
// Send read request to device if any of the following are true:
1903-
// 1. Subscription not in a state we can expect reports
1904-
// 2. The attribute has the Changes Omitted quality, so we won't get reports for it.
1905-
// 3. The attribute is not in the spec, and the read params asks to assume
1906-
// an unknown attribute has the Changes Omitted quality.
1907-
if (![self _subscriptionAbleToReport] || hasChangesOmittedQuality) {
1908-
// Read requests container will be a mutable array of items, each being an array containing:
1909-
// [attribute request path, params]
1910-
// Batching handler should only coalesce when params are equal.
1911-
1912-
// For this single read API there's only 1 array item. Use NSNull to stand in for nil params for easy comparison.
1913-
MTRAttributeRequestPath * readRequestPath = [MTRAttributeRequestPath requestPathWithEndpointID:endpointID
1914-
clusterID:clusterID
1915-
attributeID:attributeID];
1916-
NSArray * readRequestData = @[ readRequestPath, params ?: [NSNull null] ];
1917-
1918-
// But first, check if a duplicate read request is already queued and return
1919-
if ([_asyncWorkQueue hasDuplicateForTypeID:MTRDeviceWorkItemDuplicateReadTypeID workItemData:readRequestData]) {
1920-
return attributeValueToReturn;
1921-
}
1922-
1923-
NSMutableArray<NSArray *> * readRequests = [NSMutableArray arrayWithObject:readRequestData];
1924-
1925-
// Create work item, set ready handler to perform task, then enqueue the work
1926-
MTRAsyncWorkItem * workItem = [[MTRAsyncWorkItem alloc] initWithQueue:self.queue];
1927-
uint64_t workItemID = workItem.uniqueID; // capture only the ID, not the work item
1928-
NSNumber * nodeID = [self nodeID];
1929-
1930-
[workItem setBatchingID:MTRDeviceWorkItemBatchingReadID data:readRequests handler:^(id opaqueDataCurrent, id opaqueDataNext) {
1931-
mtr_hide(self); // don't capture self accidentally
1932-
NSMutableArray<NSArray *> * readRequestsCurrent = opaqueDataCurrent;
1933-
NSMutableArray<NSArray *> * readRequestsNext = opaqueDataNext;
1934-
1935-
MTRBatchingOutcome outcome = MTRNotBatched;
1936-
while (readRequestsNext.count) {
1937-
// Can only read up to 9 paths at a time, per spec
1938-
if (readRequestsCurrent.count >= 9) {
1939-
MTR_LOG("Batching read attribute work item [%llu]: cannot add more work, item is full [0x%016llX:%@:0x%llx:0x%llx]", workItemID, nodeID.unsignedLongLongValue, endpointID, clusterID.unsignedLongLongValue, attributeID.unsignedLongLongValue);
1940-
return outcome;
1941-
}
1942-
1943-
// if params don't match then they cannot be merged
1944-
if (![readRequestsNext[0][MTRDeviceReadRequestFieldParamsIndex]
1945-
isEqual:readRequestsCurrent[0][MTRDeviceReadRequestFieldParamsIndex]]) {
1946-
MTR_LOG("Batching read attribute work item [%llu]: cannot add more work, parameter mismatch [0x%016llX:%@:0x%llx:0x%llx]", workItemID, nodeID.unsignedLongLongValue, endpointID, clusterID.unsignedLongLongValue, attributeID.unsignedLongLongValue);
1947-
return outcome;
1948-
}
1949-
1950-
// merge the next item's first request into the current item's list
1951-
auto readItem = readRequestsNext.firstObject;
1952-
[readRequestsNext removeObjectAtIndex:0];
1953-
[readRequestsCurrent addObject:readItem];
1954-
MTR_LOG("Batching read attribute work item [%llu]: added %@ (now %lu requests total) [0x%016llX:%@:0x%llx:0x%llx]",
1955-
workItemID, readItem, static_cast<unsigned long>(readRequestsCurrent.count), nodeID.unsignedLongLongValue, endpointID, clusterID.unsignedLongLongValue, attributeID.unsignedLongLongValue);
1956-
outcome = MTRBatchedPartially;
1957-
}
1958-
NSCAssert(readRequestsNext.count == 0, @"should have batched everything or returned early");
1959-
return MTRBatchedFully;
1960-
}];
1961-
[workItem setDuplicateTypeID:MTRDeviceWorkItemDuplicateReadTypeID handler:^(id opaqueItemData, BOOL * isDuplicate, BOOL * stop) {
1962-
mtr_hide(self); // don't capture self accidentally
1963-
for (NSArray * readItem in readRequests) {
1964-
if ([readItem isEqual:opaqueItemData]) {
1965-
MTR_LOG("Read attribute work item [%llu] report duplicate %@ [0x%016llX:%@:0x%llx:0x%llx]", workItemID, readItem, nodeID.unsignedLongLongValue, endpointID, clusterID.unsignedLongLongValue, attributeID.unsignedLongLongValue);
1966-
*isDuplicate = YES;
1967-
*stop = YES;
1968-
return;
1969-
}
1970-
}
1971-
*stop = NO;
1972-
}];
1973-
[workItem setReadyHandler:^(MTRDevice * self, NSInteger retryCount, MTRAsyncWorkCompletionBlock completion) {
1974-
// Sanity check
1975-
if (readRequests.count == 0) {
1976-
MTR_LOG_ERROR("Read attribute work item [%llu] contained no read requests", workItemID);
1977-
completion(MTRAsyncWorkComplete);
1978-
return;
1979-
}
1980-
1981-
// Build the attribute paths from the read requests
1982-
NSMutableArray<MTRAttributeRequestPath *> * attributePaths = [NSMutableArray array];
1983-
for (NSArray * readItem in readRequests) {
1984-
NSAssert(readItem.count == 2, @"invalid read attribute item");
1985-
[attributePaths addObject:readItem[MTRDeviceReadRequestFieldPathIndex]];
1986-
}
1987-
// If param is the NSNull stand-in, then just use nil
1988-
id readParamObject = readRequests[0][MTRDeviceReadRequestFieldParamsIndex];
1989-
MTRReadParams * readParams = (![readParamObject isEqual:[NSNull null]]) ? readParamObject : nil;
1990-
1991-
MTRBaseDevice * baseDevice = [self newBaseDevice];
1992-
[baseDevice
1993-
readAttributePaths:attributePaths
1994-
eventPaths:nil
1995-
params:readParams
1996-
includeDataVersion:YES
1997-
queue:self.queue
1998-
completion:^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
1999-
if (values) {
2000-
// Since the format is the same data-value dictionary, this looks like an
2001-
// attribute report
2002-
MTR_LOG("Read attribute work item [%llu] result: %@ [0x%016llX:%@:0x%llX:0x%llX]", workItemID, values, nodeID.unsignedLongLongValue, endpointID, clusterID.unsignedLongLongValue, attributeID.unsignedLongLongValue);
2003-
[self _handleAttributeReport:values fromSubscription:NO];
2004-
}
2005-
2006-
// TODO: better retry logic
2007-
if (error && (retryCount < 2)) {
2008-
MTR_LOG_ERROR("Read attribute work item [%llu] failed (will retry): %@ [0x%016llX:%@:0x%llx:0x%llx]", workItemID, error, nodeID.unsignedLongLongValue, endpointID, clusterID.unsignedLongLongValue, attributeID.unsignedLongLongValue);
2009-
completion(MTRAsyncWorkNeedsRetry);
2010-
} else {
2011-
if (error) {
2012-
MTR_LOG("Read attribute work item [%llu] failed (giving up): %@ [0x%016llX:%@:0x%llx:0x%llx]", workItemID, error, nodeID.unsignedLongLongValue, endpointID, clusterID.unsignedLongLongValue, attributeID.unsignedLongLongValue);
2013-
}
2014-
completion(MTRAsyncWorkComplete);
2015-
}
2016-
}];
2017-
}];
2018-
[_asyncWorkQueue enqueueWorkItem:workItem descriptionWithFormat:@"read %@ 0x%llx 0x%llx", endpointID, clusterID.unsignedLongLongValue, attributeID.unsignedLongLongValue];
2019-
} else {
2020-
[self _readThroughSkipped];
2021-
}
2022-
2023-
return attributeValueToReturn;
1834+
#define ErrorStr "MTRDevice readAttributeWithEndpointID:clusterID:attributeID:params: must be handled by subclasses"
1835+
MTR_LOG_ERROR(ErrorStr);
1836+
#ifdef DEBUG
1837+
NSAssert(NO, @ErrorStr);
1838+
#endif // DEBUG
1839+
return nil;
20241840
}
20251841

20261842
- (void)writeAttributeWithEndpointID:(NSNumber *)endpointID
@@ -2456,37 +2272,6 @@ - (void)_performScheduledExpirationCheck
24562272
[self _checkExpiredExpectedValues];
24572273
}
24582274

2459-
// Get attribute value dictionary for an attribute path from the right cache
2460-
- (NSDictionary<NSString *, id> *)_attributeValueDictionaryForAttributePath:(MTRAttributePath *)attributePath
2461-
{
2462-
std::lock_guard lock(_lock);
2463-
2464-
// First check expected value cache
2465-
NSArray * expectedValue = _expectedValueCache[attributePath];
2466-
if (expectedValue) {
2467-
NSDate * now = [NSDate date];
2468-
if ([now compare:expectedValue[MTRDeviceExpectedValueFieldExpirationTimeIndex]] == NSOrderedDescending) {
2469-
// expired - purge and fall through
2470-
_expectedValueCache[attributePath] = nil;
2471-
} else {
2472-
// not yet expired - return result
2473-
return expectedValue[MTRDeviceExpectedValueFieldValueIndex];
2474-
}
2475-
}
2476-
2477-
// Then check read cache
2478-
NSDictionary<NSString *, id> * cachedAttributeValue = [self _cachedAttributeValueForPath:attributePath];
2479-
if (cachedAttributeValue) {
2480-
return cachedAttributeValue;
2481-
} else {
2482-
// TODO: when not found in cache, generated default values should be used
2483-
MTR_LOG("%@ _attributeValueDictionaryForAttributePath: could not find cached attribute values for attribute %@", self,
2484-
attributePath);
2485-
}
2486-
2487-
return nil;
2488-
}
2489-
24902275
- (BOOL)_attributeDataValue:(NSDictionary *)one isEqualToDataValue:(NSDictionary *)theOther
24912276
{
24922277
// Sanity check for nil cases

0 commit comments

Comments
 (0)