Skip to content

Commit

Permalink
[Darwin] Add OTA Provider Delegate Bridge implementation (#20516)
Browse files Browse the repository at this point in the history
  • Loading branch information
carol-apple authored and pull[bot] committed Feb 8, 2024
1 parent 839baf6 commit 1542514
Show file tree
Hide file tree
Showing 3 changed files with 257 additions and 1 deletion.
16 changes: 16 additions & 0 deletions src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,22 @@ class MTROTAProviderDelegateBridge : public chip::app::Clusters::OTAProviderDele
const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::NotifyUpdateApplied::DecodableType & commandData) override;

private:
void ConvertToQueryImageParams(
const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImage::DecodableType & commandData,
MTROtaSoftwareUpdateProviderClusterQueryImageParams * commandParams);
void ConvertFromQueryImageResponseParms(
const MTROtaSoftwareUpdateProviderClusterQueryImageResponseParams * responseParams,
chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImageResponse::Type & response);
void ConvertToApplyUpdateRequestParams(
const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::ApplyUpdateRequest::DecodableType & commandData,
MTROtaSoftwareUpdateProviderClusterApplyUpdateRequestParams * commandParams);
void ConvertFromApplyUpdateRequestResponseParms(
const MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * responseParams,
chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::ApplyUpdateResponse::Type & response);
void ConvertToNotifyUpdateAppliedParams(
const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::NotifyUpdateApplied::DecodableType & commandData,
MTROtaSoftwareUpdateProviderClusterNotifyUpdateAppliedParams * commandParams);

_Nullable id<MTROTAProviderDelegate> mDelegate;
_Nullable dispatch_queue_t mQueue;
};
Expand Down
236 changes: 236 additions & 0 deletions src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
/**
*
* Copyright (c) 2022 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import "MTROTAProviderDelegateBridge.h"

#include <app/clusters/ota-provider/ota-provider.h>

static NSInteger const kOtaProviderEndpoint = 0;

MTROTAProviderDelegateBridge::MTROTAProviderDelegateBridge(void)
: mDelegate(nil)
{
}

MTROTAProviderDelegateBridge::~MTROTAProviderDelegateBridge(void) {}

void MTROTAProviderDelegateBridge::setDelegate(id<MTROTAProviderDelegate> delegate, dispatch_queue_t queue)
{
if (delegate && queue) {
mDelegate = delegate;
mQueue = queue;
} else {
mDelegate = nil;
mQueue = nil;
}

chip::app::Clusters::OTAProvider::SetDelegate(kOtaProviderEndpoint, this);
}

void MTROTAProviderDelegateBridge::HandleQueryImage(chip::app::CommandHandler * commandObj,
const chip::app::ConcreteCommandPath & commandPath,
const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImage::DecodableType & commandData)
{
// Make sure to hold on to the command handler and command path to be used in the completion block
__block chip::app::CommandHandler::Handle handle(commandObj);
__block chip::app::ConcreteCommandPath cachedCommandPath(
commandPath.mEndpointId, commandPath.mClusterId, commandPath.mCommandId);

id<MTROTAProviderDelegate> strongDelegate = mDelegate;
if ([strongDelegate respondsToSelector:@selector(handleQueryImage:completionHandler:)]) {
if (strongDelegate && mQueue) {
auto * commandParams = [[MTROtaSoftwareUpdateProviderClusterQueryImageParams alloc] init];
ConvertToQueryImageParams(commandData, commandParams);

dispatch_async(mQueue, ^{
[strongDelegate handleQueryImage:commandParams
completionHandler:^(MTROtaSoftwareUpdateProviderClusterQueryImageResponseParams * _Nullable data,
NSError * _Nullable error) {
chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImageResponse::Type response;
ConvertFromQueryImageResponseParms(data, response);

chip::app::CommandHandler * handler = handle.Get();
if (handler) {
handler->AddResponse(cachedCommandPath, response);
handle.Release();
}
}];
});
}
}
}

void MTROTAProviderDelegateBridge::HandleApplyUpdateRequest(chip::app::CommandHandler * commandObj,
const chip::app::ConcreteCommandPath & commandPath,
const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::ApplyUpdateRequest::DecodableType & commandData)
{
// Make sure to hold on to the command handler and command path to be used in the completion block
__block chip::app::CommandHandler::Handle handle(commandObj);
__block chip::app::ConcreteCommandPath cachedCommandPath(
commandPath.mEndpointId, commandPath.mClusterId, commandPath.mCommandId);

id<MTROTAProviderDelegate> strongDelegate = mDelegate;
if ([strongDelegate respondsToSelector:@selector(handleApplyUpdateRequest:completionHandler:)]) {
if (strongDelegate && mQueue) {
auto * commandParams = [[MTROtaSoftwareUpdateProviderClusterApplyUpdateRequestParams alloc] init];
ConvertToApplyUpdateRequestParams(commandData, commandParams);

dispatch_async(mQueue, ^{
[strongDelegate
handleApplyUpdateRequest:commandParams
completionHandler:^(MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * _Nullable data,
NSError * _Nullable error) {
chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::ApplyUpdateResponse::Type response;
ConvertFromApplyUpdateRequestResponseParms(data, response);

chip::app::CommandHandler * handler = handle.Get();
if (handler) {
handler->AddResponse(cachedCommandPath, response);
handle.Release();
}
}];
});
}
}
}

void MTROTAProviderDelegateBridge::HandleNotifyUpdateApplied(chip::app::CommandHandler * commandObj,
const chip::app::ConcreteCommandPath & commandPath,
const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::NotifyUpdateApplied::DecodableType & commandData)
{
// Make sure to hold on to the command handler and command path to be used in the completion block
__block chip::app::CommandHandler::Handle handle(commandObj);
__block chip::app::ConcreteCommandPath cachedCommandPath(
commandPath.mEndpointId, commandPath.mClusterId, commandPath.mCommandId);

id<MTROTAProviderDelegate> strongDelegate = mDelegate;
if ([strongDelegate respondsToSelector:@selector(handleNotifyUpdateApplied:completionHandler:)]) {
if (strongDelegate && mQueue) {
auto * commandParams = [[MTROtaSoftwareUpdateProviderClusterNotifyUpdateAppliedParams alloc] init];
ConvertToNotifyUpdateAppliedParams(commandData, commandParams);

dispatch_async(mQueue, ^{
[strongDelegate
handleNotifyUpdateApplied:commandParams
completionHandler:^(NSError * _Nullable error) {
chip::app::CommandHandler * handler = handle.Get();
if (handler) {
handler->AddStatus(cachedCommandPath, chip::Protocols::InteractionModel::Status::Success);
handle.Release();
}
}];
});
}
}
}

void MTROTAProviderDelegateBridge::ConvertToQueryImageParams(
const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImage::DecodableType & commandData,
MTROtaSoftwareUpdateProviderClusterQueryImageParams * commandParams)
{
commandParams.vendorId = [NSNumber numberWithInt:commandData.vendorId];
commandParams.productId = [NSNumber numberWithInt:commandData.productId];
commandParams.softwareVersion = [NSNumber numberWithInt:commandData.softwareVersion];
auto iterator = commandData.protocolsSupported.begin();
NSMutableArray * protocolsSupported = [[NSMutableArray alloc] init];
while (iterator.Next()) {
chip::app::Clusters::OtaSoftwareUpdateProvider::OTADownloadProtocol protocol = iterator.GetValue();
[protocolsSupported addObject:[NSNumber numberWithInt:static_cast<int>(protocol)]];
}
commandParams.protocolsSupported = [protocolsSupported copy];

if (commandData.hardwareVersion.HasValue()) {
commandParams.hardwareVersion = [NSNumber numberWithInt:commandData.hardwareVersion.Value()];
}

if (commandData.location.HasValue()) {
commandParams.location = [NSString stringWithUTF8String:commandData.location.Value().data()];
}

if (commandData.requestorCanConsent.HasValue()) {
commandParams.requestorCanConsent = [NSNumber numberWithBool:commandData.requestorCanConsent.Value()];
}

if (commandData.metadataForProvider.HasValue()) {
commandParams.metadataForProvider = [NSData dataWithBytes:commandData.metadataForProvider.Value().data()
length:commandData.metadataForProvider.Value().size()];
}
}

void MTROTAProviderDelegateBridge::ConvertFromQueryImageResponseParms(
const MTROtaSoftwareUpdateProviderClusterQueryImageResponseParams * responseParams,
chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImageResponse::Type & response)
{
response.status = static_cast<chip::app::Clusters::OtaSoftwareUpdateProvider::OTAQueryStatus>([responseParams.status intValue]);

if (responseParams.delayedActionTime) {
response.delayedActionTime.SetValue([responseParams.delayedActionTime intValue]);
}

if (responseParams.imageURI) {
response.imageURI.SetValue(chip::CharSpan([responseParams.imageURI UTF8String], responseParams.imageURI.length));
}

if (responseParams.softwareVersion) {
response.softwareVersion.SetValue([responseParams.softwareVersion intValue]);
}

if (responseParams.softwareVersionString) {
response.softwareVersionString.SetValue(
chip::CharSpan([responseParams.softwareVersionString UTF8String], responseParams.softwareVersionString.length));
}

if (responseParams.updateToken) {
UInt8 * updateTokenBytes = (UInt8 *) responseParams.updateToken.bytes;
response.updateToken.SetValue(chip::ByteSpan(updateTokenBytes, responseParams.updateToken.length));
}

if (responseParams.userConsentNeeded) {
response.userConsentNeeded.SetValue([responseParams.userConsentNeeded boolValue]);
}

if (responseParams.metadataForRequestor) {
UInt8 * metadataForRequestorBytes = (UInt8 *) responseParams.metadataForRequestor.bytes;
response.metadataForRequestor.SetValue(
chip::ByteSpan(metadataForRequestorBytes, responseParams.metadataForRequestor.length));
}
}

void MTROTAProviderDelegateBridge::ConvertToApplyUpdateRequestParams(
const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::ApplyUpdateRequest::DecodableType & commandData,
MTROtaSoftwareUpdateProviderClusterApplyUpdateRequestParams * commandParams)
{
commandParams.updateToken = [NSData dataWithBytes:commandData.updateToken.data() length:commandData.updateToken.size()];
commandParams.newVersion = [NSNumber numberWithInt:commandData.newVersion];
}

void MTROTAProviderDelegateBridge::ConvertFromApplyUpdateRequestResponseParms(
const MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * responseParams,
chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::ApplyUpdateResponse::Type & response)
{
response.action
= static_cast<chip::app::Clusters::OtaSoftwareUpdateProvider::OTAApplyUpdateAction>([responseParams.action intValue]);
response.delayedActionTime = [responseParams.delayedActionTime intValue];
}

void MTROTAProviderDelegateBridge::ConvertToNotifyUpdateAppliedParams(
const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::NotifyUpdateApplied::DecodableType & commandData,
MTROtaSoftwareUpdateProviderClusterNotifyUpdateAppliedParams * commandParams)
{
commandParams.updateToken = [NSData dataWithBytes:commandData.updateToken.data() length:commandData.updateToken.size()];
commandParams.softwareVersion = [NSNumber numberWithInt:commandData.softwareVersion];
}
6 changes: 5 additions & 1 deletion src/darwin/Framework/Matter.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
99D466E12798936D0089A18F /* MTRCommissioningParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 99D466E02798936D0089A18F /* MTRCommissioningParameters.h */; settings = {ATTRIBUTES = (Public, ); }; };
AF1CB86E2874B03B00865A96 /* MTROTAProviderDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = AF1CB86D2874B03B00865A96 /* MTROTAProviderDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
AF1CB8702874B04C00865A96 /* MTROTAProviderDelegateBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = AF1CB86F2874B04C00865A96 /* MTROTAProviderDelegateBridge.h */; };
AF5F90FF2878D351005503FA /* MTROTAProviderDelegateBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = AF5F90FE2878D351005503FA /* MTROTAProviderDelegateBridge.mm */; };
B20252972459E34F00F97062 /* Matter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B202528D2459E34F00F97062 /* Matter.framework */; };
B289D4212639C0D300D4E314 /* MTROnboardingPayloadParser.h in Headers */ = {isa = PBXBuildFile; fileRef = B289D41F2639C0D300D4E314 /* MTROnboardingPayloadParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
B289D4222639C0D300D4E314 /* MTROnboardingPayloadParser.m in Sources */ = {isa = PBXBuildFile; fileRef = B289D4202639C0D300D4E314 /* MTROnboardingPayloadParser.m */; };
Expand Down Expand Up @@ -211,6 +212,7 @@
99D466E02798936D0089A18F /* MTRCommissioningParameters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRCommissioningParameters.h; sourceTree = "<group>"; };
AF1CB86D2874B03B00865A96 /* MTROTAProviderDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTROTAProviderDelegate.h; sourceTree = "<group>"; };
AF1CB86F2874B04C00865A96 /* MTROTAProviderDelegateBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTROTAProviderDelegateBridge.h; sourceTree = "<group>"; };
AF5F90FE2878D351005503FA /* MTROTAProviderDelegateBridge.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MTROTAProviderDelegateBridge.mm; sourceTree = "<group>"; };
B202528D2459E34F00F97062 /* Matter.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Matter.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B20252912459E34F00F97062 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B20252962459E34F00F97062 /* MatterTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MatterTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -343,8 +345,9 @@
2CB7163E252F731E0026E2BB /* MTRDevicePairingDelegate.h */,
2CB71638252E8A7B0026E2BB /* MTRDevicePairingDelegateBridge.h */,
2CB71639252E8A7B0026E2BB /* MTRDevicePairingDelegateBridge.mm */,
AF1CB86F2874B04C00865A96 /* MTROTAProviderDelegateBridge.h */,
AF1CB86D2874B03B00865A96 /* MTROTAProviderDelegate.h */,
AF1CB86F2874B04C00865A96 /* MTROTAProviderDelegateBridge.h */,
AF5F90FE2878D351005503FA /* MTROTAProviderDelegateBridge.mm */,
B2E0D7A8245B0B5C003C5B48 /* Matter.h */,
B2E0D7AB245B0B5C003C5B48 /* MTRError_Internal.h */,
5129BCFC26A9EE3300122DDF /* MTRError.h */,
Expand Down Expand Up @@ -610,6 +613,7 @@
998F287126D56940001846C6 /* MTRP256KeypairBridge.mm in Sources */,
5136661428067D550025EDAE /* MTRControllerFactory.mm in Sources */,
51B22C2A2740CB47008D5055 /* MTRCommandPayloadsObjc.mm in Sources */,
AF5F90FF2878D351005503FA /* MTROTAProviderDelegateBridge.mm in Sources */,
2C5EEEF7268A85C400CAE3D3 /* MTRDeviceConnectionBridge.mm in Sources */,
51B22C262740CB32008D5055 /* MTRStructsObjc.mm in Sources */,
2C222AD1255C620600E446B9 /* MTRBaseDevice.mm in Sources */,
Expand Down

0 comments on commit 1542514

Please sign in to comment.