Skip to content

Commit

Permalink
Add read/subscribe event function for darwin (#24057)
Browse files Browse the repository at this point in the history
* Add functions for darwin-framework-tool

Add functions for darwin-framework-tool
-discover commissionables
-pairing ethernet
-read-event-by-id

Added Matter.Framework APIs
MTRDeviceController
-discovercommissionableNodes
-setDeviceDiscoveryDelegate
MTRBaseDevice
-readEventsWithEndpointID

* Remove discovery and ethernet pairing changes

Discovery and ethernet pairing features are useful for test but
not mendatory for Matter certification.
So the removed codes will be committed after more verification.

* Update PairingCommandBridge.mm

* Update ReportCommandBridge.h

* Delete Commands.h

Removed because I think that this file seems not in pull request scope and it can be generated by using commands.zapt in this pull request.

* Rollback Commands.h

Rollback Commands.h to open source version.
I think that this file seems not in pull request scope and
it can be generated by using commands.zapt in this pull request.

* Update MTRDeviceController.h

* Update commands.zapt

Support any cluster for read-event-by-id of darwin-framework-tool

* Add Commands.h to fix zap build error

* Update Commands.h based on the latest version in upstream

* Remove fabric-filtered option in read-event-by-id

* Revert "Update Commands.h based on the latest version in upstream"

This reverts commit 8b80dd2.

* Restyled by whitespace

* Restyled by clang-format

* Restyle zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h

* Update Commands.h to fix zap-related error

* Added subscribeToEventsWithEndpointID

- Added event-min to ReadEvent

* Restyled by clang-format

* Added Read/SubscribeEvent to PowerSourceCluster

* Added BufferedReadClientCallback for both attribte and event

- Used ConcreteClusterPath and ValueId  instead of
  ConcreteAttribute/EventPath
- Removed BufferedReadEventCallback
- Added eventMin to MTRReadParams for EventFilter
- Added isUrgentEvent to MTRSubscribeParams for EventRequest
- Restyled by clang-format

* Modified to support 'any subscribe-event-by-id'

- Checked the invlalid id values are treated as wildcards in both
  subscribeToEventsWithEndpointID and readEventsWithEndpointID.
- Added suggested changes.

* Restyled by clang-format

* Removed the hardcoded true on subscribeWithQeuue

- Removed mEventNumber.SetValue on MTRSubscribeParams
- Added the wildcard handling as nil for Darwin API
- Removed the casts on descriptions

* Revert "Removed the casts on descriptions"

* Restore the mIsUrgentEvent in subscribeWithQueue.

Co-authored-by: Restyled.io <[email protected]>
Co-authored-by: HyunKoo Ryu <[email protected]>
Co-authored-by: ready2die4u <[email protected]>
Co-authored-by: Boris Zbarsky <[email protected]>
  • Loading branch information
5 people authored and pull[bot] committed Nov 7, 2023
1 parent 117830a commit caacc49
Show file tree
Hide file tree
Showing 7 changed files with 546 additions and 48 deletions.
160 changes: 140 additions & 20 deletions examples/darwin-framework-tool/commands/clusters/ReportCommandBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,24 @@ class SubscribeEvent : public ModelCommand {
public:
SubscribeEvent()
: ModelCommand("subscribe-all-events")
{
AddCommonArguments();
}

SubscribeEvent(chip::ClusterId clusterId, bool isClusterAny = false)
: ModelCommand("subscribe-event-by-id")
, mClusterId(clusterId)
{
if (isClusterAny == true) {
AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId);
}
AddArgument("event-id", 0, UINT32_MAX, &mEventId);
AddArgument("event-min", 0, UINT64_MAX, &mEventNumber);
AddArgument("is-urgent", 0, 1, &mIsUrgent);
AddCommonArguments();
}

void AddCommonArguments()
{
AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval);
AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval);
Expand All @@ -199,34 +217,61 @@ class SubscribeEvent : public ModelCommand {
dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);

MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
if (mEventNumber.HasValue()) {
params.minimumEventNumber = [NSNumber numberWithUnsignedLongLong:mEventNumber.Value()];
}
if (mKeepSubscriptions.HasValue()) {
params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
}
if (mIsUrgent.HasValue()) {
params.reportEventsUrgently = mIsUrgent.Value();
}
if (mAutoResubscribe.HasValue()) {
params.resubscribeIfLost = mAutoResubscribe.Value();
}

[device subscribeWithQueue:callbackQueue
params:params
clusterStateCacheContainer:nil
attributeReportHandler:^(NSArray * value) {
SetCommandExitStatus(CHIP_NO_ERROR);
}
eventReportHandler:^(NSArray * value) {
for (id item in value) {
NSLog(@"Response Item: %@", [item description]);
if (strcmp(GetName(), "subscribe-event-by-id") == 0) {
[device subscribeToEventsWithEndpointID:(endpointId == chip::kInvalidEndpointId)
? nil
: [NSNumber numberWithUnsignedShort:endpointId]
clusterID:(mClusterId == chip::kInvalidClusterId) ? nil : [NSNumber numberWithUnsignedInteger:mClusterId]
eventID:(mEventId == chip::kInvalidEventId) ? nil : [NSNumber numberWithUnsignedInteger:mEventId]
params:params
queue:callbackQueue
reportHandler:^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
if (values) {
for (id item in values) {
NSLog(@"Response Item: %@", [item description]);
}
}
SetCommandExitStatus(error);
}
SetCommandExitStatus(CHIP_NO_ERROR);
}
errorHandler:^(NSError * error) {
SetCommandExitStatus(error);
}
subscriptionEstablished:^() {
mSubscriptionEstablished = YES;
}
resubscriptionScheduled:^(NSError * error, NSNumber * resubscriptionDelay) {
NSLog(@"Subscription dropped with error %@. Resubscription in %@ms", error, resubscriptionDelay);
}];
subscriptionEstablished:^() {
mSubscriptionEstablished = YES;
}];
} else {
[device subscribeWithQueue:callbackQueue
params:params
clusterStateCacheContainer:nil
attributeReportHandler:^(NSArray * value) {
SetCommandExitStatus(CHIP_NO_ERROR);
}
eventReportHandler:^(NSArray * value) {
for (id item in value) {
NSLog(@"Response Item: %@", [item description]);
}
SetCommandExitStatus(CHIP_NO_ERROR);
}
errorHandler:^(NSError * error) {
SetCommandExitStatus(error);
}
subscriptionEstablished:^() {
mSubscriptionEstablished = YES;
}
resubscriptionScheduled:^(NSError * error, NSNumber * resubscriptionDelay) {
NSLog(@"Subscription dropped with error %@. Resubscription in %@ms", error, resubscriptionDelay);
}];
}

return CHIP_NO_ERROR;
}
Expand All @@ -237,7 +282,82 @@ class SubscribeEvent : public ModelCommand {
chip::Optional<bool> mKeepSubscriptions;
chip::Optional<bool> mAutoResubscribe;
chip::Optional<chip::EventNumber> mEventNumber;
chip::Optional<bool> mIsUrgent;
bool mSubscriptionEstablished = NO;
uint16_t mMinInterval;
uint16_t mMaxInterval;

void Shutdown() override
{
mSubscriptionEstablished = NO;
ModelCommand::Shutdown();
}

bool DeferInteractiveCleanup() override { return mSubscriptionEstablished; }

private:
chip::ClusterId mClusterId;
chip::EventId mEventId;
};

class ReadEvent : public ModelCommand {
public:
ReadEvent()
: ModelCommand("read-event-by-id")
{
AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId);
AddArgument("event-id", 0, UINT32_MAX, &mEventId);
AddArgument("event-min", 0, UINT64_MAX, &mEventNumber);
ModelCommand::AddArguments();
}

ReadEvent(chip::ClusterId clusterId)
: ModelCommand("read-event-by-id")
, mClusterId(clusterId)
{
AddArgument("event-id", 0, UINT32_MAX, &mEventId);
AddArgument("event-min", 0, UINT64_MAX, &mEventNumber);
ModelCommand::AddArguments();
}

~ReadEvent() {}

CHIP_ERROR SendCommand(MTRBaseDevice * _Nonnull device, chip::EndpointId endpointId) override
{
dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
MTRReadParams * params = [[MTRReadParams alloc] init];
if (mFabricFiltered.HasValue()) {
params.filterByFabric = mFabricFiltered.Value();
}
if (mEventNumber.HasValue()) {
params.minimumEventNumber = [NSNumber numberWithUnsignedLongLong:mEventNumber.Value()];
}

[device
readEventsWithEndpointID:(endpointId == chip::kInvalidEndpointId) ? nil : [NSNumber numberWithUnsignedShort:endpointId]
clusterID:(mClusterId == chip::kInvalidClusterId) ? nil : [NSNumber numberWithUnsignedInteger:mClusterId]
eventID:(mEventId == chip::kInvalidEventId) ? nil : [NSNumber numberWithUnsignedInteger:mEventId]
params:params
queue:callbackQueue
completion:^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
if (error != nil) {
LogNSError("Error reading event", error);
}
if (values) {
for (id item in values) {
NSLog(@"Response Item: %@", [item description]);
}
}
SetCommandExitStatus(error);
}];
return CHIP_NO_ERROR;
}

protected:
chip::Optional<bool> mFabricFiltered;
chip::Optional<chip::EventNumber> mEventNumber;

private:
chip::ClusterId mClusterId;
chip::AttributeId mEventId;
};
8 changes: 8 additions & 0 deletions examples/darwin-framework-tool/templates/commands.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,12 @@ void registerCluster{{asUpperCamelCase name}}(Commands & commands)
{{/if}}
{{/unless}}
{{/chip_server_cluster_attributes}}
{{#zcl_events}}
{{#first}}
make_unique<ReadEvent>(Id), //
make_unique<SubscribeEvent>(Id), //
{{/first}}
{{/zcl_events}}
};

commands.Register(clusterName, clusterCommands);
Expand All @@ -308,6 +314,8 @@ void registerClusterAny(Commands & commands)
make_unique<ReadAttribute>(), //
make_unique<WriteAttribute>(), //
make_unique<SubscribeAttribute>(), //
make_unique<ReadEvent>(), //
make_unique<SubscribeEvent>(chip::kInvalidClusterId, true), //
make_unique<SubscribeEvent>(), //
};

Expand Down
41 changes: 41 additions & 0 deletions src/darwin/Framework/CHIP/MTRBaseDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,47 @@ typedef NS_ENUM(uint8_t, MTRTransportType) {
completion:(MTRDeviceOpenCommissioningWindowHandler)completion
API_AVAILABLE(ios(16.2), macos(13.1), watchos(9.2), tvos(16.2));

/**
* Reads events from the device.
*
* Nil values for endpointID, clusterID, eventID indicate wildcards
* (e.g. nil eventID means "read all the events from the endpoint(s) and
* cluster(s) that match endpointID/clusterID").
*
* If all of endpointID, clusterID, eventID are non-nil, all the matching instances of a single
* event will be read.
*
* If all of endpointID, clusterID, eventID are nil, all events on the
* device will be read.
*/

- (void)readEventsWithEndpointID:(NSNumber * _Nullable)endpointID
clusterID:(NSNumber * _Nullable)clusterID
eventID:(NSNumber * _Nullable)eventID
params:(MTRReadParams * _Nullable)params
queue:(dispatch_queue_t)queue
completion:(MTRDeviceResponseHandler)completion MTR_NEWLY_AVAILABLE;

/**
* Subscribes to the specified events on the device.
*
* Nil values for endpointID, clusterID, eventID indicate wildcards
* (e.g. nil eventID means "subscribe to all the events from the
* endpoint(s) and cluster(s) that match endpointID/clusterID").
*
* If all of endpointID, clusterID, eventID are non-nil, a single event
* will be subscribed to.
*
* If all of endpointID, clusterID, eventID are nil, all events on the
* device will be subscribed to.
*/
- (void)subscribeToEventsWithEndpointID:(NSNumber * _Nullable)endpointID
clusterID:(NSNumber * _Nullable)clusterID
eventID:(NSNumber * _Nullable)eventID
params:(MTRSubscribeParams * _Nullable)params
queue:(dispatch_queue_t)queue
reportHandler:(MTRDeviceResponseHandler)reportHandler
subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished MTR_NEWLY_AVAILABLE;
@end

/**
Expand Down
Loading

0 comments on commit caacc49

Please sign in to comment.