Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / darwin / CHIPTool / CHIPTool / View Controllers / MultiAdmin / MultiAdminViewController.m
1 /**
2  *
3  *    Copyright (c) 2021 Project CHIP Authors
4  *
5  *    Licensed under the Apache License, Version 2.0 (the "License");
6  *    you may not use this file except in compliance with the License.
7  *    You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *    Unless required by applicable law or agreed to in writing, software
12  *    distributed under the License is distributed on an "AS IS" BASIS,
13  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *    See the License for the specific language governing permissions and
15  *    limitations under the License.
16  */
17
18 #import "MultiAdminViewController.h"
19
20 #import "CHIPUIViewUtils.h"
21 #import "DefaultsUtils.h"
22 #import "DeviceSelector.h"
23
24 static NSString * const DEFAULT_TIMEOUT = @"900";
25 static NSString * const DEFAULT_DISCRIMINATOR = @"3840";
26
27 @interface MultiAdminViewController ()
28
29 @property (strong, nonatomic) UISwitch * openPairingOnAllDevices;
30 @property (strong, nonatomic) UISwitch * useOnboardingTokenSwitch;
31 @property (strong, nonatomic) UITextField * discriminatorField;
32 @property (strong, nonatomic) UITextField * timeoutField;
33 @property (strong, nonatomic) UIButton * openPairingWindowButton;
34
35 @property (nonatomic, strong) UILabel * resultLabel;
36 @property (nonatomic, strong) UIStackView * stackView;
37
38 @property (nonatomic, strong) DeviceSelector * deviceSelector;
39 @end
40
41 @implementation MultiAdminViewController
42
43 // MARK: UIViewController methods
44
45 - (void)viewDidLoad
46 {
47     [super viewDidLoad];
48     [self setupUIElements];
49
50     // listen for taps to dismiss the keyboard
51     UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
52     [self.view addGestureRecognizer:tap];
53 }
54
55 - (void)dismissKeyboard
56 {
57     [self.discriminatorField resignFirstResponder];
58     [self.timeoutField resignFirstResponder];
59     [self.deviceSelector resignFirstResponder];
60 }
61
62 // MARK: UI Setup
63
64 - (void)setupUIElements
65 {
66     self.view.backgroundColor = UIColor.whiteColor;
67
68     // Title
69     UILabel * titleLabel = [CHIPUIViewUtils addTitle:@"Open Pairing Window" toView:self.view];
70
71     // stack view
72     UIStackView * stackView = [UIStackView new];
73     stackView.axis = UILayoutConstraintAxisVertical;
74     stackView.distribution = UIStackViewDistributionFill;
75     stackView.alignment = UIStackViewAlignmentLeading;
76     stackView.spacing = 30;
77     [self.view addSubview:stackView];
78
79     stackView.translatesAutoresizingMaskIntoConstraints = false;
80     [stackView.topAnchor constraintEqualToAnchor:titleLabel.bottomAnchor constant:40].active = YES;
81     [stackView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:30].active = YES;
82     [stackView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-30].active = YES;
83
84     // Open pairing on all devices
85     UILabel * pairAllDevices = [UILabel new];
86     pairAllDevices.text = @"Enable pairing on all devices";
87     _openPairingOnAllDevices = [UISwitch new];
88     [_openPairingOnAllDevices setOn:YES];
89     UIView * openPairingOnAllDevicesView = [CHIPUIViewUtils viewWithLabel:pairAllDevices toggle:_openPairingOnAllDevices];
90     [_openPairingOnAllDevices addTarget:self action:@selector(pairAllDevicesButton:) forControlEvents:UIControlEventTouchUpInside];
91     [stackView addArrangedSubview:openPairingOnAllDevicesView];
92     openPairingOnAllDevicesView.translatesAutoresizingMaskIntoConstraints = false;
93     [openPairingOnAllDevicesView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES;
94
95     // Device List and selector
96     _deviceSelector = [DeviceSelector new];
97     [_deviceSelector setEnabled:NO];
98
99     UILabel * deviceIDLabel = [UILabel new];
100     deviceIDLabel.text = @"Device ID:";
101     UIView * deviceIDView = [CHIPUIViewUtils viewWithLabel:deviceIDLabel textField:_deviceSelector];
102     [stackView addArrangedSubview:deviceIDView];
103
104     deviceIDView.translatesAutoresizingMaskIntoConstraints = false;
105     [deviceIDView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = true;
106
107     // Open Pairing Window
108     UILabel * useOnboardingToken = [UILabel new];
109     useOnboardingToken.text = @"Use Onboarding Token";
110     _useOnboardingTokenSwitch = [UISwitch new];
111     [_useOnboardingTokenSwitch setOn:YES];
112     UIView * useOnboardingTokenView = [CHIPUIViewUtils viewWithLabel:useOnboardingToken toggle:_useOnboardingTokenSwitch];
113     [_useOnboardingTokenSwitch addTarget:self action:@selector(overrideControls:) forControlEvents:UIControlEventTouchUpInside];
114     [stackView addArrangedSubview:useOnboardingTokenView];
115     useOnboardingTokenView.translatesAutoresizingMaskIntoConstraints = false;
116     [useOnboardingTokenView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES;
117
118     // Discriminator
119     _discriminatorField = [UITextField new];
120     _discriminatorField.keyboardType = UIKeyboardTypeNumberPad;
121     _discriminatorField.placeholder = DEFAULT_DISCRIMINATOR;
122     UILabel * discriminatorLabel = [UILabel new];
123     [discriminatorLabel setText:@"Discriminator"];
124     UIView * discriminatorView = [CHIPUIViewUtils viewWithLabel:discriminatorLabel textField:_discriminatorField];
125     [stackView addArrangedSubview:discriminatorView];
126
127     discriminatorView.translatesAutoresizingMaskIntoConstraints = false;
128     [discriminatorView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES;
129
130     // Pairing Timeout
131     _timeoutField = [UITextField new];
132     _timeoutField.keyboardType = UIKeyboardTypeNumberPad;
133     _timeoutField.placeholder = DEFAULT_TIMEOUT;
134     UILabel * timeoutLabel = [UILabel new];
135     [timeoutLabel setText:@"Timeout after (seconds)"];
136     UIView * timeoutView = [CHIPUIViewUtils viewWithLabel:timeoutLabel textField:_timeoutField];
137     [stackView addArrangedSubview:timeoutView];
138
139     timeoutView.translatesAutoresizingMaskIntoConstraints = false;
140     [timeoutView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES;
141
142     // Open Pairing Window button
143     _openPairingWindowButton = [UIButton new];
144     [_openPairingWindowButton setTitle:@"Open Pairing Window" forState:UIControlStateNormal];
145     [_openPairingWindowButton addTarget:self action:@selector(openPairingWindow:) forControlEvents:UIControlEventTouchUpInside];
146     _openPairingWindowButton.backgroundColor = UIColor.systemBlueColor;
147     _openPairingWindowButton.titleLabel.font = [UIFont systemFontOfSize:17];
148     _openPairingWindowButton.titleLabel.textColor = [UIColor whiteColor];
149     _openPairingWindowButton.layer.cornerRadius = 5;
150     _openPairingWindowButton.clipsToBounds = YES;
151     [stackView addArrangedSubview:_openPairingWindowButton];
152
153     _openPairingWindowButton.translatesAutoresizingMaskIntoConstraints = false;
154     [_openPairingWindowButton.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES;
155
156     // Result message
157     _resultLabel = [UILabel new];
158     _resultLabel.hidden = YES;
159     _resultLabel.font = [UIFont systemFontOfSize:17];
160     _resultLabel.textColor = UIColor.systemBlueColor;
161     _resultLabel.lineBreakMode = NSLineBreakByWordWrapping;
162     _resultLabel.numberOfLines = 0;
163     [stackView addArrangedSubview:_resultLabel];
164
165     _resultLabel.translatesAutoresizingMaskIntoConstraints = false;
166     [_resultLabel.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES;
167     _resultLabel.adjustsFontSizeToFitWidth = YES;
168 }
169
170 - (void)updateResult:(NSString *)result
171 {
172     _resultLabel.hidden = NO;
173     _resultLabel.text = result;
174 }
175
176 // MARK: UIButton actions
177
178 - (IBAction)pairAllDevicesButton:(id)sender
179 {
180     if ([_openPairingOnAllDevices isOn]) {
181         [_deviceSelector setEnabled:NO];
182     } else {
183         [_deviceSelector setEnabled:YES];
184     }
185 }
186
187 - (IBAction)overrideControls:(id)sender
188 {
189     if ([_useOnboardingTokenSwitch isOn]) {
190         _discriminatorField.placeholder = DEFAULT_DISCRIMINATOR;
191         _timeoutField.placeholder = DEFAULT_TIMEOUT;
192         [_discriminatorField setEnabled:YES];
193     } else {
194         _discriminatorField.text = @"";
195         _discriminatorField.placeholder = @"Original discriminator";
196         [_discriminatorField setEnabled:NO];
197     }
198 }
199
200 - (IBAction)openPairingWindow:(id)sender
201 {
202     uint32_t setupPIN = arc4random();
203     [_deviceSelector forSelectedDevices:^(uint64_t deviceId) {
204         CHIPDevice * chipDevice = CHIPGetPairedDeviceWithID(deviceId);
205         // send message
206         if (chipDevice != nil && [chipDevice isActive]) {
207             NSString * timeoutStr = [self.timeoutField text];
208             if (timeoutStr.length == 0) {
209                 timeoutStr = [self.timeoutField placeholder];
210             }
211             int timeout = [timeoutStr intValue];
212
213             NSString * output;
214             NSError * error;
215             if ([self.useOnboardingTokenSwitch isOn]) {
216                 NSString * discriminatorStr = [self.discriminatorField text];
217                 if (discriminatorStr.length == 0) {
218                     discriminatorStr = [self.discriminatorField placeholder];
219                 }
220                 NSInteger discriminator = [discriminatorStr intValue];
221
222                 output = [chipDevice openPairingWindowWithPIN:timeout discriminator:discriminator setupPIN:setupPIN error:&error];
223
224                 if (output != nil) {
225                     NSString * result = [@"Use Manual Code: " stringByAppendingString:output];
226                     [self updateResult:result];
227                 } else {
228                     [self updateResult:@"Failed in opening the pairing window"];
229                 }
230             } else {
231                 BOOL didSend = [chipDevice openPairingWindow:timeout error:&error];
232                 if (didSend) {
233                     [self updateResult:@"Scan the QR code on the device"];
234                 } else {
235                     NSString * errorString = [@"Error: " stringByAppendingString:error.localizedDescription];
236                     [self updateResult:errorString];
237                 }
238             }
239         } else {
240             [self updateResult:@"Controller not connected"];
241         }
242     }];
243 }
244
245 @end