From 229128123e2f9b7c75fb7cd17da27df21dfc8359 Mon Sep 17 00:00:00 2001 From: Sharad Binjola <31142146+sharadb-amazon@users.noreply.github.com> Date: Mon, 27 Jun 2022 15:37:47 -0700 Subject: [PATCH] iOS TvCasting app: Displaying onboarding payload and aesthetic improvements (#19934) --- .../MatterBridge/CastingServerBridge.h | 10 ++++++ .../MatterBridge/CastingServerBridge.mm | 15 +++++++++ .../MatterBridge/OnboardingPayload.h | 31 +++++++++++++++++ .../MatterBridge/OnboardingPayload.m | 33 +++++++++++++++++++ .../TvCasting.xcodeproj/project.pbxproj | 6 ++++ .../TvCasting/CommissioningView.swift | 32 +++++++++++------- .../TvCasting/CommissioningViewModel.swift | 4 ++- .../TvCasting/ContentLauncherViewModel.swift | 4 ++- 8 files changed, 122 insertions(+), 13 deletions(-) create mode 100644 examples/tv-casting-app/darwin/TvCasting/MatterBridge/OnboardingPayload.h create mode 100644 examples/tv-casting-app/darwin/TvCasting/MatterBridge/OnboardingPayload.m diff --git a/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.h b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.h index d66909a60ca7f7..522478444789b0 100644 --- a/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.h +++ b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.h @@ -16,6 +16,7 @@ */ #import "DiscoveredNodeData.h" +#import "OnboardingPayload.h" #import #ifndef CastingServerBridge_h @@ -27,6 +28,8 @@ @property void (^_Nullable launchUrlResponseCallback)(bool); +@property OnboardingPayload * _Nonnull onboardingPayload; + + (CastingServerBridge * _Nullable)getSharedInstance; /*! @@ -71,6 +74,13 @@ clientQueue:(dispatch_queue_t _Nonnull)clientQueue udcRequestSentHandler:(nullable void (^)(bool))udcRequestSentHandler; +/*! + @brief Return the onboarding payload for this app (setup passcode, discriminator) + + @return Onboarding payload + */ +- (OnboardingPayload * _Nonnull)getOnboardingPaylod; + /*! @brief Request opening of a basic commissioning window diff --git a/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.mm b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.mm index d523d991d3c8a0..de72fd816071ff 100644 --- a/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.mm +++ b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.mm @@ -19,6 +19,7 @@ #import "CastingServer.h" #import "DiscoveredNodeDataConverter.hpp" +#import "OnboardingPayload.h" #include #include @@ -26,6 +27,7 @@ #include #include #include +#include @interface CastingServerBridge () @@ -61,6 +63,14 @@ - (instancetype)init return nil; } + chip::DeviceLayer::TestOnlyCommissionableDataProvider TestOnlyCommissionableDataProvider; + uint32_t defaultTestPasscode = 0; + VerifyOrDie(TestOnlyCommissionableDataProvider.GetSetupPasscode(defaultTestPasscode) == CHIP_NO_ERROR); + uint16_t defaultTestSetupDiscriminator = 0; + VerifyOrDie(TestOnlyCommissionableDataProvider.GetSetupDiscriminator(defaultTestSetupDiscriminator) == CHIP_NO_ERROR); + _onboardingPayload = [[OnboardingPayload alloc] initWithSetupPasscode:defaultTestPasscode + setupDiscriminator:defaultTestSetupDiscriminator]; + // Initialize device attestation config SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider()); @@ -169,6 +179,11 @@ - (void)sendUserDirectedCommissioningRequest:(NSString * _Nonnull)commissionerIp }); } +- (OnboardingPayload *)getOnboardingPaylod +{ + return _onboardingPayload; +} + - (void)openBasicCommissioningWindow:(nullable void (^)(bool))commissioningCompleteCallback clientQueue:(dispatch_queue_t _Nonnull)clientQueue commissioningWindowRequestedHandler:(nullable void (^)(bool))commissioningWindowRequestedHandler diff --git a/examples/tv-casting-app/darwin/TvCasting/MatterBridge/OnboardingPayload.h b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/OnboardingPayload.h new file mode 100644 index 00000000000000..27a76b302a6683 --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/OnboardingPayload.h @@ -0,0 +1,31 @@ +/** + * + * Copyright (c) 2020-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. + */ + +#ifndef OnboardingPayload_h +#define OnboardingPayload_h + +@interface OnboardingPayload : NSObject + +@property uint32_t setupPasscode; + +@property uint16_t setupDiscriminator; + +- (instancetype)initWithSetupPasscode:(uint32_t)setupPasscode setupDiscriminator:(uint16_t)setupDiscriminator; + +@end + +#endif /* OnboardingPayload_h */ diff --git a/examples/tv-casting-app/darwin/TvCasting/MatterBridge/OnboardingPayload.m b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/OnboardingPayload.m new file mode 100644 index 00000000000000..20ed22a3305e8f --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/OnboardingPayload.m @@ -0,0 +1,33 @@ +/** + * + * Copyright (c) 2020-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 + +#import "OnboardingPayload.h" + +@implementation OnboardingPayload + +- (instancetype)initWithSetupPasscode:(uint32_t)setupPasscode setupDiscriminator:(uint16_t)setupDiscriminator +{ + if (self = [super init]) { + _setupPasscode = setupPasscode; + _setupDiscriminator = setupDiscriminator; + } + return self; +} + +@end diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj b/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj index 22dccecf8e6e0d..89a446e38f939d 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 3C7507B92853EFF000D7DB3A /* CommissioningViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C7507B82853EFF000D7DB3A /* CommissioningViewModel.swift */; }; 3C7507BC2857A6EE00D7DB3A /* DiscoveredNodeDataConverter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C7507BB2857A6EE00D7DB3A /* DiscoveredNodeDataConverter.mm */; }; 3C9ACC05284ABF4000718B2D /* libTvCastingCommon.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C9ACC04284ABF2F00718B2D /* libTvCastingCommon.a */; }; + 3C9EE55E2864D88700BA9115 /* OnboardingPayload.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C9EE55D2864D88700BA9115 /* OnboardingPayload.m */; }; 3CA19435285BA780004768D5 /* ContentLauncherView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CA19434285BA780004768D5 /* ContentLauncherView.swift */; }; 3CA19437285BA877004768D5 /* ContentLauncherViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CA19436285BA877004768D5 /* ContentLauncherViewModel.swift */; }; 3CC0E8FA2841DD3400EC6A18 /* TvCastingApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CC0E8F92841DD3400EC6A18 /* TvCastingApp.swift */; }; @@ -36,6 +37,8 @@ 3C7507BB2857A6EE00D7DB3A /* DiscoveredNodeDataConverter.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DiscoveredNodeDataConverter.mm; sourceTree = ""; }; 3C7507BD2857A72A00D7DB3A /* DiscoveredNodeDataConverter.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DiscoveredNodeDataConverter.hpp; sourceTree = ""; }; 3C9ACC04284ABF2F00718B2D /* libTvCastingCommon.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libTvCastingCommon.a; path = lib/libTvCastingCommon.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 3C9EE55C2864D7EB00BA9115 /* OnboardingPayload.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OnboardingPayload.h; sourceTree = ""; }; + 3C9EE55D2864D88700BA9115 /* OnboardingPayload.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OnboardingPayload.m; sourceTree = ""; }; 3CA19434285BA780004768D5 /* ContentLauncherView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentLauncherView.swift; sourceTree = ""; }; 3CA19436285BA877004768D5 /* ContentLauncherViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentLauncherViewModel.swift; sourceTree = ""; }; 3CC0E8F62841DD3400EC6A18 /* TvCasting.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TvCasting.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -126,6 +129,8 @@ 3C7507A62851188500D7DB3A /* DiscoveredNodeData.mm */, 3C7507BB2857A6EE00D7DB3A /* DiscoveredNodeDataConverter.mm */, 3C7507BD2857A72A00D7DB3A /* DiscoveredNodeDataConverter.hpp */, + 3C9EE55C2864D7EB00BA9115 /* OnboardingPayload.h */, + 3C9EE55D2864D88700BA9115 /* OnboardingPayload.m */, ); path = MatterBridge; sourceTree = ""; @@ -241,6 +246,7 @@ 3C7507AD285299DF00D7DB3A /* CommissionerDiscoveryView.swift in Sources */, 3CC0E8FA2841DD3400EC6A18 /* TvCastingApp.swift in Sources */, 3C7507B92853EFF000D7DB3A /* CommissioningViewModel.swift in Sources */, + 3C9EE55E2864D88700BA9115 /* OnboardingPayload.m in Sources */, 3C7507BC2857A6EE00D7DB3A /* DiscoveredNodeDataConverter.mm in Sources */, 3C7507A72851188500D7DB3A /* DiscoveredNodeData.mm in Sources */, 3CA19437285BA877004768D5 /* ContentLauncherViewModel.swift in Sources */, diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningView.swift index 1d202f61332812..b246a3bda45e50 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningView.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningView.swift @@ -30,47 +30,57 @@ struct CommissioningView: View { var body: some View { VStack(alignment: .leading) { if(viewModel.commisisoningWindowOpened == true) { - Text("Commissioning window opened.") + Text("Commissioning window opened.").padding() + Text("Onboarding PIN: " + String((CastingServerBridge.getSharedInstance()?.getOnboardingPaylod().setupPasscode)!)) + .border(Color.blue, width: 1) + .padding() + Text("Discriminator: " + String((CastingServerBridge.getSharedInstance()?.getOnboardingPaylod().setupDiscriminator)!)) + .border(Color.blue, width: 1) + .padding() + if(self.selectedCommissioner != nil) { if(viewModel.udcRequestSent == true) { Text("Complete commissioning on " + (selectedCommissioner?.deviceName)!) + .padding() } else if(viewModel.udcRequestSent == false) { Text("Could not send user directed commissioning request to " + (selectedCommissioner?.deviceName)! + "! Complete commissioning manually!") .foregroundColor(Color.red) + .padding() } } else{ - Text("Complete commissioning with a commissioner manually!") + Text("Complete commissioning with a commissioner manually!").padding() } - - // TBD: actual values - Text("Onboarding PIN: ") - .padding() - .border(Color.black, width: 1) - Text("Discriminator: ") - .padding() - .border(Color.black, width: 1) } else if(viewModel.commisisoningWindowOpened == false) { Text("Failed to open Commissioning window!") .foregroundColor(Color.red) + .padding() } if(viewModel.commisisoningComplete == true) { + Text("Commissioning finished!").padding() NavigationLink( destination: ContentLauncherView(), label: { Text("Next") - .frame(width: 75, height: 30, alignment: .center) + .frame(width: 100, height: 30, alignment: .center) .border(Color.black, width: 1) } ).background(Color.blue) .foregroundColor(Color.white) + .frame(maxHeight: .infinity, alignment: .bottom) + .padding() + } + else if(viewModel.commisisoningComplete == false) + { + Text("Commissioning failure!") + .foregroundColor(Color.red) .padding() } } diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift index 34edf1f1af9e81..3f2d4404d3aa81 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift @@ -36,7 +36,9 @@ class CommissioningViewModel: ObservableObject { { (result: Bool) -> () in // commissioning complete handler code self.Log.info("Commissioning status: \(result)") - self.commisisoningComplete = result + DispatchQueue.main.async { + self.commisisoningComplete = result + } }, clientQueue: DispatchQueue.main, commissioningWindowRequestedHandler: { (result: Bool) -> () in diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentLauncherViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentLauncherViewModel.swift index 2f42037bbb0aad..c3506bfd068aec 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentLauncherViewModel.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentLauncherViewModel.swift @@ -37,7 +37,9 @@ class ContentLauncherViewModel: ObservableObject { launchUrlResponseCallback: { (result: Bool) -> () in self.Log.info("ContentLauncherViewModel.launchUrl.launchUrlResponseCallback result \(result)") - self.status = result ? "Launched URL successfully" : "Launch URL failure!" + DispatchQueue.main.async { + self.status = result ? "Launched URL successfully" : "Launch URL failure!" + } }, clientQueue: DispatchQueue.main, launchUrlRequestSentHandler: