Skip to content

Commit

Permalink
Rename expectedResult to requiredResponse in the invokeCommands API.
Browse files Browse the repository at this point in the history
The old naming was too confusing, and this more accurately represents what is
actually going on.
  • Loading branch information
bzbarsky-apple committed Feb 6, 2025
1 parent 48fc426 commit 87c8e04
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
NS_ASSUME_NONNULL_BEGIN

/**
* An object representing a single command to be invoked and the expected
* result of invoking it.
* An object representing a single command to be invoked and the response
* required for the invoke to be considered successful.
*/
MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4))
@interface MTRCommandWithExpectedResult : NSObject <NSCopying, NSSecureCoding>
@interface MTRCommandWithRequiredResponse : NSObject <NSCopying, NSSecureCoding>

/**
* The path of the command being invoked.
Expand All @@ -39,22 +39,22 @@ MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4))
@property (nonatomic, retain, nullable) NSDictionary<NSString *, id> * commandFields;

/**
* The expected result of invoking the command.
* The response that represents this command succeeding.
*
* If this is nil, that indicates that the invoke is considered successful if it
* does not result in an error status response.
*
* If this is is not nil, then invoke is considered successful if
* it results in a data response and for each entry in the provided
* expectedResult the field whose field ID matches the key of the entry has a
* If this is is not nil, then the invoke is considered successful if
* the response is a data response and for each entry in the provided
* requiredResponse the field whose field ID matches the key of the entry has a
* value that equals the value of the entry. Values of entries are data-value
* dictionaries.
*/
@property (nonatomic, copy, nullable) NSDictionary<NSNumber *, NSDictionary<NSString *, id> *> * expectedResult;
@property (nonatomic, copy, nullable) NSDictionary<NSNumber *, NSDictionary<NSString *, id> *> * requiredResponse;

- (instancetype)initWithPath:(MTRCommandPath *)path
commandFields:(nullable NSDictionary<NSString *, id> *)commandFields
expectedResult:(nullable NSDictionary<NSNumber *, NSDictionary<NSString *, id> *> *)expectedResult;
requiredResponse:(nullable NSDictionary<NSNumber *, NSDictionary<NSString *, id> *> *)requiredResponse;

@end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,35 @@
#import "MTRLogging_Internal.h"
#import <Matter/Matter.h>

@implementation MTRCommandWithExpectedResult
@implementation MTRCommandWithRequiredResponse
- (instancetype)initWithPath:(MTRCommandPath *)path
commandFields:(nullable NSDictionary<NSString *, id> *)commandFields
expectedResult:(nullable NSDictionary<NSNumber *, NSDictionary<NSString *, id> *> *)expectedResult
requiredResponse:(nullable NSDictionary<NSNumber *, NSDictionary<NSString *, id> *> *)requiredResponse
{
if (self = [super init]) {
self.path = path;
self.commandFields = commandFields;
self.expectedResult = expectedResult;
self.requiredResponse = requiredResponse;
}

return self;
}

- (id)copyWithZone:(NSZone *)zone
{
return [[MTRCommandWithExpectedResult alloc] initWithPath:self.path commandFields:self.commandFields expectedResult:self.expectedResult];
return [[MTRCommandWithRequiredResponse alloc] initWithPath:self.path commandFields:self.commandFields requiredResponse:self.requiredResponse];
}

- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p, path: %@, fields: %@, expectedResult: %@", NSStringFromClass(self.class), self, self.path, self.commandFields, self.expectedResult];
return [NSString stringWithFormat:@"<%@: %p, path: %@, fields: %@, requiredResponse: %@", NSStringFromClass(self.class), self, self.path, self.commandFields, self.requiredResponse];
}

#pragma mark - MTRCommandWithExpectedResult NSSecureCoding implementation
#pragma mark - MTRCommandWithRequiredResponse NSSecureCoding implementation

static NSString * const sPathKey = @"pathKey";
static NSString * const sFieldsKey = @"fieldsKey";
static NSString * const sExpectedResultKey = @"expectedResultKey";
static NSString * const sExpectedResultKey = @"requiredResponseKey";

+ (BOOL)supportsSecureCoding
{
Expand All @@ -62,38 +62,38 @@ - (nullable instancetype)initWithCoder:(NSCoder *)decoder

_path = [decoder decodeObjectOfClass:MTRCommandPath.class forKey:sPathKey];
if (!_path || ![_path isKindOfClass:MTRCommandPath.class]) {
MTR_LOG_ERROR("MTRCommandWithExpectedResult decoded %@ for endpoint, not MTRCommandPath.", _path);
MTR_LOG_ERROR("MTRCommandWithRequiredResponse decoded %@ for endpoint, not MTRCommandPath.", _path);
return nil;
}

_commandFields = [decoder decodeObjectOfClass:NSDictionary.class forKey:sFieldsKey];
if (_commandFields) {
if (![_commandFields isKindOfClass:NSDictionary.class]) {
MTR_LOG_ERROR("MTRCommandWithExpectedResult decoded %@ for commandFields, not NSDictionary.", _commandFields);
MTR_LOG_ERROR("MTRCommandWithRequiredResponse decoded %@ for commandFields, not NSDictionary.", _commandFields);
return nil;
}

if (!MTRDataValueDictionaryIsWellFormed(_commandFields) || ![MTRStructureValueType isEqual:_commandFields[MTRTypeKey]]) {
MTR_LOG_ERROR("MTRCommandWithExpectedResult decoded %@ for commandFields, not a structure-typed data-value dictionary.", _commandFields);
MTR_LOG_ERROR("MTRCommandWithRequiredResponse decoded %@ for commandFields, not a structure-typed data-value dictionary.", _commandFields);
return nil;
}
}

_expectedResult = [decoder decodeObjectOfClass:NSDictionary.class forKey:sExpectedResultKey];
if (_expectedResult) {
if (![_expectedResult isKindOfClass:NSDictionary.class]) {
MTR_LOG_ERROR("MTRCommandWithExpectedResult decoded %@ for expectedResult, not NSDictionary.", _expectedResult);
_requiredResponse = [decoder decodeObjectOfClass:NSDictionary.class forKey:sExpectedResultKey];
if (_requiredResponse) {
if (![_requiredResponse isKindOfClass:NSDictionary.class]) {
MTR_LOG_ERROR("MTRCommandWithRequiredResponse decoded %@ for requiredResponse, not NSDictionary.", _requiredResponse);
return nil;
}

for (id key in _expectedResult) {
for (id key in _requiredResponse) {
if (![key isKindOfClass:NSNumber.class]) {
MTR_LOG_ERROR("MTRCommandWithExpectedResult decoded key %@ in expectedResult", key);
MTR_LOG_ERROR("MTRCommandWithRequiredResponse decoded key %@ in requiredResponse", key);
return nil;
}

if (![_expectedResult[key] isKindOfClass:NSDictionary.class] || !MTRDataValueDictionaryIsWellFormed(_expectedResult[key])) {
MTR_LOG_ERROR("MTRCommandWithExpectedResult decoded value %@ for key %@ in expectedResult", _expectedResult[key], key);
if (![_requiredResponse[key] isKindOfClass:NSDictionary.class] || !MTRDataValueDictionaryIsWellFormed(_requiredResponse[key])) {
MTR_LOG_ERROR("MTRCommandWithRequiredResponse decoded value %@ for key %@ in requiredResponse", _requiredResponse[key], key);
return nil;
}
}
Expand All @@ -111,8 +111,8 @@ - (void)encodeWithCoder:(NSCoder *)coder
if (self.commandFields) {
[coder encodeObject:self.commandFields forKey:sFieldsKey];
}
if (self.expectedResult) {
[coder encodeObject:self.expectedResult forKey:sExpectedResultKey];
if (self.requiredResponse) {
[coder encodeObject:self.requiredResponse forKey:sExpectedResultKey];
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/darwin/Framework/CHIP/MTRDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#import <Matter/MTRAttributeValueWaiter.h>
#import <Matter/MTRBaseClusters.h>
#import <Matter/MTRBaseDevice.h>
#import <Matter/MTRCommandWithExpectedResult.h>
#import <Matter/MTRCommandWithRequiredResponse.h>
#import <Matter/MTRDefines.h>

NS_ASSUME_NONNULL_BEGIN
Expand Down Expand Up @@ -316,7 +316,7 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1))
* response. In this case the data-value representing the response will be
* the value of this field.
*/
- (void)invokeCommands:(NSArray<NSArray<MTRCommandWithExpectedResult *> *> *)commands
- (void)invokeCommands:(NSArray<NSArray<MTRCommandWithRequiredResponse *> *> *)commands
queue:(dispatch_queue_t)queue
completion:(MTRDeviceResponseHandler)completion MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4));

Expand Down
2 changes: 1 addition & 1 deletion src/darwin/Framework/CHIP/MTRDevice.mm
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ - (void)_invokeKnownCommandWithEndpointID:(NSNumber *)endpointID
completion:responseHandler];
}

- (void)invokeCommands:(NSArray<NSArray<MTRCommandWithExpectedResult *> *> *)commands
- (void)invokeCommands:(NSArray<NSArray<MTRCommandWithRequiredResponse *> *> *)commands
queue:(dispatch_queue_t)queue
completion:(MTRDeviceResponseHandler)completion
{
Expand Down
4 changes: 2 additions & 2 deletions src/darwin/Framework/CHIP/MTRDeviceController_XPC.mm
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,10 @@ - (NSXPCInterface *)_interfaceForServerProtocol
argumentIndex:0
ofReply:YES];

// invokeCommands gets handed MTRCommandWithExpectedResult (which includes
// invokeCommands gets handed MTRCommandWithRequiredResponse (which includes
// MTRCommandPath, which is already in allowedClasses).
[allowedClasses addObjectsFromArray:@[
[MTRCommandWithExpectedResult class],
[MTRCommandWithRequiredResponse class],
]];
[interface setClasses:allowedClasses
forSelector:@selector(deviceController:nodeID:invokeCommands:completion:)
Expand Down
14 changes: 7 additions & 7 deletions src/darwin/Framework/CHIP/MTRDevice_Concrete.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3306,7 +3306,7 @@ - (void)_invokeCommandWithEndpointID:(NSNumber *)endpointID
commandFields];
}

- (BOOL)_invokeResponse:(MTRDeviceResponseValueDictionary)response matchesExpectedResult:(NSDictionary<NSNumber *, MTRDeviceDataValueDictionary> *)expectedResult
- (BOOL)_invokeResponse:(MTRDeviceResponseValueDictionary)response matchesRequiredResponse:(NSDictionary<NSNumber *, MTRDeviceDataValueDictionary> *)requiredResponse
{
if (response[MTRDataKey] == nil) {
MTR_LOG_ERROR("%@ invokeCommands expects a data response for %@ but got no data", self, response[MTRCommandPathKey]);
Expand All @@ -3321,7 +3321,7 @@ - (BOOL)_invokeResponse:(MTRDeviceResponseValueDictionary)response matchesExpect

NSArray<NSDictionary<NSString *, id> *> * fields = data[MTRValueKey];

for (NSNumber * fieldID in expectedResult) {
for (NSNumber * fieldID in requiredResponse) {
// Check that this field is present in the response.
MTRDeviceDataValueDictionary _Nullable fieldValue = nil;
for (NSDictionary<NSString *, id> * field in fields) {
Expand All @@ -3336,7 +3336,7 @@ - (BOOL)_invokeResponse:(MTRDeviceResponseValueDictionary)response matchesExpect
return NO;
}

auto * expected = expectedResult[fieldID];
auto * expected = requiredResponse[fieldID];
if (![expected isEqual:fieldValue]) {
MTR_LOG_ERROR("%@ invokeCommands response for %@ field %@ got %@ but expected %@", self, response[MTRCommandPathKey], fieldID, fieldValue, expected);
return NO;
Expand All @@ -3346,7 +3346,7 @@ - (BOOL)_invokeResponse:(MTRDeviceResponseValueDictionary)response matchesExpect
return YES;
}

- (void)invokeCommands:(NSArray<NSArray<MTRCommandWithExpectedResult *> *> *)commands
- (void)invokeCommands:(NSArray<NSArray<MTRCommandWithRequiredResponse *> *> *)commands
queue:(dispatch_queue_t)queue
completion:(MTRDeviceResponseHandler)completion
{
Expand All @@ -3361,10 +3361,10 @@ - (void)invokeCommands:(NSArray<NSArray<MTRCommandWithExpectedResult *> *> *)com
// We want to invoke the command groups in order, stopping after failures as needed. Build up a
// linked list of groups via chaining the completions, with calls out to the original
// completion instead of going to the next list item when we want to stop.
for (NSArray<MTRCommandWithExpectedResult *> * commandGroup in [commands reverseObjectEnumerator]) {
for (NSArray<MTRCommandWithRequiredResponse *> * commandGroup in [commands reverseObjectEnumerator]) {
// We want to invoke all the commands in the group in order, propagating along the list of
// current responses. Build up that linked list of command invokes via chaining the completions.
for (MTRCommandWithExpectedResult * command in [commandGroup reverseObjectEnumerator]) {
for (MTRCommandWithRequiredResponse * command in [commandGroup reverseObjectEnumerator]) {
auto commandInvokeBlock = ^(BOOL allSucceededSoFar, NSArray<MTRDeviceResponseValueDictionary> * previousResponses) {
[self invokeCommandWithEndpointID:command.path.endpoint
clusterID:command.path.cluster
Expand Down Expand Up @@ -3394,7 +3394,7 @@ - (void)invokeCommands:(NSArray<NSArray<MTRCommandWithExpectedResult *> *> *)com

BOOL nextAllSucceeded = allSucceededSoFar;
MTRDeviceResponseValueDictionary response = responses[0];
if (command.expectedResult != nil && ![self _invokeResponse:response matchesExpectedResult:command.expectedResult]) {
if (command.requiredResponse != nil && ![self _invokeResponse:response matchesRequiredResponse:command.requiredResponse]) {
nextAllSucceeded = NO;
}

Expand Down
2 changes: 1 addition & 1 deletion src/darwin/Framework/CHIP/MTRDevice_XPC.mm
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ - (void)_invokeCommandWithEndpointID:(NSNumber *)endpointID
}
}

- (void)invokeCommands:(NSArray<NSArray<MTRCommandWithExpectedResult *> *> *)commands
- (void)invokeCommands:(NSArray<NSArray<MTRCommandWithRequiredResponse *> *> *)commands
queue:(dispatch_queue_t)queue
completion:(MTRDeviceResponseHandler)completion
{
Expand Down
2 changes: 1 addition & 1 deletion src/darwin/Framework/CHIP/Matter.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#import <Matter/MTRClusterStateCacheContainer.h>
#import <Matter/MTRClusters.h>
#import <Matter/MTRCommandPayloadsObjc.h>
#import <Matter/MTRCommandWithExpectedResult.h>
#import <Matter/MTRCommandWithRequiredResponse.h>
#import <Matter/MTRCommissionableBrowserDelegate.h>
#import <Matter/MTRCommissionableBrowserResult.h>
#import <Matter/MTRCommissioneeInfo.h>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ MTR_AVAILABLE(ios(18.2), macos(15.2), watchos(11.2), tvos(18.2))
*/
- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID downloadLogOfType:(MTRDiagnosticLogType)type timeout:(NSTimeInterval)timeout completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion;

- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID invokeCommands:(NSArray<NSArray<MTRCommandWithExpectedResult *> *> *)commands completion:(MTRDeviceResponseHandler)completion MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4));
- (oneway void)deviceController:(NSUUID *)controller nodeID:(NSNumber *)nodeID invokeCommands:(NSArray<NSArray<MTRCommandWithRequiredResponse *> *> *)commands completion:(MTRDeviceResponseHandler)completion MTR_AVAILABLE(ios(18.4), macos(15.4), watchos(11.4), tvos(18.4));

@end

Expand Down
Loading

0 comments on commit 87c8e04

Please sign in to comment.