Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UI for temperature sensor in CHIPTool iOS app #3250

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
B243A6692513A73600E56FEA /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B243A6682513A73600E56FEA /* RootViewController.m */; };
B2946A4224C99D53005C87D0 /* WifiViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B2946A4124C99D53005C87D0 /* WifiViewController.m */; };
B2946A9B24C9A7BF005C87D0 /* DefaultsUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = B2946A9A24C9A7BF005C87D0 /* DefaultsUtils.m */; };
B2F51E99252DCDC000911FA5 /* TemperatureSensorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B2F51E98252DCDC000911FA5 /* TemperatureSensorViewController.m */; };
B2F53AEB245B0D140010745E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B2F53AE9245B0D140010745E /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -74,6 +75,8 @@
B2946A4124C99D53005C87D0 /* WifiViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WifiViewController.m; sourceTree = "<group>"; };
B2946A9924C9A7BF005C87D0 /* DefaultsUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DefaultsUtils.h; sourceTree = "<group>"; };
B2946A9A24C9A7BF005C87D0 /* DefaultsUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DefaultsUtils.m; sourceTree = "<group>"; };
B2F51E97252DCDC000911FA5 /* TemperatureSensorViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TemperatureSensorViewController.h; sourceTree = "<group>"; };
B2F51E98252DCDC000911FA5 /* TemperatureSensorViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TemperatureSensorViewController.m; sourceTree = "<group>"; };
B2F53AEA245B0D140010745E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = UI/Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -191,6 +194,7 @@
B204A623244E1D0600C7C0E1 /* SceneDelegate.m */,
B243A6672513A73600E56FEA /* RootViewController.h */,
B243A6682513A73600E56FEA /* RootViewController.m */,
B2F51E93252DCC9E00911FA5 /* Temperature Sensor */,
B2946A3F24C99D21005C87D0 /* Wifi */,
0C79937824858B3B0047A373 /* QRCode */,
0C79937924858B4F0047A373 /* Echo client */,
Expand All @@ -217,6 +221,15 @@
path = Wifi;
sourceTree = "<group>";
};
B2F51E93252DCC9E00911FA5 /* Temperature Sensor */ = {
isa = PBXGroup;
children = (
B2F51E97252DCDC000911FA5 /* TemperatureSensorViewController.h */,
B2F51E98252DCDC000911FA5 /* TemperatureSensorViewController.m */,
);
path = "Temperature Sensor";
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -322,6 +335,7 @@
B2946A9B24C9A7BF005C87D0 /* DefaultsUtils.m in Sources */,
991DC091247747F500C13860 /* EchoViewController.m in Sources */,
B204A621244E1D0600C7C0E1 /* AppDelegate.m in Sources */,
B2F51E99252DCDC000911FA5 /* TemperatureSensorViewController.m in Sources */,
B243A6692513A73600E56FEA /* RootViewController.m in Sources */,
B204A632244E1D0700C7C0E1 /* main.m in Sources */,
B204A624244E1D0600C7C0E1 /* SceneDelegate.m in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ + (UILabel *)addTitle:(NSString *)title toView:(UIView *)view

titleLabel.translatesAutoresizingMaskIntoConstraints = false;
[titleLabel.centerXAnchor constraintEqualToAnchor:view.centerXAnchor].active = YES;
[titleLabel.topAnchor constraintEqualToAnchor:view.topAnchor constant:100].active = YES;
[titleLabel.topAnchor constraintEqualToAnchor:view.topAnchor constant:110].active = YES;

return titleLabel;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#import "EchoViewController.h"
#import "OnOffViewController.h"
#import "QRCodeViewController.h"
#import "TemperatureSensorViewController.h"
#import "WifiViewController.h"

@implementation RootViewController
Expand All @@ -36,7 +37,7 @@ - (void)setUpTableView
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:self.tableView];
self.options = @[ @"QRCode scanner", @"Echo client", @"Light on / off cluster", @"Wifi Configuration" ];
self.options = @[ @"QRCode scanner", @"Echo client", @"Light on / off cluster", @"Temperature Sensor", @"Wifi Configuration" ];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
Expand Down Expand Up @@ -71,13 +72,22 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
[self pushLightOnOffCluster];
break;
case 3:
[self pushTemperatureSensor];
break;
case 4:
[self pushNetworkConfiguration];
break;
default:
break;
}
}

- (void)pushTemperatureSensor
{
TemperatureSensorViewController * controller = [TemperatureSensorViewController new];
[self.navigationController pushViewController:controller animated:YES];
}

- (void)pushNetworkConfiguration
{
WifiViewController * controller = [WifiViewController new];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// TemperatureSensorViewController.h
// CHIPTool
//
// Created by Shana Azria on 07/10/2020.
// Copyright © 2020 CHIP. All rights reserved.
//

#import <CHIP/CHIP.h>
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface TemperatureSensorViewController : UIViewController <CHIPDeviceControllerDelegate>

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
//
// TemperatureSensorViewController.m
// CHIPTool
//
// Created by Shana Azria on 07/10/2020.
// Copyright © 2020 CHIP. All rights reserved.
//

#import "TemperatureSensorViewController.h"
#import "CHIPUIViewUtils.h"
#import "DefaultsUtils.h"
#import <CHIP/CHIP.h>

@interface TemperatureSensorViewController ()
@property (nonatomic, strong) UILabel * temperatureLabel;
@property (nonatomic, strong) UITextField * minIntervalInSecondsTextField;
@property (nonatomic, strong) UITextField * maxIntervalInSecondsTextField;
@property (nonatomic, strong) UITextField * deltaInFahrenheitTextField;
@property (nonatomic, strong) UIButton * sendReportingSetup;

@property (nonatomic, strong) CHIPTemperatureMeasurement * chipTempMeasurement;
@property (readwrite) CHIPDevice * chipDevice;
@property (readwrite) CHIPDeviceController * chipController;

@end

@implementation TemperatureSensorViewController

// MARK: UIViewController methods

- (void)viewDidLoad
{
[super viewDidLoad];
[self setupUI];

UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];

// initialize the device controller
dispatch_queue_t callbackQueue = dispatch_queue_create("com.zigbee.chip.tempsensorvc.callback", DISPATCH_QUEUE_SERIAL);
self.chipController = [CHIPDeviceController sharedController];
[self.chipController setDelegate:self queue:callbackQueue];

uint64_t deviceID = CHIPGetNextAvailableDeviceID();
if (deviceID > 1) {
// Let's use the last device that was paired
deviceID--;
NSError * error;
self.chipDevice = [self.chipController getPairedDevice:deviceID error:&error];
self.chipTempMeasurement = [[CHIPTemperatureMeasurement alloc] initWithDevice:self.chipDevice
endpoint:1
queue:callbackQueue];
}

[self readCurrentTemperature];
}

- (IBAction)sendReportingSetup:(id)sender
{
NSLog(@"Status: User request to send reporting setup.");
[self reportFromUserEnteredSettings];
}

- (IBAction)refreshTemperatureMeasurement:(id)sender
{
NSLog(@"Status: User request to refresh temperature reading.");
[self readCurrentTemperature];
}

// MARK: UI helpers

- (void)dismissKeyboard
{
[_minIntervalInSecondsTextField resignFirstResponder];
[_maxIntervalInSecondsTextField resignFirstResponder];
[_deltaInFahrenheitTextField resignFirstResponder];
}

- (void)setupUI
{
self.view.backgroundColor = UIColor.whiteColor;

// Title
UILabel * titleLabel = [CHIPUIViewUtils addTitle:@"Temperature Sensor" toView:self.view];

// stack view
UIStackView * stackView = [UIStackView new];
stackView.axis = UILayoutConstraintAxisVertical;
stackView.distribution = UIStackViewDistributionFill;
stackView.alignment = UIStackViewAlignmentLeading;
stackView.spacing = 30;
[self.view addSubview:stackView];

stackView.translatesAutoresizingMaskIntoConstraints = false;
[stackView.topAnchor constraintEqualToAnchor:titleLabel.bottomAnchor constant:40].active = YES;
[stackView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:30].active = YES;
[stackView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-30].active = YES;

// Temperature label
_temperatureLabel = [UILabel new];
_temperatureLabel.text = @"°F";
_temperatureLabel.textColor = UIColor.blackColor;
_temperatureLabel.textAlignment = NSTextAlignmentCenter;
_temperatureLabel.font = [UIFont systemFontOfSize:50 weight:UIFontWeightThin];
[stackView addArrangedSubview:_temperatureLabel];
_temperatureLabel.translatesAutoresizingMaskIntoConstraints = false;
[_temperatureLabel.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES;

// Reporting settings
UILabel * reportingLabel = [UILabel new];
reportingLabel.text = @"Reporting Setup";
reportingLabel.textColor = UIColor.blackColor;
reportingLabel.textAlignment = NSTextAlignmentLeft;
reportingLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold];
[stackView addArrangedSubview:reportingLabel];

reportingLabel.translatesAutoresizingMaskIntoConstraints = false;
[reportingLabel.centerXAnchor constraintEqualToAnchor:stackView.centerXAnchor].active = YES;

// Min interval in seconds
_minIntervalInSecondsTextField = [UITextField new];
_minIntervalInSecondsTextField.keyboardType = UIKeyboardTypeNumberPad;
UILabel * minIntervalInSecondsLabel = [UILabel new];
[minIntervalInSecondsLabel setText:@"Min. interval (sec):"];
UIView * minIntervalInSecondsView = [CHIPUIViewUtils viewWithLabel:minIntervalInSecondsLabel
textField:_minIntervalInSecondsTextField];
[stackView addArrangedSubview:minIntervalInSecondsView];

minIntervalInSecondsView.translatesAutoresizingMaskIntoConstraints = false;
[minIntervalInSecondsView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES;

// Min interval in seconds
_maxIntervalInSecondsTextField = [UITextField new];
_maxIntervalInSecondsTextField.keyboardType = UIKeyboardTypeNumberPad;
UILabel * maxIntervalInSecondsLabel = [UILabel new];
[maxIntervalInSecondsLabel setText:@"Max. interval (sec):"];
UIView * maxIntervalInSecondsView = [CHIPUIViewUtils viewWithLabel:maxIntervalInSecondsLabel
textField:_maxIntervalInSecondsTextField];
[stackView addArrangedSubview:maxIntervalInSecondsView];

maxIntervalInSecondsView.translatesAutoresizingMaskIntoConstraints = false;
[maxIntervalInSecondsView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES;

// Delta
_deltaInFahrenheitTextField = [UITextField new];
_deltaInFahrenheitTextField.keyboardType = UIKeyboardTypeNumberPad;
UILabel * deltaInFahrenheitLabel = [UILabel new];
[deltaInFahrenheitLabel setText:@"Delta (F):"];
UIView * deltaInFahrenheitView = [CHIPUIViewUtils viewWithLabel:deltaInFahrenheitLabel textField:_deltaInFahrenheitTextField];
[stackView addArrangedSubview:deltaInFahrenheitView];

deltaInFahrenheitView.translatesAutoresizingMaskIntoConstraints = false;
[deltaInFahrenheitView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES;

// Reporting button
_sendReportingSetup = [UIButton new];
[_sendReportingSetup setTitle:@"Send reporting settings" forState:UIControlStateNormal];
[_sendReportingSetup addTarget:self action:@selector(sendReportingSetup:) forControlEvents:UIControlEventTouchUpInside];
_sendReportingSetup.backgroundColor = UIColor.systemBlueColor;
_sendReportingSetup.titleLabel.font = [UIFont systemFontOfSize:17];
_sendReportingSetup.titleLabel.textColor = [UIColor whiteColor];
_sendReportingSetup.layer.cornerRadius = 5;
_sendReportingSetup.clipsToBounds = YES;
[stackView addArrangedSubview:_sendReportingSetup];

_sendReportingSetup.translatesAutoresizingMaskIntoConstraints = false;
[_sendReportingSetup.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES;

// Refresh button
UIBarButtonItem * button = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
target:self
action:@selector(refreshTemperatureMeasurement:)];
self.navigationItem.rightBarButtonItem = button;
}

- (void)updateTempInUI:(int)newTemp
{
_temperatureLabel.text = [NSString stringWithFormat:@"%@ °F", @(newTemp)];
NSLog(@"Status: Updated temp in UI to %@", _temperatureLabel.text);
}

// MARK: CHIPTemperatureMeasurement

- (void)readCurrentTemperature
{
CHIPDeviceCallback completionHandler = ^(NSError * error) {
NSLog(@"Status: Read temperature request completed with error %@", [error description]);
};

[self.chipTempMeasurement readAttributeMeasuredValue:completionHandler];
}

- (void)reportFromUserEnteredSettings
{
CHIPDeviceCallback onCompletionCallback = ^(NSError * error) {
NSLog(@"Status: update reportAttributeMeasuredValue completed with error %@", [error description]);
};

CHIPDeviceCallback onChangeCallback = ^(NSError * error) {
NSLog(@"Status: Temp value changed with error %@", [error description]);
};
int minIntervalSeconds = [_minIntervalInSecondsTextField.text intValue] * 1000;
int maxIntervalSeconds = [_maxIntervalInSecondsTextField.text intValue] * 1000;
int deltaInFahrenheit = [_deltaInFahrenheitTextField.text intValue];

NSLog(@"Sending temp reporting values: min %@ max %@ value %@", @(minIntervalSeconds), @(maxIntervalSeconds),
@(deltaInFahrenheit));

[self.chipTempMeasurement reportAttributeMeasuredValue:onCompletionCallback
onChange:onChangeCallback
minInterval:minIntervalSeconds
maxInterval:maxIntervalSeconds
change:deltaInFahrenheit];
}

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

- (void)deviceControllerOnError:(nonnull NSError *)error
{
NSLog(@"Status: Device Controller error %@", [error description]);
}

- (void)deviceControllerOnMessage:(nonnull NSData *)message
{
NSLog(@"Status: Received a message.");
// TODO: Use callback APIs to show read response
}

@end