diff --git a/src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj b/src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj index 3676673fb42d03..3502944d991e0b 100644 --- a/src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj +++ b/src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj @@ -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 */ @@ -74,6 +75,8 @@ B2946A4124C99D53005C87D0 /* WifiViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WifiViewController.m; sourceTree = ""; }; B2946A9924C9A7BF005C87D0 /* DefaultsUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DefaultsUtils.h; sourceTree = ""; }; B2946A9A24C9A7BF005C87D0 /* DefaultsUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DefaultsUtils.m; sourceTree = ""; }; + B2F51E97252DCDC000911FA5 /* TemperatureSensorViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TemperatureSensorViewController.h; sourceTree = ""; }; + B2F51E98252DCDC000911FA5 /* TemperatureSensorViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TemperatureSensorViewController.m; sourceTree = ""; }; B2F53AEA245B0D140010745E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = UI/Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXFileReference section */ @@ -191,6 +194,7 @@ B204A623244E1D0600C7C0E1 /* SceneDelegate.m */, B243A6672513A73600E56FEA /* RootViewController.h */, B243A6682513A73600E56FEA /* RootViewController.m */, + B2F51E93252DCC9E00911FA5 /* Temperature Sensor */, B2946A3F24C99D21005C87D0 /* Wifi */, 0C79937824858B3B0047A373 /* QRCode */, 0C79937924858B4F0047A373 /* Echo client */, @@ -217,6 +221,15 @@ path = Wifi; sourceTree = ""; }; + B2F51E93252DCC9E00911FA5 /* Temperature Sensor */ = { + isa = PBXGroup; + children = ( + B2F51E97252DCDC000911FA5 /* TemperatureSensorViewController.h */, + B2F51E98252DCDC000911FA5 /* TemperatureSensorViewController.m */, + ); + path = "Temperature Sensor"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -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 */, diff --git a/src/darwin/CHIPTool/CHIPTool/UI Helpers/CHIPUIViewUtils.m b/src/darwin/CHIPTool/CHIPTool/UI Helpers/CHIPUIViewUtils.m index eecde55e2c2c37..d0cfadb835de18 100644 --- a/src/darwin/CHIPTool/CHIPTool/UI Helpers/CHIPUIViewUtils.m +++ b/src/darwin/CHIPTool/CHIPTool/UI Helpers/CHIPUIViewUtils.m @@ -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; } diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/RootViewController.m b/src/darwin/CHIPTool/CHIPTool/View Controllers/RootViewController.m index b436ba69d84172..0d852cdbbb35b5 100644 --- a/src/darwin/CHIPTool/CHIPTool/View Controllers/RootViewController.m +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/RootViewController.m @@ -19,6 +19,7 @@ #import "EchoViewController.h" #import "OnOffViewController.h" #import "QRCodeViewController.h" +#import "TemperatureSensorViewController.h" #import "WifiViewController.h" @implementation RootViewController @@ -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 @@ -71,6 +72,9 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath [self pushLightOnOffCluster]; break; case 3: + [self pushTemperatureSensor]; + break; + case 4: [self pushNetworkConfiguration]; break; default: @@ -78,6 +82,12 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath } } +- (void)pushTemperatureSensor +{ + TemperatureSensorViewController * controller = [TemperatureSensorViewController new]; + [self.navigationController pushViewController:controller animated:YES]; +} + - (void)pushNetworkConfiguration { WifiViewController * controller = [WifiViewController new]; diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/Temperature Sensor/TemperatureSensorViewController.h b/src/darwin/CHIPTool/CHIPTool/View Controllers/Temperature Sensor/TemperatureSensorViewController.h new file mode 100644 index 00000000000000..7e8f09018365e8 --- /dev/null +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/Temperature Sensor/TemperatureSensorViewController.h @@ -0,0 +1,18 @@ +// +// TemperatureSensorViewController.h +// CHIPTool +// +// Created by Shana Azria on 07/10/2020. +// Copyright © 2020 CHIP. All rights reserved. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TemperatureSensorViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/Temperature Sensor/TemperatureSensorViewController.m b/src/darwin/CHIPTool/CHIPTool/View Controllers/Temperature Sensor/TemperatureSensorViewController.m new file mode 100644 index 00000000000000..e00581423a59b4 --- /dev/null +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/Temperature Sensor/TemperatureSensorViewController.m @@ -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 + +@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