Skip to content

Commit

Permalink
Add a device selector view in CHIPTool iOS app
Browse files Browse the repository at this point in the history
  • Loading branch information
pan-apple committed Feb 13, 2021
1 parent a557905 commit 1356a8d
Show file tree
Hide file tree
Showing 7 changed files with 226 additions and 33 deletions.
6 changes: 6 additions & 0 deletions src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
0CA0E0CF248599BB009087B9 /* OnOffViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CA0E0CE248599BB009087B9 /* OnOffViewController.m */; };
2C21071525D1A8F200DDA4AD /* MultiAdminViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C21071325D1A8F200DDA4AD /* MultiAdminViewController.m */; };
2C460C2425D7594B000512D6 /* DeviceSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C460C2325D7594B000512D6 /* DeviceSelector.m */; };
991DC091247747F500C13860 /* EchoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 991DC090247747F500C13860 /* EchoViewController.m */; };
997A639C253F93F7005C64E6 /* CHIP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 997A639B253F93F7005C64E6 /* CHIP.framework */; };
997A639D253F93F7005C64E6 /* CHIP.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 997A639B253F93F7005C64E6 /* CHIP.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
Expand Down Expand Up @@ -55,6 +56,8 @@
0CA0E0CE248599BB009087B9 /* OnOffViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OnOffViewController.m; sourceTree = "<group>"; };
2C21071325D1A8F200DDA4AD /* MultiAdminViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MultiAdminViewController.m; sourceTree = "<group>"; };
2C21071425D1A8F200DDA4AD /* MultiAdminViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MultiAdminViewController.h; sourceTree = "<group>"; };
2C460C2225D7594B000512D6 /* DeviceSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeviceSelector.h; sourceTree = "<group>"; };
2C460C2325D7594B000512D6 /* DeviceSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DeviceSelector.m; sourceTree = "<group>"; };
991DC08F247747F500C13860 /* EchoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EchoViewController.h; sourceTree = "<group>"; };
991DC090247747F500C13860 /* EchoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EchoViewController.m; sourceTree = "<group>"; };
997A639B253F93F7005C64E6 /* CHIP.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CHIP.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -203,6 +206,8 @@
B232D8BF251A0EC500792CB4 /* View Controllers */ = {
isa = PBXGroup;
children = (
2C460C2225D7594B000512D6 /* DeviceSelector.h */,
2C460C2325D7594B000512D6 /* DeviceSelector.m */,
2C21071225D1A8F200DDA4AD /* MultiAdmin */,
B204A61F244E1D0600C7C0E1 /* AppDelegate.h */,
B204A620244E1D0600C7C0E1 /* AppDelegate.m */,
Expand Down Expand Up @@ -356,6 +361,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
2C460C2425D7594B000512D6 /* DeviceSelector.m in Sources */,
2C21071525D1A8F200DDA4AD /* MultiAdminViewController.m in Sources */,
B204A627244E1D0600C7C0E1 /* QRCodeViewController.m in Sources */,
B232D8BA2514BD0800792CB4 /* CHIPUIViewUtils.m in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ void CHIPRemoveDomainValueForKey(NSString * domain, NSString * key);
uint64_t CHIPGetNextAvailableDeviceID(void);
void CHIPSetNextAvailableDeviceID(uint64_t id);
CHIPDevice * GetPairedDevice(void);
CHIPDevice * GetPairedDeviceWithID(uint64_t id);

@interface CHIPToolPersistentStorageDelegate : NSObject <CHIPPersistentStorageDelegate>

Expand Down
12 changes: 12 additions & 0 deletions src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,18 @@ void CHIPSetNextAvailableDeviceID(uint64_t id)
return device;
}

CHIPDevice * GetPairedDeviceWithID(uint64_t deviceId)
{
CHIPToolPersistentStorageDelegate * storage = [[CHIPToolPersistentStorageDelegate alloc] init];
dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.persistentstorage.callback", DISPATCH_QUEUE_SERIAL);

CHIPDeviceController * controller = [CHIPDeviceController sharedController];
[controller setPersistentStorageDelegate:storage queue:callbackQueue];

NSError * error;
return [controller getPairedDevice:deviceId error:&error];
}

@implementation CHIPToolPersistentStorageDelegate

// MARK: CHIPPersistentStorageDelegate
Expand Down
28 changes: 28 additions & 0 deletions src/darwin/CHIPTool/CHIPTool/View Controllers/DeviceSelector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
*
* Copyright (c) 2021 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 <CHIP/CHIP.h>
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface DeviceSelector : UITextField <UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate>
- (instancetype)init;
- (CHIPDevice *)selectedDevice;
@end

NS_ASSUME_NONNULL_END
136 changes: 136 additions & 0 deletions src/darwin/CHIPTool/CHIPTool/View Controllers/DeviceSelector.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/**
*
* Copyright (c) 2021 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 "DeviceSelector.h"

#import "CHIPUIViewUtils.h"
#import "DefaultsUtils.h"

@interface DeviceSelector ()
@property (readwrite) CHIPDevice * chipDevice;
@property (readwrite) uint64_t nextDeviceID;
@end

@implementation DeviceSelector {
NSMutableArray * _deviceList;
UIPickerView * _devicePicker;
NSUInteger _selectedDeviceIndex;
}

- (id)init
{
if (self = [super init]) {
_nextDeviceID = CHIPGetNextAvailableDeviceID();
_selectedDeviceIndex = self.nextDeviceID + 1;
[self refreshDeviceList];
[self setupView];
}
return self;
}

- (void)refreshDeviceList
{
_deviceList = [NSMutableArray new];
for (uint64_t i = 0; i < _nextDeviceID; i++) {
if (GetPairedDeviceWithID(i) != nil) {
[_deviceList addObject:[@(i) stringValue]];
}
}
_selectedDeviceIndex = 0;
}

- (void)selectDevice
{
uint64_t deviceID = [_deviceList[_selectedDeviceIndex] intValue];
_chipDevice = GetPairedDeviceWithID(deviceID);
}

- (CHIPDevice *)selectedDevice
{
return _chipDevice;
}

- (void)setupView
{
self.text = [_deviceList objectAtIndex:_selectedDeviceIndex];
_devicePicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 100, 0, 0)];
self.inputView = _devicePicker;
[_devicePicker setDataSource:self];
[_devicePicker setDelegate:self];
self.delegate = self;

UIToolbar * deviceSelectButtonView = [[UIToolbar alloc] init];
[deviceSelectButtonView sizeToFit];
UIBarButtonItem * deviceSelectButton = [[UIBarButtonItem alloc] initWithTitle:@"Select Device"
style:UIBarButtonItemStylePlain
target:self
action:@selector(deviceSelectClicked:)];
UIBarButtonItem * flexible = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:self
action:nil];
[deviceSelectButtonView setItems:[NSArray arrayWithObjects:flexible, deviceSelectButton, nil]];
self.inputAccessoryView = deviceSelectButtonView;

[self selectDevice];
}

// MARK: UIPickerView

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSLog(@"%@", [_deviceList objectAtIndex:row]);
self.text = [NSString stringWithFormat:@"%@", [_deviceList objectAtIndex:row]];
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [_deviceList count];
}

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [_deviceList objectAtIndex:row];
}

- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
{
return 200;
}

- (IBAction)deviceSelectClicked:(id)sender
{
_selectedDeviceIndex = [_deviceList indexOfObject:self.text];
[self resignFirstResponder];
[self selectDevice];
}

// MARK: CHIPDeviceControllerDelegate
- (void)deviceControllerOnConnected
{
NSLog(@"Status: Device connected");
}

- (void)deviceControllerOnError:(nonnull NSError *)error
{
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#import "CHIPUIViewUtils.h"
#import "DefaultsUtils.h"
#import "DeviceSelector.h"

static NSString * const DEFAULT_TIMEOUT = @"900";
static NSString * const DEFAULT_DISCRIMINATOR = @"3840";
Expand All @@ -33,10 +34,7 @@ @interface MultiAdminViewController ()
@property (nonatomic, strong) UILabel * resultLabel;
@property (nonatomic, strong) UIStackView * stackView;

@property (readwrite) CHIPDevice * chipDevice;

@property (readonly) CHIPToolPersistentStorageDelegate * persistentStorage;

@property (nonatomic, strong) DeviceSelector * deviceSelector;
@end

@implementation MultiAdminViewController
Expand All @@ -51,14 +49,13 @@ - (void)viewDidLoad
// listen for taps to dismiss the keyboard
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];

self.chipDevice = GetPairedDevice();
}

- (void)dismissKeyboard
{
[self.discriminatorField resignFirstResponder];
[self.timeoutField resignFirstResponder];
[self.deviceSelector resignFirstResponder];
}

// MARK: UI Setup
Expand All @@ -83,6 +80,18 @@ - (void)setupUIElements
[stackView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:30].active = YES;
[stackView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-30].active = YES;

// Device List and selector
UILabel * deviceIDLabel = [UILabel new];
deviceIDLabel.text = @"Device ID:";
_deviceSelector = [DeviceSelector new];

UIView * deviceIDView = [CHIPUIViewUtils viewWithLabel:deviceIDLabel textField:_deviceSelector];
deviceIDLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightSemibold];

[stackView addArrangedSubview:deviceIDView];
deviceIDView.translatesAutoresizingMaskIntoConstraints = false;
[deviceIDView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = true;

// Open Pairing Window
UILabel * useOnboardingToken = [UILabel new];
useOnboardingToken.text = @"Use Onboarding Token";
Expand Down Expand Up @@ -170,7 +179,8 @@ - (IBAction)overrideControls:(id)sender
- (IBAction)openPairingWindow:(id)sender
{
// send message
if ([self.chipDevice isActive]) {
CHIPDevice * chipDevice = [self.deviceSelector selectedDevice];
if (chipDevice != nil && [chipDevice isActive]) {
NSString * timeoutStr = [self.timeoutField text];
if (timeoutStr.length == 0) {
timeoutStr = [self.timeoutField placeholder];
Expand All @@ -186,7 +196,7 @@ - (IBAction)openPairingWindow:(id)sender
}
NSInteger discriminator = [discriminatorStr intValue];

output = [self.chipDevice openPairingWindowWithPIN:timeout discriminator:discriminator error:&error];
output = [chipDevice openPairingWindowWithPIN:timeout discriminator:discriminator error:&error];

if (output != nil) {
NSString * result = [@"Use Manual Code: " stringByAppendingString:output];
Expand All @@ -195,7 +205,7 @@ - (IBAction)openPairingWindow:(id)sender
[self updateResult:@"Failed in opening the pairing window"];
}
} else {
BOOL didSend = [self.chipDevice openPairingWindow:timeout error:&error];
BOOL didSend = [chipDevice openPairingWindow:timeout error:&error];
if (didSend) {
[self updateResult:@"Scan the QR code on the device"];
} else {
Expand All @@ -208,21 +218,4 @@ - (IBAction)openPairingWindow:(id)sender
}
}

// MARK: CHIPDeviceControllerDelegate
- (void)deviceControllerOnConnected
{
NSLog(@"Status: Device connected");
}

- (void)deviceControllerOnError:(nonnull NSError *)error
{
NSLog(@"Status: Device Controller error %@", [error description]);
if (error) {
NSString * stringError = [@"Error: " stringByAppendingString:error.description];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5.0), dispatch_get_main_queue(), ^{
[self updateResult:stringError];
});
}
}

@end
Loading

0 comments on commit 1356a8d

Please sign in to comment.