3 * Copyright (c) 2020 Project CHIP Authors
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #import "OnOffViewController.h"
19 #import "CHIPUIViewUtils.h"
20 #import "DefaultsUtils.h"
21 #import "DeviceSelector.h"
24 NSString * const kCHIPNumLightOnOffCluster = @"OnOffViewController_NumLights";
26 @interface OnOffViewController ()
27 @property (nonatomic, strong) UITextField * numLightsTextField;
29 @property (nonatomic, strong) UILabel * resultLabel;
30 @property (nonatomic, strong) UILabel * titleLabel;
31 @property (nonatomic, strong) UIStackView * stackView;
33 @property (nonatomic, strong) DeviceSelector * deviceSelector;
37 @implementation OnOffViewController {
38 dispatch_queue_t _callbackQueue;
39 NSArray * _numLightsOptions;
42 // MARK: UIViewController methods
48 UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
49 [self.view addGestureRecognizer:tap];
51 [self setupUIElements];
54 - (void)dismissKeyboard
56 [_numLightsTextField resignFirstResponder];
57 [_deviceSelector resignFirstResponder];
62 - (void)setupUIElements
64 self.view.backgroundColor = UIColor.whiteColor;
67 _titleLabel = [CHIPUIViewUtils addTitle:@"On Off Cluster" toView:self.view];
68 [self setupStackView];
71 - (void)setupStackView
74 UIStackView * stackView = [UIStackView new];
75 stackView.axis = UILayoutConstraintAxisVertical;
76 stackView.distribution = UIStackViewDistributionEqualSpacing;
77 stackView.alignment = UIStackViewAlignmentLeading;
78 stackView.spacing = 30;
79 [_stackView removeFromSuperview];
80 _stackView = stackView;
81 [self.view addSubview:stackView];
83 stackView.translatesAutoresizingMaskIntoConstraints = false;
84 [stackView.topAnchor constraintEqualToAnchor:_titleLabel.bottomAnchor constant:30].active = YES;
85 [stackView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:30].active = YES;
86 [stackView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-30].active = YES;
88 // Device List and picker
89 _deviceSelector = [DeviceSelector new];
91 UILabel * deviceIDLabel = [UILabel new];
92 deviceIDLabel.text = @"Device ID:";
93 UIView * deviceIDView = [CHIPUIViewUtils viewWithLabel:deviceIDLabel textField:_deviceSelector];
94 [stackView addArrangedSubview:deviceIDView];
96 deviceIDView.translatesAutoresizingMaskIntoConstraints = false;
97 [deviceIDView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = true;
100 UILabel * numLightsLabel = [UILabel new];
101 numLightsLabel.text = @"# of light endpoints:";
102 _numLightsTextField = [UITextField new];
103 _numLightsOptions = @[ @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10" ];
104 _numLightsTextField.text
105 = CHIPGetDomainValueForKey(kCHIPToolDefaultsDomain, kCHIPNumLightOnOffCluster) ?: [_numLightsOptions objectAtIndex:0];
106 UIPickerView * numLightsPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 100, 0, 0)];
107 _numLightsTextField.inputView = numLightsPicker;
108 [numLightsPicker setDataSource:self];
109 [numLightsPicker setDelegate:self];
110 _numLightsTextField.delegate = self;
111 UIView * numLightsView = [CHIPUIViewUtils viewWithLabel:numLightsLabel textField:_numLightsTextField];
112 numLightsLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightSemibold];
114 UIToolbar * keyboardDoneButtonView = [[UIToolbar alloc] init];
115 [keyboardDoneButtonView sizeToFit];
116 UIBarButtonItem * doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done"
117 style:UIBarButtonItemStylePlain
119 action:@selector(pickerDoneClicked:)];
120 UIBarButtonItem * flexible = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
123 [keyboardDoneButtonView setItems:[NSArray arrayWithObjects:flexible, doneButton, nil]];
124 _numLightsTextField.inputAccessoryView = keyboardDoneButtonView;
126 [stackView addArrangedSubview:numLightsView];
127 numLightsView.translatesAutoresizingMaskIntoConstraints = false;
128 [numLightsView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = true;
131 [self addButtons:[self numLightClustersToShow] toStackView:stackView];
134 _resultLabel = [UILabel new];
135 _resultLabel.hidden = YES;
136 _resultLabel.font = [UIFont systemFontOfSize:17];
137 _resultLabel.textColor = UIColor.systemBlueColor;
138 _resultLabel.lineBreakMode = NSLineBreakByWordWrapping;
139 _resultLabel.numberOfLines = 0;
140 [stackView addArrangedSubview:_resultLabel];
142 _resultLabel.translatesAutoresizingMaskIntoConstraints = false;
143 [_resultLabel.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES;
144 _resultLabel.adjustsFontSizeToFitWidth = YES;
147 - (void)addButtons:(NSInteger)numButtons toStackView:(UIStackView *)stackView
149 for (int i = 1; i <= numButtons; i++) {
151 UILabel * labelLight = [UILabel new];
152 labelLight.text = [NSString stringWithFormat:@"Light (endpoint %@): ", @(i)];
153 UIButton * onButton = [UIButton new];
155 [onButton setTitle:@"On" forState:UIControlStateNormal];
156 [onButton addTarget:self action:@selector(onButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
157 UIButton * offButton = [UIButton new];
159 [offButton setTitle:@"Off" forState:UIControlStateNormal];
160 [offButton addTarget:self action:@selector(offButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
161 UIButton * toggleButton = [UIButton new];
162 toggleButton.tag = i;
163 [toggleButton setTitle:@"Toggle" forState:UIControlStateNormal];
164 [toggleButton addTarget:self action:@selector(toggleButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
166 UIStackView * stackViewButtons = [CHIPUIViewUtils stackViewWithLabel:labelLight
167 buttons:@[ onButton, offButton, toggleButton ]];
168 stackViewButtons.axis = UILayoutConstraintAxisHorizontal;
169 stackViewButtons.distribution = UIStackViewDistributionEqualSpacing;
170 stackViewButtons.alignment = UIStackViewAlignmentLeading;
171 stackViewButtons.spacing = 10;
172 [stackView addArrangedSubview:stackViewButtons];
176 - (void)updateResult:(NSString *)result
178 _resultLabel.hidden = NO;
179 _resultLabel.text = result;
182 // MARK: UIPickerView
184 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
186 NSLog(@"%@", [_numLightsOptions objectAtIndex:row]);
187 _numLightsTextField.text = [NSString stringWithFormat:@"%@", [_numLightsOptions objectAtIndex:row]];
190 - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
192 return [_numLightsOptions count];
195 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
200 - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
202 return [_numLightsOptions objectAtIndex:row];
205 // tell the picker the width of each row for a given component
206 - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
211 - (IBAction)pickerDoneClicked:(id)sender
213 CHIPSetDomainValueForKey(kCHIPToolDefaultsDomain, kCHIPNumLightOnOffCluster, _numLightsTextField.text);
214 [_numLightsTextField resignFirstResponder];
215 [self setupStackView];
218 // MARK: Cluster Setup
220 - (int)numLightClustersToShow
222 NSString * numClusters = CHIPGetDomainValueForKey(kCHIPToolDefaultsDomain, kCHIPNumLightOnOffCluster);
223 int numberOfLights = 1;
226 numberOfLights = [numClusters intValue];
228 return numberOfLights;
231 // MARK: UIButton actions
233 - (IBAction)onButtonTapped:(id)sender
235 UIButton * button = (UIButton *) sender;
236 NSInteger endpoint = button.tag;
237 [self updateResult:[NSString stringWithFormat:@"On command sent on endpoint %@", @(endpoint)]];
239 [_deviceSelector forSelectedDevices:^(uint64_t deviceId) {
240 CHIPDevice * chipDevice = CHIPGetPairedDeviceWithID(deviceId);
241 if (chipDevice != nil) {
242 CHIPOnOff * onOff = [[CHIPOnOff alloc] initWithDevice:chipDevice endpoint:endpoint queue:dispatch_get_main_queue()];
243 [onOff on:^(NSError * error, NSDictionary * values) {
244 NSString * resultString
245 = (error != nil) ? [NSString stringWithFormat:@"An error occured: 0x%02lx", error.code] : @"On command success";
246 [self updateResult:resultString];
249 [self updateResult:[NSString stringWithFormat:@"Device not found"]];
254 - (IBAction)offButtonTapped:(id)sender
256 UIButton * button = (UIButton *) sender;
257 NSInteger endpoint = button.tag;
258 [self updateResult:[NSString stringWithFormat:@"Off command sent on endpoint %@", @(endpoint)]];
260 [_deviceSelector forSelectedDevices:^(uint64_t deviceId) {
261 CHIPDevice * chipDevice = CHIPGetPairedDeviceWithID(deviceId);
262 if (chipDevice != nil) {
263 CHIPOnOff * onOff = [[CHIPOnOff alloc] initWithDevice:chipDevice endpoint:endpoint queue:dispatch_get_main_queue()];
264 [onOff off:^(NSError * error, NSDictionary * values) {
265 NSString * resultString = (error != nil) ? [NSString stringWithFormat:@"An error occured: 0x%02lx", error.code]
266 : @"Off command success";
267 [self updateResult:resultString];
270 [self updateResult:[NSString stringWithFormat:@"Device not found"]];
275 - (IBAction)toggleButtonTapped:(id)sender
277 UIButton * button = (UIButton *) sender;
278 NSInteger endpoint = button.tag;
279 [self updateResult:[NSString stringWithFormat:@"Toggle command sent on endpoint %@", @(endpoint)]];
281 [_deviceSelector forSelectedDevices:^(uint64_t deviceId) {
282 CHIPDevice * chipDevice = CHIPGetPairedDeviceWithID(deviceId);
283 if (chipDevice != nil) {
284 CHIPOnOff * onOff = [[CHIPOnOff alloc] initWithDevice:chipDevice endpoint:endpoint queue:dispatch_get_main_queue()];
285 [onOff toggle:^(NSError * error, NSDictionary * values) {
286 NSString * resultString = (error != nil) ? [NSString stringWithFormat:@"An error occured: 0x%02lx", error.code]
287 : @"Toggle command success";
288 [self updateResult:resultString];
291 [self updateResult:[NSString stringWithFormat:@"Device not found"]];