Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement MTRBaseCluster invokes on top of MTRBaseDevice. #29554

Merged
merged 3 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 0 additions & 36 deletions src/darwin/Framework/CHIP/MTRBaseClusterUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -392,40 +392,4 @@ class MTRInvokeCallback : public chip::app::CommandSender::Callback {
bool mCalledCallback = false;
};

/**
* timedInvokeTimeoutMs, if provided, is how long the server will wait for us to
* send the invoke after we sent the Timed Request message.
*
* invokeTimeout, if provided, will have possible MRP latency added to it and
* the result is how long we will wait for the server to respond.
*/
template <typename BridgeType, typename RequestDataType>
CHIP_ERROR MTRStartInvokeInteraction(BridgeType * _Nonnull bridge, const RequestDataType & requestData,
chip::Messaging::ExchangeManager & exchangeManager, const chip::SessionHandle & session,
typename BridgeType::SuccessCallbackType successCb, MTRErrorCallback failureCb, chip::EndpointId endpoint,
chip::Optional<uint16_t> timedInvokeTimeoutMs, chip::Optional<chip::System::Clock::Timeout> invokeTimeout)
{
auto callback = chip::Platform::MakeUnique<MTRInvokeCallback<BridgeType, typename RequestDataType::ResponseType>>(
bridge, successCb, failureCb);
VerifyOrReturnError(callback != nullptr, CHIP_ERROR_NO_MEMORY);

auto commandSender
= chip::Platform::MakeUnique<chip::app::CommandSender>(callback.get(), &exchangeManager, timedInvokeTimeoutMs.HasValue());
VerifyOrReturnError(commandSender != nullptr, CHIP_ERROR_NO_MEMORY);

chip::app::CommandPathParams commandPath(endpoint, 0, RequestDataType::GetClusterId(), RequestDataType::GetCommandId(),
chip::app::CommandPathFlags::kEndpointIdValid);
ReturnErrorOnFailure(commandSender->AddRequestData(commandPath, requestData, timedInvokeTimeoutMs));

if (invokeTimeout.HasValue()) {
invokeTimeout.SetValue(session->ComputeRoundTripTimeout(invokeTimeout.Value()));
}
ReturnErrorOnFailure(commandSender->SendCommandRequest(session, invokeTimeout));

callback->AdoptCommandSender(std::move(commandSender));
callback.release();

return CHIP_NO_ERROR;
};

NS_ASSUME_NONNULL_END
49 changes: 49 additions & 0 deletions src/darwin/Framework/CHIP/MTRBaseDevice.mm
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#import "MTRSetupPayload_Internal.h"
#import "NSDataSpanConversion.h"
#import "NSStringSpanConversion.h"
#import "zap-generated/MTRCommandPayloads_Internal.h"

#include "app/ConcreteAttributePath.h"
#include "app/ConcreteCommandPath.h"
Expand Down Expand Up @@ -1308,6 +1309,54 @@ - (void)_invokeCommandWithEndpointID:(NSNumber *)endpointID
std::move(*bridge).DispatchAction(self);
}

- (void)_invokeKnownCommandWithEndpointID:(NSNumber *)endpointID
clusterID:(NSNumber *)clusterID
commandID:(NSNumber *)commandID
commandPayload:(id)commandPayload
timedInvokeTimeout:(NSNumber * _Nullable)timeout
serverSideProcessingTimeout:(NSNumber * _Nullable)serverSideProcessingTimeout
responseClass:(Class _Nullable)responseClass
queue:(dispatch_queue_t)queue
completion:(void (^)(id _Nullable response, NSError * _Nullable error))completion
{
if (![commandPayload respondsToSelector:@selector(_encodeAsDataValue:)]) {
bzbarsky-apple marked this conversation as resolved.
Show resolved Hide resolved
dispatch_async(queue, ^{
completion(nil, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_ARGUMENT]);
});
return;
}

NSError * encodingError;
auto * commandFields = [commandPayload _encodeAsDataValue:&encodingError];
if (commandFields == nil) {
dispatch_async(queue, ^{
completion(nil, encodingError);
});
return;
}

auto responseHandler = ^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
id _Nullable response = nil;
if (error == nil) {
if (values.count != 1) {
error = [NSError errorWithDomain:MTRErrorDomain code:MTRErrorCodeSchemaMismatch userInfo:nil];
} else if (responseClass != nil) {
response = [[responseClass alloc] initWithResponseValue:values[0] error:&error];
}
}
completion(response, error);
};

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

- (void)subscribeToAttributesWithEndpointID:(NSNumber * _Nullable)endpointID
clusterID:(NSNumber * _Nullable)clusterID
attributeID:(NSNumber * _Nullable)attributeID
Expand Down
18 changes: 18 additions & 0 deletions src/darwin/Framework/CHIP/MTRBaseDevice_Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,24 @@ static inline MTRTransportType MTRMakeTransportType(chip::Transport::Type type)
queue:(dispatch_queue_t)queue
completion:(MTRDeviceResponseHandler)completion;

/**
* Like the public invokeCommandWithEndpointID but:
*
* 1) Allows passing through a serverSideProcessingTimeout.
* 2) Expects one of the command payload structs as commandPayload
* 3) On success, returns an instance of responseClass via the completion (or
* nil if there is no responseClass, which indicates a status-only command).
*/
- (void)_invokeKnownCommandWithEndpointID:(NSNumber *)endpointID
clusterID:(NSNumber *)clusterID
commandID:(NSNumber *)commandID
commandPayload:(id)commandPayload
timedInvokeTimeout:(NSNumber * _Nullable)timeout
serverSideProcessingTimeout:(NSNumber * _Nullable)serverSideProcessingTimeout
responseClass:(Class _Nullable)responseClass
queue:(dispatch_queue_t)queue
completion:(void (^)(id _Nullable response, NSError * _Nullable error))completion;

@end

@interface MTRClusterPath ()
Expand Down
86 changes: 32 additions & 54 deletions src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#import "NSStringSpanConversion.h"
#import "NSDataSpanConversion.h"

#include <app-common/zap-generated/cluster-objects.h>
#include <controller/CHIPCluster.h>
#include <lib/support/CHIPListUtils.h>
#include <platform/CHIPDeviceLayer.h>
Expand Down Expand Up @@ -53,7 +54,6 @@ using chip::System::Clock::Seconds16;
{{! This is used as the implementation for both the new-name and old-name bits, so check for both here. }}
{{#if (or (isSupported cluster command=command)
(isSupported (compatClusterNameRemapping parent.name) command=(compatCommandNameRemapping parent.name name)))}}
{{#*inline "callbackName"}}{{#if hasSpecificResponse}}{{cluster}}Cluster{{asUpperCamelCase responseName preserveAcronyms=true}}{{else}}CommandSuccess{{/if}}{{/inline}}
{{#*inline "paramsType"}}
{{#unless (isSupported cluster command=command)}}
MTR{{compatClusterNameRemapping parent.name}}Cluster{{compatCommandNameRemapping parent.name name}}Params
Expand All @@ -69,61 +69,39 @@ MTR{{cluster}}Cluster{{command}}Params
{{/unless}}
- (void){{asLowerCamelCase name}}WithParams: ({{> paramsType}} * {{#unless commandHasRequiredField}}_Nullable{{/unless}})params completion:({{>command_completion_type command=.}})completion
{
// Make a copy of params before we go async.
params = [params copy];
auto * bridge = new MTR{{>callbackName}}CallbackBridge(self.callbackQueue,
{{#if hasSpecificResponse}}
{{! This treats completion as taking an id for the data. This is
not great from a type-safety perspective, of course. }}
completion,
{{else}}
{{! For now, don't change the bridge API; instead just use an adapter
to invoke our completion handler. This is not great from a
type-safety perspective, of course. }}
^(id _Nullable value, NSError * _Nullable error) {
completion(error);
},
{{/if}}
^(ExchangeManager & exchangeManager, const SessionHandle & session, {{>callbackName}}CallbackType successCb, MTRErrorCallback failureCb, MTRCallbackBridgeBase * bridge) {
auto * typedBridge = static_cast<MTR{{>callbackName}}CallbackBridge *>(bridge);
Optional<uint16_t> timedInvokeTimeoutMs;
Optional<Timeout> invokeTimeout;
ListFreer listFreer;
{{asUpperCamelCase parent.name}}::Commands::{{asUpperCamelCase name}}::Type request;
if (params != nil) {
if (params.timedInvokeTimeoutMs != nil) {
params.timedInvokeTimeoutMs = MTRClampedNumber(params.timedInvokeTimeoutMs, @(1), @(UINT16_MAX));
timedInvokeTimeoutMs.SetValue(params.timedInvokeTimeoutMs.unsignedShortValue);
}
if (params.serverSideProcessingTimeout != nil) {
// Clamp to a number of seconds that will not overflow 32-bit
// int when converted to ms.
auto * serverSideProcessingTimeout = MTRClampedNumber(params.serverSideProcessingTimeout, @(0), @(UINT16_MAX));
invokeTimeout.SetValue(Seconds16(serverSideProcessingTimeout.unsignedShortValue));
}
}
{{#if mustUseTimedInvoke}}
if (!timedInvokeTimeoutMs.HasValue()) {
timedInvokeTimeoutMs.SetValue(10000);
}
if (params == nil) {
params = [[{{> paramsType}} alloc] init];
}

auto responseHandler = ^(id _Nullable response, NSError * _Nullable error) {
{{#if hasSpecificResponse}}
completion(response, error);
{{else}}
completion(error);
{{/if}}
{{#zcl_command_arguments}}
{{#first}}
{{#unless parent.commandHasRequiredField}}
if (params != nil) {
{{/unless}}
{{/first}}
{{>encode_value target=(concat "request." (asLowerCamelCase label)) source=(concat "params." (asStructPropertyName label)) cluster=parent.parent.name errorCode="return CHIP_ERROR_INVALID_ARGUMENT;" depth=0}}
{{#last}}
{{#unless parent.commandHasRequiredField}}
}
{{/unless}}
{{/last}}
{{/zcl_command_arguments}}
};

return MTRStartInvokeInteraction(typedBridge, request, exchangeManager, session, successCb, failureCb, self.endpoint, timedInvokeTimeoutMs, invokeTimeout);
});
std::move(*bridge).DispatchAction(self.device);
auto * timedInvokeTimeoutMs = params.timedInvokeTimeoutMs;
{{#if mustUseTimedInvoke}}
if (timedInvokeTimeoutMs == nil) {
timedInvokeTimeoutMs = @(10000);
}
{{/if}}

using RequestType = {{asUpperCamelCase parent.name}}::Commands::{{asUpperCamelCase name}}::Type;
[self.device _invokeKnownCommandWithEndpointID:@(self.endpoint)
clusterID:@(RequestType::GetClusterId())
commandID:@(RequestType::GetCommandId())
commandPayload:params
timedInvokeTimeout:timedInvokeTimeoutMs
serverSideProcessingTimeout:params.serverSideProcessingTimeout
{{#if hasSpecificResponse}}
responseClass:MTR{{cluster}}Cluster{{asUpperCamelCase responseName preserveAcronyms=true}}Params.class
{{else}}
responseClass:nil
{{/if}}
queue:self.callbackQueue
completion:responseHandler];
}
{{/if}}
{{/inline}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <lib/support/TypeTraits.h>

{{#>MTRCallbackBridge partial-type="Status" }}DefaultSuccessCallback{{/MTRCallbackBridge}}
{{#>MTRCallbackBridge partial-type="CommandStatus" }}CommandSuccessCallback{{/MTRCallbackBridge}}
{{#>MTRCallbackBridge type="Octet_String" isNullable=false ns="chip"}}OctetStringAttributeCallback{{/MTRCallbackBridge}}
{{#>MTRCallbackBridge type="Octet_String" isNullable=true ns="chip"}}NullableOctetStringAttributeCallback{{/MTRCallbackBridge}}
{{#>MTRCallbackBridge type="Char_String" isNullable=false ns="chip"}}CharStringAttributeCallback{{/MTRCallbackBridge}}
Expand Down Expand Up @@ -57,14 +56,6 @@
{{/zcl_attributes_server}}
{{/zcl_clusters}}

{{#zcl_clusters}}
{{#zcl_command_responses}}
{{#if (isSupported (asUpperCamelCase ../name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true))}}
{{#>MTRCallbackBridge partial-type="Command" }}{{asUpperCamelCase ../../name preserveAcronyms=true}}Cluster{{asUpperCamelCase ../name preserveAcronyms=true}}Callback{{/MTRCallbackBridge}}
{{/if}}
{{/zcl_command_responses}}
{{/zcl_clusters}}

{{#zcl_clusters}}
{{#zcl_enums}}
{{#if (isSupported (asUpperCamelCase parent.name preserveAcronyms=true) enum=(asUpperCamelCase name preserveAcronyms=true))}}
Expand Down
19 changes: 0 additions & 19 deletions src/darwin/Framework/CHIP/templates/MTRCallbackBridge.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,11 @@
#include <app/util/im-client-callbacks.h>
#include <app-common/zap-generated/cluster-objects.h>

typedef void (*CommandSuccessCallback)(void *, const chip::app::DataModel::NullObjectType &);
using CommandSuccessCallbackType = CommandSuccessCallback;
typedef void (*DefaultSuccessCallbackType)(void *);

typedef void (*VendorIdAttributeCallback)(void *, chip::VendorId);
typedef void (*NullableVendorIdAttributeCallback)(void *, const chip::app::DataModel::Nullable<chip::VendorId> &);

{{#zcl_clusters}}
{{#zcl_command_responses}}
{{#if (isSupported (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true))}}
typedef void (*{{asUpperCamelCase parent.name preserveAcronyms=true}}Cluster{{asUpperCamelCase name preserveAcronyms=true}}CallbackType)(void *, const chip::app::Clusters::{{asUpperCamelCase parent.name}}::Commands::{{asUpperCamelCase name}}::DecodableType &);
{{/if}}
{{/zcl_command_responses}}
{{/zcl_clusters}}

{{#zcl_clusters}}
{{#zcl_enums}}
{{#if (isSupported (asUpperCamelCase parent.name preserveAcronyms=true) enum=(asUpperCamelCase name preserveAcronyms=true))}}
Expand Down Expand Up @@ -50,7 +40,6 @@ typedef void (*{{asUpperCamelCase parent.name preserveAcronyms=true}}{{asUpperCa
{{/zcl_clusters}}

{{#>MTRCallbackBridge header="1" partial-type="Status" }}DefaultSuccessCallback{{/MTRCallbackBridge}}
{{#>MTRCallbackBridge header="1" partial-type="CommandStatus" }}CommandSuccessCallback{{/MTRCallbackBridge}}
{{#>MTRCallbackBridge header="1" type="Octet_String" isNullable=false ns="chip"}}OctetStringAttributeCallback{{/MTRCallbackBridge}}
{{#>MTRCallbackBridge header="1" type="Octet_String" isNullable=true ns="chip"}}NullableOctetStringAttributeCallback{{/MTRCallbackBridge}}
{{#>MTRCallbackBridge header="1" type="Char_String" isNullable=false ns="chip"}}CharStringAttributeCallback{{/MTRCallbackBridge}}
Expand Down Expand Up @@ -97,14 +86,6 @@ typedef void (*{{asUpperCamelCase parent.name preserveAcronyms=true}}{{asUpperCa
{{/zcl_attributes_server}}
{{/zcl_clusters}}

{{#zcl_clusters}}
{{#zcl_command_responses}}
{{#if (isSupported (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true))}}
{{#>MTRCallbackBridge header="1" partial-type="Command" provisional=(isProvisional (asUpperCamelCase parent.name preserveAcronyms=true) command=(asUpperCamelCase name preserveAcronyms=true))}}{{asUpperCamelCase ../../name preserveAcronyms=true}}Cluster{{asUpperCamelCase ../name preserveAcronyms=true}}Callback{{/MTRCallbackBridge}}
{{/if}}
{{/zcl_command_responses}}
{{/zcl_clusters}}

{{#zcl_clusters}}
{{#zcl_enums}}
{{#if (isSupported (asUpperCamelCase parent.name preserveAcronyms=true) enum=(asUpperCamelCase name preserveAcronyms=true))}}
Expand Down
21 changes: 5 additions & 16 deletions src/darwin/Framework/CHIP/templates/MTRClusters-src.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
#import "MTRCommandPayloadsObjc.h"
#import "MTRLogging_Internal.h"

#include <app-common/zap-generated/cluster-objects.h>
#include <platform/CHIPDeviceLayer.h>

#include <type_traits>

using chip::Callback::Callback;
Expand Down Expand Up @@ -54,20 +56,6 @@ MTR{{compatClusterNameRemapping parent.name}}Cluster{{compatCommandNameRemapping
MTR{{cluster}}Cluster{{command}}Params
{{/unless}}
{{/inline}}
{{#*inline "clusterId"}}
{{#unless (isSupported cluster command=command)}}
{{asMEI ../manufacturerCode ../code}}
{{else}}
MTRClusterIDType{{cluster}}ID
{{/unless}}
{{/inline}}
{{#*inline "commandId"}}
{{#unless (isSupported cluster command=command)}}
{{asMEI manufacturerCode code}}
{{else}}
MTRCommandIDTypeCluster{{cluster}}Command{{command}}ID
{{/unless}}
{{/inline}}
{{#unless hasArguments}}
- (void){{asLowerCamelCase name}}WithExpectedValues:(NSArray<NSDictionary<NSString *, id> *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completion:({{>command_completion_type command=.}})completion
{
Expand Down Expand Up @@ -95,9 +83,10 @@ MTRCommandIDTypeCluster{{cluster}}Command{{command}}ID
}
{{/if}}

using RequestType = {{asUpperCamelCase parent.name}}::Commands::{{asUpperCamelCase name}}::Type;
[self.device _invokeKnownCommandWithEndpointID:@(self.endpoint)
clusterID:@({{> clusterId}})
commandID:@({{> commandId}})
clusterID:@(RequestType::GetClusterId())
commandID:@(RequestType::GetCommandId())
commandPayload:params
expectedValues:expectedValues
expectedValueInterval:expectedValueIntervalMs
Expand Down
Loading