Skip to content

Commit

Permalink
Make MTRClusters just use MTRDevice for command invokes.
Browse files Browse the repository at this point in the history
Decouples them from MTRBaseClusters.
  • Loading branch information
bzbarsky-apple committed Oct 3, 2023
1 parent 1ec98c8 commit b074a31
Show file tree
Hide file tree
Showing 16 changed files with 21,005 additions and 6,905 deletions.
47 changes: 41 additions & 6 deletions src/darwin/Framework/CHIP/MTRBaseDevice.mm
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ - (void)subscribeWithQueue:(dispatch_queue_t)queue
}

// Convert TLV data into data-value dictionary as described in MTRDeviceResponseHandler
id _Nullable MTRDecodeDataValueDictionaryFromCHIPTLV(chip::TLV::TLVReader * data)
NSDictionary<NSString *, id> * _Nullable MTRDecodeDataValueDictionaryFromCHIPTLV(chip::TLV::TLVReader * data)
{
chip::TLV::TLVType dataTLVType = data->GetType();
switch (dataTLVType) {
Expand Down Expand Up @@ -1208,14 +1208,45 @@ - (void)invokeCommandWithEndpointID:(NSNumber *)endpointID
timedInvokeTimeout:(NSNumber * _Nullable)timeoutMs
queue:(dispatch_queue_t)queue
completion:(MTRDeviceResponseHandler)completion
{
// We don't have a way to communicate a non-default invoke timeout
// here for now.
// TODO: https://github.com/project-chip/connectedhomeip/issues/24563
[self _invokeCommandWithEndpointID:endpointID
clusterID:clusterID
commandID:commandID
commandFields:commandFields
timedInvokeTimeout:timeoutMs
serverSideProcessingTimeout:nil
queue:queue
completion:completion];
}

- (void)_invokeCommandWithEndpointID:(NSNumber *)endpointID
clusterID:(NSNumber *)clusterID
commandID:(NSNumber *)commandID
commandFields:(id)commandFields
timedInvokeTimeout:(NSNumber * _Nullable)timeoutMs
serverSideProcessingTimeout:(NSNumber * _Nullable)serverSideProcessingTimeout
queue:(dispatch_queue_t)queue
completion:(MTRDeviceResponseHandler)completion
{
endpointID = (endpointID == nil) ? nil : [endpointID copy];
clusterID = (clusterID == nil) ? nil : [clusterID copy];
commandID = (commandID == nil) ? nil : [commandID copy];
// TODO: This is not going to deep-copy the NSArray instances in
// commandFields. We need to do something smarter here.
commandFields = (commandFields == nil) ? nil : [commandFields copy];
timeoutMs = (timeoutMs == nil) ? nil : [timeoutMs copy];

serverSideProcessingTimeout = [serverSideProcessingTimeout copy];
if (serverSideProcessingTimeout != nil) {
serverSideProcessingTimeout = MTRClampedNumber(serverSideProcessingTimeout, @(0), @(UINT16_MAX));
}

timeoutMs = [timeoutMs copy];
if (timeoutMs != nil) {
timeoutMs = MTRClampedNumber(timeoutMs, @(1), @(UINT16_MAX));
}

auto * bridge = new MTRDataValueDictionaryCallbackBridge(queue, completion,
^(ExchangeManager & exchangeManager, const SessionHandle & session, MTRDataValueDictionaryCallback successCb,
Expand Down Expand Up @@ -1261,10 +1292,14 @@ - (void)invokeCommandWithEndpointID:(NSNumber *)endpointID
ReturnErrorOnFailure(commandSender->AddRequestData(commandPath, MTRDataValueDictionaryDecodableType(commandFields),
(timeoutMs == nil) ? NullOptional : Optional<uint16_t>([timeoutMs unsignedShortValue])));

// We don't have a way to communicate a non-default invoke timeout
// here for now.
// TODO: https://github.com/project-chip/connectedhomeip/issues/24563
ReturnErrorOnFailure(commandSender->SendCommandRequest(session, NullOptional));
Optional<System::Clock::Timeout> invokeTimeout;
if (serverSideProcessingTimeout != nil) {
// Clamp to a number of seconds that will not overflow 32-bit
// int when converted to ms.
auto serverTimeoutInSeconds = System::Clock::Seconds16(serverSideProcessingTimeout.unsignedShortValue);
invokeTimeout.SetValue(session->ComputeRoundTripTimeout(serverTimeoutInSeconds));
}
ReturnErrorOnFailure(commandSender->SendCommandRequest(session, invokeTimeout));

decoder.release();
commandSender.release();
Expand Down
16 changes: 15 additions & 1 deletion src/darwin/Framework/CHIP/MTRBaseDevice_Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,20 @@ static inline MTRTransportType MTRMakeTransportType(chip::Transport::Type type)
clusterID:(chip::ClusterId)clusterID
commandID:(chip::CommandId)commandID
error:(NSError * __autoreleasing *)error;

/**
* Like the public invokeCommandWithEndpointID but allows passing through a
* serverSideProcessingTimeout.
*/
- (void)_invokeCommandWithEndpointID:(NSNumber *)endpointID
clusterID:(NSNumber *)clusterID
commandID:(NSNumber *)commandID
commandFields:(id)commandFields
timedInvokeTimeout:(NSNumber * _Nullable)timeoutMs
serverSideProcessingTimeout:(NSNumber * _Nullable)serverSideProcessingTimeout
queue:(dispatch_queue_t)queue
completion:(MTRDeviceResponseHandler)completion;

@end

@interface MTRClusterPath ()
Expand Down Expand Up @@ -140,6 +154,6 @@ static inline MTRTransportType MTRMakeTransportType(chip::Transport::Type type)

// Exported utility function
// Convert TLV data into data-value dictionary as described in MTRDeviceResponseHandler
id _Nullable MTRDecodeDataValueDictionaryFromCHIPTLV(chip::TLV::TLVReader * data);
NSDictionary<NSString *, id> * _Nullable MTRDecodeDataValueDictionaryFromCHIPTLV(chip::TLV::TLVReader * data);

NS_ASSUME_NONNULL_END
9 changes: 0 additions & 9 deletions src/darwin/Framework/CHIP/MTRCluster.mm
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,6 @@ - (instancetype)initWithEndpointID:(NSNumber *)endpointID queue:(dispatch_queue_
return self;
}

- (chip::ByteSpan)asByteSpan:(NSData *)value
{
return AsByteSpan(value);
}

- (chip::CharSpan)asCharSpan:(NSString *)value
{
return AsCharSpan(value);
}
@end

@implementation MTRWriteParams
Expand Down
2 changes: 0 additions & 2 deletions src/darwin/Framework/CHIP/MTRCluster_Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) chip::EndpointId endpoint;

- (instancetype)initWithEndpointID:(NSNumber *)endpointID queue:(dispatch_queue_t)queue;
- (chip::ByteSpan)asByteSpan:(NSData *)value;
- (chip::CharSpan)asCharSpan:(NSString *)value;
@end

@interface MTRReadParams ()
Expand Down
72 changes: 50 additions & 22 deletions src/darwin/Framework/CHIP/MTRDevice.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1056,17 +1056,44 @@ - (void)invokeCommandWithEndpointID:(NSNumber *)endpointID
timedInvokeTimeout:(NSNumber * _Nullable)timeout
queue:(dispatch_queue_t)queue
completion:(MTRDeviceResponseHandler)completion
{
// We don't have a way to communicate a non-default invoke timeout
// here for now.
// TODO: https://github.com/project-chip/connectedhomeip/issues/24563

[self _invokeCommandWithEndpointID:endpointID
clusterID:clusterID
commandID:commandID
commandFields:commandFields
expectedValues:expectedValues
expectedValueInterval:expectedValueInterval
timedInvokeTimeout:timeout
serverSideProcessingTimeout:nil
queue:queue
completion:completion];
}

- (void)_invokeCommandWithEndpointID:(NSNumber *)endpointID
clusterID:(NSNumber *)clusterID
commandID:(NSNumber *)commandID
commandFields:(id)commandFields
expectedValues:(NSArray<NSDictionary<NSString *, id> *> * _Nullable)expectedValues
expectedValueInterval:(NSNumber * _Nullable)expectedValueInterval
timedInvokeTimeout:(NSNumber * _Nullable)timeout
serverSideProcessingTimeout:(NSNumber * _Nullable)serverSideProcessingTimeout
queue:(dispatch_queue_t)queue
completion:(MTRDeviceResponseHandler)completion
{
NSString * logPrefix = [NSString stringWithFormat:@"%@ command %@ %@ %@", self, endpointID, clusterID, commandID];
if (timeout) {
timeout = MTRClampedNumber(timeout, @(1), @(UINT16_MAX));
}
if (!expectedValueInterval || ([expectedValueInterval compare:@(0)] == NSOrderedAscending)) {
expectedValues = nil;
} else {
expectedValueInterval = MTRClampedNumber(expectedValueInterval, @(1), @(UINT32_MAX));
}

serverSideProcessingTimeout = [serverSideProcessingTimeout copy];
timeout = [timeout copy];

uint64_t expectedValueID = 0;
NSMutableArray<MTRAttributePath *> * attributePaths = nil;
if (expectedValues) {
Expand All @@ -1087,25 +1114,26 @@ - (void)invokeCommandWithEndpointID:(NSNumber *)endpointID
MTR_LOG_DEFAULT("%@ dequeueWorkItem %@", logPrefix, self->_asyncWorkQueue);
MTRBaseDevice * baseDevice = [self newBaseDevice];
[baseDevice
invokeCommandWithEndpointID:endpointID
clusterID:clusterID
commandID:commandID
commandFields:commandFields
timedInvokeTimeout:timeout
queue:self.queue
completion:^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
// Log the data at the INFO level (not usually persisted permanently),
// but make sure we log the work completion at the DEFAULT level.
MTR_LOG_INFO("%@ received response: %@ error: %@", logPrefix, values, error);
dispatch_async(queue, ^{
completion(values, error);
});
if (error && expectedValues) {
[self removeExpectedValuesForAttributePaths:attributePaths expectedValueID:expectedValueID];
}
MTR_LOG_DEFAULT("%@ endWork", logPrefix);
workCompletion(MTRAsyncWorkComplete);
}];
_invokeCommandWithEndpointID:endpointID
clusterID:clusterID
commandID:commandID
commandFields:commandFields
timedInvokeTimeout:timeout
serverSideProcessingTimeout:serverSideProcessingTimeout
queue:self.queue
completion:^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
// Log the data at the INFO level (not usually persisted permanently),
// but make sure we log the work completion at the DEFAULT level.
MTR_LOG_INFO("%@ received response: %@ error: %@", logPrefix, values, error);
dispatch_async(queue, ^{
completion(values, error);
});
if (error && expectedValues) {
[self removeExpectedValuesForAttributePaths:attributePaths expectedValueID:expectedValueID];
}
MTR_LOG_DEFAULT("%@ endWork", logPrefix);
workCompletion(MTRAsyncWorkComplete);
}];
}];
MTR_LOG_DEFAULT("%@ enqueueWorkItem %@", logPrefix, _asyncWorkQueue);
[_asyncWorkQueue enqueueWorkItem:workItem];
Expand Down
15 changes: 15 additions & 0 deletions src/darwin/Framework/CHIP/MTRDevice_Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,21 @@ typedef void (^MTRDevicePerformAsyncBlock)(MTRBaseDevice * baseDevice);
// false-positives, for example due to compressed fabric id collisions.
- (void)nodeMayBeAdvertisingOperational;

/**
* Like the public invokeCommandWithEndpointID but allows passing through a
* serverSideProcessingTimeout.
*/
- (void)_invokeCommandWithEndpointID:(NSNumber *)endpointID
clusterID:(NSNumber *)clusterID
commandID:(NSNumber *)commandID
commandFields:(id)commandFields
expectedValues:(NSArray<NSDictionary<NSString *, id> *> * _Nullable)expectedValues
expectedValueInterval:(NSNumber * _Nullable)expectedValueInterval
timedInvokeTimeout:(NSNumber * _Nullable)timeout
serverSideProcessingTimeout:(NSNumber * _Nullable)serverSideProcessingTimeout
queue:(dispatch_queue_t)queue
completion:(MTRDeviceResponseHandler)completion;

@property (nonatomic, readonly) MTRDeviceController * deviceController;
@property (nonatomic, readonly, copy) NSNumber * nodeID;
// Queue used for various internal bookkeeping work.
Expand Down
2 changes: 2 additions & 0 deletions src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#import "MTRCommandPayloadsObjc.h"
#import "MTRDevice_Internal.h"
#import "MTRStructsObjc.h"
#import "NSStringSpanConversion.h"
#import "NSDataSpanConversion.h"

#include <controller/CHIPCluster.h>
#include <lib/support/CHIPListUtils.h>
Expand Down
Loading

0 comments on commit b074a31

Please sign in to comment.