Skip to content

Commit

Permalink
Turn on auto-resubscribe for Darwin wildcard subscriptions. (#16201)
Browse files Browse the repository at this point in the history
We weren't doing it before, but should do it.
  • Loading branch information
bzbarsky-apple authored and pull[bot] committed Dec 7, 2023
1 parent 200181e commit 2932681
Show file tree
Hide file tree
Showing 9 changed files with 6,208 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ - (void)reportFromUserEnteredSettings
[chipDevice subscribeWithQueue:dispatch_get_main_queue()
minInterval:minIntervalSeconds
maxInterval:maxIntervalSeconds
params:nil
reportHandler:^(NSArray<CHIPAttributeReport *> * _Nullable reports, NSError * _Nullable error) {
if (error) {
NSLog(@"Status: update reportAttributeMeasuredValue completed with error %@",
Expand Down
14 changes: 14 additions & 0 deletions src/darwin/Framework/CHIP/CHIPCluster.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,20 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (strong, nonatomic, nullable) NSNumber * keepPreviousSubscriptions;

/**
* Whether the subscription should automatically try to re-establish if it
* drops. nil (the default value) is treated as YES.
*
* If NO, loss of subscription will simply lead to an error report. Some
* subscription APIs do not support this value.
*
* If YES, loss of subscription will lead to an automatic resubscription
* attempt. If this succeeds, the subscriptionEstablished callback will be
* called again.
*
*/
@property (strong, nonatomic, nullable) NSNumber * autoResubscribe;

- (instancetype)init;
@end

Expand Down
1 change: 1 addition & 0 deletions src/darwin/Framework/CHIP/CHIPCluster.mm
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ - (instancetype)init
{
if (self = [super init]) {
_keepPreviousSubscriptions = nil;
_autoResubscribe = nil;
}
return self;
}
Expand Down
6 changes: 5 additions & 1 deletion src/darwin/Framework/CHIP/CHIPDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

#import <Foundation/Foundation.h>

@class CHIPSubscribeParams;

NS_ASSUME_NONNULL_BEGIN

typedef void (^CHIPDeviceResponseHandler)(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error);
Expand Down Expand Up @@ -65,13 +67,15 @@ extern NSString * const kCHIPStatusKey;
*
* subscriptionEstablished block, if not nil, will be called once the
* subscription is established. This will be _after_ the first (priming) call
* to reportHandler.
* to reportHandler. Note that if the CHIPSubscribeParams are set to
* automatically resubscribe this can end up being called more than once.
*
* TODO: The "all events" part does not work yet.
*/
- (void)subscribeWithQueue:(dispatch_queue_t)queue
minInterval:(uint16_t)minInterval
maxInterval:(uint16_t)maxInterval
params:(nullable CHIPSubscribeParams *)params
reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler
subscriptionEstablished:(nullable void (^)(void))subscriptionEstablishedHandler;

Expand Down
52 changes: 43 additions & 9 deletions src/darwin/Framework/CHIP/CHIPDevice.mm
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ - (instancetype)initWithDevice:(chip::DeviceProxy *)device

void OnDone() override;

void OnDeallocatePaths(ReadPrepareParams && aReadPrepareParams) override;

void OnSubscriptionEstablished(uint64_t aSubscriptionId) override;

void ReportError(CHIP_ERROR err);
Expand Down Expand Up @@ -274,6 +276,7 @@ - (instancetype)initWithDevice:(chip::DeviceProxy *)device
- (void)subscribeWithQueue:(dispatch_queue_t)queue
minInterval:(uint16_t)minInterval
maxInterval:(uint16_t)maxInterval
params:(nullable CHIPSubscribeParams *)params
reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler
subscriptionEstablished:(nullable void (^)(void))subscriptionEstablishedHandler
{
Expand All @@ -284,18 +287,30 @@ - (void)subscribeWithQueue:(dispatch_queue_t)queue
});
return;
}
AttributePathParams attributePath; // Wildcard endpoint, cluster, attribute.
ReadPrepareParams params(device->GetSecureSession().Value());
params.mMinIntervalFloorSeconds = minInterval;
params.mMaxIntervalCeilingSeconds = maxInterval;
params.mpAttributePathParamsList = &attributePath;
params.mAttributePathParamsListSize = 1;

// Wildcard endpoint, cluster, attribute.
auto attributePath = std::make_unique<AttributePathParams>();
ReadPrepareParams readParams(device->GetSecureSession().Value());
readParams.mMinIntervalFloorSeconds = minInterval;
readParams.mMaxIntervalCeilingSeconds = maxInterval;
readParams.mpAttributePathParamsList = attributePath.get();
readParams.mAttributePathParamsListSize = 1;
readParams.mKeepSubscriptions
= (params != nil) && (params.keepPreviousSubscriptions != nil) && [params.keepPreviousSubscriptions boolValue];

auto callback = std::make_unique<SubscriptionCallback>(queue, reportHandler, subscriptionEstablishedHandler);
auto readClient = std::make_unique<ReadClient>(InteractionModelEngine::GetInstance(), device->GetExchangeManager(),
callback->GetBufferedCallback(), ReadClient::InteractionType::Subscribe);

CHIP_ERROR err = readClient->SendRequest(params);
CHIP_ERROR err;
if (params != nil && params.autoResubscribe != nil && ![params.autoResubscribe boolValue]) {
err = readClient->SendRequest(readParams);
} else {
// SendAutoResubscribeRequest cleans up the params, even on failure.
attributePath.release();
err = readClient->SendAutoResubscribeRequest(std::move(readParams));
}

if (err != CHIP_NO_ERROR) {
dispatch_async(queue, ^{
reportHandler(nil, [CHIPError errorForCHIPErrorCode:err]);
Expand Down Expand Up @@ -1266,12 +1281,31 @@ - (instancetype)initWithPath:(const ConcreteDataAttributePath &)path value:(null
}
}

void SubscriptionCallback::OnDeallocatePaths(ReadPrepareParams && aReadPrepareParams)
{
VerifyOrDie((aReadPrepareParams.mAttributePathParamsListSize == 0 && aReadPrepareParams.mpAttributePathParamsList == nullptr)
|| (aReadPrepareParams.mAttributePathParamsListSize == 1 && aReadPrepareParams.mpAttributePathParamsList != nullptr));
if (aReadPrepareParams.mpAttributePathParamsList) {
delete aReadPrepareParams.mpAttributePathParamsList;
}

VerifyOrDie((aReadPrepareParams.mDataVersionFilterListSize == 0 && aReadPrepareParams.mpDataVersionFilterList == nullptr)
|| (aReadPrepareParams.mDataVersionFilterListSize == 1 && aReadPrepareParams.mpDataVersionFilterList != nullptr));
if (aReadPrepareParams.mpDataVersionFilterList != nullptr) {
delete aReadPrepareParams.mpDataVersionFilterList;
}

VerifyOrDie((aReadPrepareParams.mEventPathParamsListSize == 0 && aReadPrepareParams.mpEventPathParamsList == nullptr)
|| (aReadPrepareParams.mEventPathParamsListSize == 1 && aReadPrepareParams.mpEventPathParamsList != nullptr));
if (aReadPrepareParams.mpEventPathParamsList) {
delete aReadPrepareParams.mpEventPathParamsList;
}
}

void SubscriptionCallback::OnSubscriptionEstablished(uint64_t aSubscriptionId)
{
if (mSubscriptionEstablishedHandler) {
dispatch_async(mQueue, mSubscriptionEstablishedHandler);
// Don't need it anymore.
mSubscriptionEstablishedHandler = nil;
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/darwin/Framework/CHIP/templates/CHIPClustersObjc-src.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ subscriptionEstablished:(SubscriptionEstablishedHandler _Nullable)subscriptionEs
not great from a type-safety perspective, of course. }}
reportHandler,
^(Cancelable * success, Cancelable * failure) {
if (params != nil && params.autoResubscribe != nil && ![params.autoResubscribe boolValue]) {
// We don't support disabling auto-resubscribe.
return CHIP_ERROR_INVALID_ARGUMENT;
}
using TypeInfo = {{asUpperCamelCase parent.name}}::Attributes::{{asUpperCamelCase name}}::TypeInfo;
auto successFn = Callback<{{>attribute_data_callback_name}}Callback>::FromCancelable(success);
auto failureFn = Callback<CHIPDefaultFailureCallbackType>::FromCancelable(failure);
Expand Down
4 changes: 4 additions & 0 deletions src/darwin/Framework/CHIP/templates/CHIPClustersObjc.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ NS_ASSUME_NONNULL_BEGIN
- (void)write{{>attribute}}WithValue:({{asObjectiveCType type parent.name}})value completionHandler:(StatusCompletion)completionHandler;
{{/if}}
{{#if isReportableAttribute}}
/**
* This API does not support setting autoResubscribe to NO in the
* CHIPSubscribeParams.
*/
- (void) subscribe{{>attribute}}WithMinInterval:(NSNumber * _Nonnull)minInterval maxInterval:(NSNumber * _Nonnull)maxInterval
params:(CHIPSubscribeParams * _Nullable)params
subscriptionEstablished:(SubscriptionEstablishedHandler _Nullable)subscriptionEstablishedHandler reportHandler:(void (^)({{asObjectiveCClass type parent.name}} * _Nullable value, NSError * _Nullable error))reportHandler;
Expand Down
Loading

0 comments on commit 2932681

Please sign in to comment.