diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index 390352a8eeb2c8..37fa1bac62ce33 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -248,7 +248,7 @@ void Device::OnMessageReceived(const PacketHeader & header, const PayloadHeader } } -CHIP_ERROR Device::OpenPairingWindow(uint32_t timeout, bool useToken, uint16_t discriminator, SetupPayload & setupPayload) +CHIP_ERROR Device::OpenPairingWindow(uint32_t timeout, PairingWindowOption option, SetupPayload & setupPayload) { // TODO: This code is temporary, and must be updated to use the Cluster API. // Issue: https://github.com/project-chip/connectedhomeip/issues/4725 @@ -262,12 +262,13 @@ CHIP_ERROR Device::OpenPairingWindow(uint32_t timeout, bool useToken, uint16_t d ReturnErrorOnFailure(writer.Put(TLV::ProfileTag(writer.ImplicitProfileId, 1), timeout)); - if (useToken) + if (option != PairingWindowOption::kOriginalSetupCode) { - ReturnErrorOnFailure(writer.Put(TLV::ProfileTag(writer.ImplicitProfileId, 2), discriminator)); + ReturnErrorOnFailure(writer.Put(TLV::ProfileTag(writer.ImplicitProfileId, 2), setupPayload.discriminator)); PASEVerifier verifier; - ReturnErrorOnFailure(PASESession::GeneratePASEVerifier(verifier, setupPayload.setUpPINCode)); + bool randomSetupPIN = (option == PairingWindowOption::kTokenWithRandomPIN); + ReturnErrorOnFailure(PASESession::GeneratePASEVerifier(verifier, randomSetupPIN, setupPayload.setUpPINCode)); ReturnErrorOnFailure(writer.PutBytes(TLV::ProfileTag(writer.ImplicitProfileId, 3), reinterpret_cast(verifier), sizeof(verifier))); } @@ -283,7 +284,6 @@ CHIP_ERROR Device::OpenPairingWindow(uint32_t timeout, bool useToken, uint16_t d setupPayload.version = 1; setupPayload.rendezvousInformation = RendezvousInformationFlags::kBLE; - setupPayload.discriminator = discriminator; return CHIP_NO_ERROR; } diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index 5bfa3e0619c72b..bbff70daa7da6b 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -71,6 +71,13 @@ class DLL_EXPORT Device } } + enum class PairingWindowOption + { + kOriginalSetupCode, + kTokenWithRandomPIN, + kTokenWithProvidedPIN, + }; + /** * @brief * Set the delegate object which will be called when a message is received. @@ -241,15 +248,15 @@ class DLL_EXPORT Device * The device will exit the pairing mode after a successful pairing, or after the given `timeout` time. * * @param[in] timeout The pairing mode should terminate after this much time. - * @param[in] useToken Generate an onboarding token and send it to the device. The device must - * use the provided onboarding token instead of the original pairing setup PIN - * and discriminator. - * @param[in] discriminator The discriminator that the device should use for advertising and pairing. + * @param[in] option The pairing window can be opened using the original setup code, or an + * onboarding token can be generated using a random setup PIN code (or with + * the PIN code provied in the setupPayload). This argument selects one of these + * methods. * @param[out] setupPayload The setup payload corresponding to the generated onboarding token. * * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error */ - CHIP_ERROR OpenPairingWindow(uint32_t timeout, bool useToken, uint16_t discriminator, SetupPayload & setupPayload); + CHIP_ERROR OpenPairingWindow(uint32_t timeout, PairingWindowOption option, SetupPayload & setupPayload); /** * @brief diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 8006d9632930a9..02efc14e0ca1de 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -332,6 +332,10 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) { chip::Platform::MemoryFree(buffer); } + if (err != CHIP_NO_ERROR && device != nullptr) + { + ReleaseDevice(device); + } return err; } @@ -452,6 +456,17 @@ void DeviceController::ReleaseDevice(uint16_t index) } } +void DeviceController::ReleaseDeviceById(NodeId remoteDeviceId) +{ + for (uint16_t i = 0; i < kNumMaxActiveDevices; i++) + { + if (mActiveDevices[i].GetDeviceId() == remoteDeviceId) + { + ReleaseDevice(&mActiveDevices[i]); + } + } +} + void DeviceController::ReleaseAllDevices() { for (uint16_t i = 0; i < kNumMaxActiveDevices; i++) @@ -672,6 +687,7 @@ CHIP_ERROR DeviceCommissioner::PairTestDeviceWithoutSecurity(NodeId remoteDevice return err; } + CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -703,10 +719,12 @@ CHIP_ERROR DeviceCommissioner::UnpairDevice(NodeId remoteDeviceId) if (mStorageDelegate != nullptr) { PERSISTENT_KEY_OP(remoteDeviceId, kPairedDeviceKeyPrefix, key, mStorageDelegate->DeleteKeyValue(key)); - mPairedDevices.Remove(remoteDeviceId); - mPairedDevicesUpdated = true; } + mPairedDevices.Remove(remoteDeviceId); + mPairedDevicesUpdated = true; + ReleaseDeviceById(remoteDeviceId); + return CHIP_NO_ERROR; } diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 38bb3f7c9acdcd..b7534f46b3f75e 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -198,6 +198,7 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers uint16_t FindDeviceIndex(SecureSessionHandle session); uint16_t FindDeviceIndex(NodeId id); void ReleaseDevice(uint16_t index); + void ReleaseDeviceById(NodeId remoteDeviceId); CHIP_ERROR SetPairedDeviceList(const char * pairedDeviceSerializedSet); Transport::AdminId mAdminId = 0; diff --git a/src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj b/src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj index 2f18be7523e836..e9d4509059bb54 100644 --- a/src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj +++ b/src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 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 */; }; + 2C460C3225D97CB3000512D6 /* UnpairDevicesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C460C3025D97CB3000512D6 /* UnpairDevicesViewController.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, ); }; }; @@ -58,6 +59,8 @@ 2C21071425D1A8F200DDA4AD /* MultiAdminViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MultiAdminViewController.h; sourceTree = ""; }; 2C460C2225D7594B000512D6 /* DeviceSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeviceSelector.h; sourceTree = ""; }; 2C460C2325D7594B000512D6 /* DeviceSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DeviceSelector.m; sourceTree = ""; }; + 2C460C3025D97CB3000512D6 /* UnpairDevicesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UnpairDevicesViewController.m; sourceTree = ""; }; + 2C460C3125D97CB3000512D6 /* UnpairDevicesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnpairDevicesViewController.h; sourceTree = ""; }; 991DC08F247747F500C13860 /* EchoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EchoViewController.h; sourceTree = ""; }; 991DC090247747F500C13860 /* EchoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EchoViewController.m; sourceTree = ""; }; 997A639B253F93F7005C64E6 /* CHIP.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CHIP.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -144,6 +147,15 @@ path = MultiAdmin; sourceTree = ""; }; + 2C460C2F25D97CB3000512D6 /* UnpairDevices */ = { + isa = PBXGroup; + children = ( + 2C460C3025D97CB3000512D6 /* UnpairDevicesViewController.m */, + 2C460C3125D97CB3000512D6 /* UnpairDevicesViewController.h */, + ); + path = UnpairDevices; + sourceTree = ""; + }; B20252DE2459EC7600F97062 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -206,6 +218,7 @@ B232D8BF251A0EC500792CB4 /* View Controllers */ = { isa = PBXGroup; children = ( + 2C460C2F25D97CB3000512D6 /* UnpairDevices */, 2C460C2225D7594B000512D6 /* DeviceSelector.h */, 2C460C2325D7594B000512D6 /* DeviceSelector.m */, 2C21071225D1A8F200DDA4AD /* MultiAdmin */, @@ -364,6 +377,7 @@ 2C460C2425D7594B000512D6 /* DeviceSelector.m in Sources */, 2C21071525D1A8F200DDA4AD /* MultiAdminViewController.m in Sources */, B204A627244E1D0600C7C0E1 /* QRCodeViewController.m in Sources */, + 2C460C3225D97CB3000512D6 /* UnpairDevicesViewController.m in Sources */, B232D8BA2514BD0800792CB4 /* CHIPUIViewUtils.m in Sources */, B2946A9B24C9A7BF005C87D0 /* DefaultsUtils.m in Sources */, 991DC091247747F500C13860 /* EchoViewController.m in Sources */, diff --git a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.h b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.h index e21b34755e83b0..26374a83c857e7 100644 --- a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.h +++ b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.h @@ -22,6 +22,7 @@ extern NSString * const kCHIPToolDefaultsDomain; extern NSString * const kNetworkSSIDDefaultsKey; extern NSString * const kNetworkPasswordDefaultsKey; +CHIPDeviceController * InitializeCHIP(void); id CHIPGetDomainValueForKey(NSString * domain, NSString * key); void CHIPSetDomainValueForKey(NSString * domain, NSString * key, id value); void CHIPRemoveDomainValueForKey(NSString * domain, NSString * key); @@ -29,6 +30,7 @@ uint64_t CHIPGetNextAvailableDeviceID(void); void CHIPSetNextAvailableDeviceID(uint64_t id); CHIPDevice * CHIPGetPairedDevice(void); CHIPDevice * CHIPGetPairedDeviceWithID(uint64_t id); +void CHIPUnpairDeviceWithID(uint64_t deviceId); @interface CHIPToolPersistentStorageDelegate : NSObject diff --git a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m index 628c1013961a70..795cacf7f1d8f3 100644 --- a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m +++ b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m @@ -101,6 +101,14 @@ void CHIPSetNextAvailableDeviceID(uint64_t id) return [controller getPairedDevice:deviceId error:&error]; } +void CHIPUnpairDeviceWithID(uint64_t deviceId) +{ + CHIPDeviceController * controller = InitializeCHIP(); + + NSError * error; + [controller unpairDevice:deviceId error:&error]; +} + @implementation CHIPToolPersistentStorageDelegate // MARK: CHIPPersistentStorageDelegate diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/Bindings/BindingsViewController.m b/src/darwin/CHIPTool/CHIPTool/View Controllers/Bindings/BindingsViewController.m index d974220356d0bc..1c6c283c9a2d7b 100644 --- a/src/darwin/CHIPTool/CHIPTool/View Controllers/Bindings/BindingsViewController.m +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/Bindings/BindingsViewController.m @@ -122,7 +122,7 @@ - (void)setupUI - (void)_clearTextFields { - CHIPDeviceController * chipController = [CHIPDeviceController sharedController]; + CHIPDeviceController * chipController = InitializeCHIP(); _nodeIDTextField.text = [NSString stringWithFormat:@"%@", chipController.getControllerNodeId]; _endpointIDTextField.text = @"1"; _groupIDTextField.text = @"0"; diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/DeviceSelector.h b/src/darwin/CHIPTool/CHIPTool/View Controllers/DeviceSelector.h index 44bb67e6d83ddd..e10c847550a6c5 100644 --- a/src/darwin/CHIPTool/CHIPTool/View Controllers/DeviceSelector.h +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/DeviceSelector.h @@ -20,9 +20,12 @@ NS_ASSUME_NONNULL_BEGIN +typedef void (^DeviceAction)(uint64_t deviceId); + @interface DeviceSelector : UITextField - (instancetype)init; -- (CHIPDevice *)selectedDevice; +- (void)refreshDeviceList; +- (void)forSelectedDevices:(DeviceAction)action; @end NS_ASSUME_NONNULL_END diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/DeviceSelector.m b/src/darwin/CHIPTool/CHIPTool/View Controllers/DeviceSelector.m index 6b51973918c42d..770db8c69de9fe 100644 --- a/src/darwin/CHIPTool/CHIPTool/View Controllers/DeviceSelector.m +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/DeviceSelector.m @@ -21,8 +21,6 @@ #import "DefaultsUtils.h" @interface DeviceSelector () -@property (readwrite) CHIPDevice * chipDevice; -@property (readwrite) uint64_t nextDeviceID; @end @implementation DeviceSelector { @@ -34,43 +32,49 @@ @implementation DeviceSelector { - (id)init { if (self = [super init]) { - _nextDeviceID = CHIPGetNextAvailableDeviceID(); - _selectedDeviceIndex = self.nextDeviceID + 1; [self refreshDeviceList]; [self setupView]; + [self setEnabled:YES]; } return self; } - (void)refreshDeviceList { + uint64_t nextDeviceID = CHIPGetNextAvailableDeviceID(); _deviceList = [NSMutableArray new]; - for (uint64_t i = 0; i < _nextDeviceID; i++) { + for (uint64_t i = 0; i < nextDeviceID; i++) { if (CHIPGetPairedDeviceWithID(i) != nil) { [_deviceList addObject:[@(i) stringValue]]; } } _selectedDeviceIndex = 0; -} -- (void)selectDevice -{ - if ([_deviceList count] > 0) { - uint64_t deviceID = [_deviceList[_selectedDeviceIndex] intValue]; - _chipDevice = CHIPGetPairedDeviceWithID(deviceID); - } + // This will refresh the view with the updated device list + [self setEnabled:self.isEnabled]; } -- (CHIPDevice *)selectedDevice +- (void)forSelectedDevices:(DeviceAction)action { - return _chipDevice; + if ([self isEnabled]) { + if ([_deviceList count] > 0) { + uint64_t nodeId; + NSScanner * scanner = [NSScanner scannerWithString:[_deviceList objectAtIndex:_selectedDeviceIndex]]; + [scanner scanUnsignedLongLong:&nodeId]; + action(nodeId); + } + } else { + for (id device in _deviceList) { + uint64_t nodeId; + NSScanner * scanner = [NSScanner scannerWithString:device]; + [scanner scanUnsignedLongLong:&nodeId]; + action(nodeId); + } + } } - (void)setupView { - if ([_deviceList count] > 0) { - self.text = [_deviceList objectAtIndex:_selectedDeviceIndex]; - } _devicePicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 100, 0, 0)]; self.inputView = _devicePicker; [_devicePicker setDataSource:self]; @@ -79,7 +83,7 @@ - (void)setupView UIToolbar * deviceSelectButtonView = [[UIToolbar alloc] init]; [deviceSelectButtonView sizeToFit]; - UIBarButtonItem * deviceSelectButton = [[UIBarButtonItem alloc] initWithTitle:@"Select Device" + UIBarButtonItem * deviceSelectButton = [[UIBarButtonItem alloc] initWithTitle:@"Select" style:UIBarButtonItemStylePlain target:self action:@selector(deviceSelectClicked:)]; @@ -88,16 +92,26 @@ - (void)setupView action:nil]; [deviceSelectButtonView setItems:[NSArray arrayWithObjects:flexible, deviceSelectButton, nil]]; self.inputAccessoryView = deviceSelectButtonView; +} - [self selectDevice]; +- (void)setEnabled:(BOOL)enabled +{ + [super setEnabled:enabled]; + if (enabled == NO) { + self.text = [_deviceList description]; + } else if ([_deviceList count] > 0) { + self.text = [NSString stringWithFormat:@"%@", [_deviceList objectAtIndex:_selectedDeviceIndex]]; + } } // MARK: UIPickerView - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { - NSLog(@"%@", [_deviceList objectAtIndex:row]); - self.text = [NSString stringWithFormat:@"%@", [_deviceList objectAtIndex:row]]; + if ([_deviceList count] > 0) { + NSLog(@"%@", [_deviceList objectAtIndex:row]); + self.text = [NSString stringWithFormat:@"%@", [_deviceList objectAtIndex:row]]; + } } - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component @@ -112,7 +126,11 @@ - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { - return [_deviceList objectAtIndex:row]; + if ([_deviceList count] > 0) { + return [_deviceList objectAtIndex:row]; + } else { + return [NSString new]; + } } - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component @@ -122,9 +140,10 @@ - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)co - (IBAction)deviceSelectClicked:(id)sender { - _selectedDeviceIndex = [_deviceList indexOfObject:self.text]; + if ([_deviceList count] > 0) { + _selectedDeviceIndex = [_deviceList indexOfObject:self.text]; + } [self resignFirstResponder]; - [self selectDevice]; } // MARK: CHIPDeviceControllerDelegate diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/MultiAdmin/MultiAdminViewController.m b/src/darwin/CHIPTool/CHIPTool/View Controllers/MultiAdmin/MultiAdminViewController.m index 8cfd2fdf0128f1..26a54f8c9b27ba 100644 --- a/src/darwin/CHIPTool/CHIPTool/View Controllers/MultiAdmin/MultiAdminViewController.m +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/MultiAdmin/MultiAdminViewController.m @@ -26,6 +26,7 @@ @interface MultiAdminViewController () +@property (strong, nonatomic) UISwitch * openPairingOnAllDevices; @property (strong, nonatomic) UISwitch * useOnboardingTokenSwitch; @property (strong, nonatomic) UITextField * discriminatorField; @property (strong, nonatomic) UITextField * timeoutField; @@ -80,15 +81,26 @@ - (void)setupUIElements [stackView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:30].active = YES; [stackView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-30].active = YES; + // Open pairing on all devices + UILabel * pairAllDevices = [UILabel new]; + pairAllDevices.text = @"Enable pairing on all devices"; + _openPairingOnAllDevices = [UISwitch new]; + [_openPairingOnAllDevices setOn:YES]; + UIView * openPairingOnAllDevicesView = [CHIPUIViewUtils viewWithLabel:pairAllDevices toggle:_openPairingOnAllDevices]; + [_openPairingOnAllDevices addTarget:self action:@selector(pairAllDevicesButton:) forControlEvents:UIControlEventTouchUpInside]; + [stackView addArrangedSubview:openPairingOnAllDevicesView]; + openPairingOnAllDevicesView.translatesAutoresizingMaskIntoConstraints = false; + [openPairingOnAllDevicesView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES; + // Device List and selector - UILabel * deviceIDLabel = [UILabel new]; - deviceIDLabel.text = @"Device ID:"; _deviceSelector = [DeviceSelector new]; + [_deviceSelector setEnabled:NO]; + UILabel * deviceIDLabel = [UILabel new]; + deviceIDLabel.text = @"Device ID:"; 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; @@ -163,6 +175,15 @@ - (void)updateResult:(NSString *)result // MARK: UIButton actions +- (IBAction)pairAllDevicesButton:(id)sender +{ + if ([_openPairingOnAllDevices isOn]) { + [_deviceSelector setEnabled:NO]; + } else { + [_deviceSelector setEnabled:YES]; + } +} + - (IBAction)overrideControls:(id)sender { if ([_useOnboardingTokenSwitch isOn]) { @@ -178,44 +199,47 @@ - (IBAction)overrideControls:(id)sender - (IBAction)openPairingWindow:(id)sender { - // send message - CHIPDevice * chipDevice = [self.deviceSelector selectedDevice]; - if (chipDevice != nil && [chipDevice isActive]) { - NSString * timeoutStr = [self.timeoutField text]; - if (timeoutStr.length == 0) { - timeoutStr = [self.timeoutField placeholder]; - } - int timeout = [timeoutStr intValue]; - - NSString * output; - NSError * error; - if ([_useOnboardingTokenSwitch isOn]) { - NSString * discriminatorStr = [self.discriminatorField text]; - if (discriminatorStr.length == 0) { - discriminatorStr = [self.discriminatorField placeholder]; + uint32_t setupPIN = arc4random(); + [_deviceSelector forSelectedDevices:^(uint64_t deviceId) { + CHIPDevice * chipDevice = CHIPGetPairedDeviceWithID(deviceId); + // send message + if (chipDevice != nil && [chipDevice isActive]) { + NSString * timeoutStr = [self.timeoutField text]; + if (timeoutStr.length == 0) { + timeoutStr = [self.timeoutField placeholder]; } - NSInteger discriminator = [discriminatorStr intValue]; - - output = [chipDevice openPairingWindowWithPIN:timeout discriminator:discriminator error:&error]; - - if (output != nil) { - NSString * result = [@"Use Manual Code: " stringByAppendingString:output]; - [self updateResult:result]; + int timeout = [timeoutStr intValue]; + + NSString * output; + NSError * error; + if ([self.useOnboardingTokenSwitch isOn]) { + NSString * discriminatorStr = [self.discriminatorField text]; + if (discriminatorStr.length == 0) { + discriminatorStr = [self.discriminatorField placeholder]; + } + NSInteger discriminator = [discriminatorStr intValue]; + + output = [chipDevice openPairingWindowWithPIN:timeout discriminator:discriminator setupPIN:setupPIN error:&error]; + + if (output != nil) { + NSString * result = [@"Use Manual Code: " stringByAppendingString:output]; + [self updateResult:result]; + } else { + [self updateResult:@"Failed in opening the pairing window"]; + } } else { - [self updateResult:@"Failed in opening the pairing window"]; + BOOL didSend = [chipDevice openPairingWindow:timeout error:&error]; + if (didSend) { + [self updateResult:@"Scan the QR code on the device"]; + } else { + NSString * errorString = [@"Error: " stringByAppendingString:error.localizedDescription]; + [self updateResult:errorString]; + } } } else { - BOOL didSend = [chipDevice openPairingWindow:timeout error:&error]; - if (didSend) { - [self updateResult:@"Scan the QR code on the device"]; - } else { - NSString * errorString = [@"Error: " stringByAppendingString:error.localizedDescription]; - [self updateResult:errorString]; - } + [self updateResult:@"Controller not connected"]; } - } else { - [self updateResult:@"Controller not connected"]; - } + }]; } @end diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/OnOffCluster/OnOffViewController.m b/src/darwin/CHIPTool/CHIPTool/View Controllers/OnOffCluster/OnOffViewController.m index e030bced9ed7c7..b7f078e91cd22f 100644 --- a/src/darwin/CHIPTool/CHIPTool/View Controllers/OnOffCluster/OnOffViewController.m +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/OnOffCluster/OnOffViewController.m @@ -86,14 +86,13 @@ - (void)setupStackView [stackView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-30].active = YES; // Device List and picker - UILabel * deviceIDLabel = [UILabel new]; - deviceIDLabel.text = @"Device ID:"; _deviceSelector = [DeviceSelector new]; + UILabel * deviceIDLabel = [UILabel new]; + deviceIDLabel.text = @"Device ID:"; 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; @@ -233,61 +232,64 @@ - (int)numLightClustersToShow - (IBAction)onButtonTapped:(id)sender { - CHIPDevice * chipDevice = [self.deviceSelector selectedDevice]; - if (chipDevice == nil) { - [self updateResult:[NSString stringWithFormat:@"No device has been selected"]]; - return; - } - UIButton * button = (UIButton *) sender; NSInteger endpoint = button.tag; [self updateResult:[NSString stringWithFormat:@"On command sent on endpoint %@", @(endpoint)]]; - CHIPOnOff * onOff = [[CHIPOnOff alloc] initWithDevice:chipDevice endpoint:endpoint queue:dispatch_get_main_queue()]; - [onOff on:^(NSError * error, NSDictionary * values) { - NSString * resultString - = (error != nil) ? [NSString stringWithFormat:@"An error occured: 0x%02lx", error.code] : @"On command success"; - [self updateResult:resultString]; + [_deviceSelector forSelectedDevices:^(uint64_t deviceId) { + CHIPDevice * chipDevice = CHIPGetPairedDeviceWithID(deviceId); + if (chipDevice != nil) { + CHIPOnOff * onOff = [[CHIPOnOff alloc] initWithDevice:chipDevice endpoint:endpoint queue:dispatch_get_main_queue()]; + [onOff on:^(NSError * error, NSDictionary * values) { + NSString * resultString + = (error != nil) ? [NSString stringWithFormat:@"An error occured: 0x%02lx", error.code] : @"On command success"; + [self updateResult:resultString]; + }]; + } else { + [self updateResult:[NSString stringWithFormat:@"Device not found"]]; + } }]; } - (IBAction)offButtonTapped:(id)sender { - CHIPDevice * chipDevice = [self.deviceSelector selectedDevice]; - if (chipDevice == nil) { - [self updateResult:[NSString stringWithFormat:@"No device has been selected"]]; - return; - } - UIButton * button = (UIButton *) sender; NSInteger endpoint = button.tag; [self updateResult:[NSString stringWithFormat:@"Off command sent on endpoint %@", @(endpoint)]]; - CHIPOnOff * onOff = [[CHIPOnOff alloc] initWithDevice:chipDevice endpoint:endpoint queue:dispatch_get_main_queue()]; - [onOff off:^(NSError * error, NSDictionary * values) { - NSString * resultString - = (error != nil) ? [NSString stringWithFormat:@"An error occured: 0x%02lx", error.code] : @"Off command success"; - [self updateResult:resultString]; + [_deviceSelector forSelectedDevices:^(uint64_t deviceId) { + CHIPDevice * chipDevice = CHIPGetPairedDeviceWithID(deviceId); + if (chipDevice != nil) { + CHIPOnOff * onOff = [[CHIPOnOff alloc] initWithDevice:chipDevice endpoint:endpoint queue:dispatch_get_main_queue()]; + [onOff off:^(NSError * error, NSDictionary * values) { + NSString * resultString = (error != nil) ? [NSString stringWithFormat:@"An error occured: 0x%02lx", error.code] + : @"Off command success"; + [self updateResult:resultString]; + }]; + } else { + [self updateResult:[NSString stringWithFormat:@"Device not found"]]; + } }]; } - (IBAction)toggleButtonTapped:(id)sender { - CHIPDevice * chipDevice = [self.deviceSelector selectedDevice]; - if (chipDevice == nil) { - [self updateResult:[NSString stringWithFormat:@"No device has been selected"]]; - return; - } - UIButton * button = (UIButton *) sender; NSInteger endpoint = button.tag; [self updateResult:[NSString stringWithFormat:@"Toggle command sent on endpoint %@", @(endpoint)]]; - CHIPOnOff * onOff = [[CHIPOnOff alloc] initWithDevice:chipDevice endpoint:endpoint queue:dispatch_get_main_queue()]; - [onOff toggle:^(NSError * error, NSDictionary * values) { - NSString * resultString - = (error != nil) ? [NSString stringWithFormat:@"An error occured: 0x%02lx", error.code] : @"Toggle command success"; - [self updateResult:resultString]; + [_deviceSelector forSelectedDevices:^(uint64_t deviceId) { + CHIPDevice * chipDevice = CHIPGetPairedDeviceWithID(deviceId); + if (chipDevice != nil) { + CHIPOnOff * onOff = [[CHIPOnOff alloc] initWithDevice:chipDevice endpoint:endpoint queue:dispatch_get_main_queue()]; + [onOff toggle:^(NSError * error, NSDictionary * values) { + NSString * resultString = (error != nil) ? [NSString stringWithFormat:@"An error occured: 0x%02lx", error.code] + : @"Toggle command success"; + [self updateResult:resultString]; + }]; + } else { + [self updateResult:[NSString stringWithFormat:@"Device not found"]]; + } }]; } diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/QRCode/QRCodeViewController.m b/src/darwin/CHIPTool/CHIPTool/View Controllers/QRCode/QRCodeViewController.m index b21f29eeafc2b0..44236d13609b70 100644 --- a/src/darwin/CHIPTool/CHIPTool/View Controllers/QRCode/QRCodeViewController.m +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/QRCode/QRCodeViewController.m @@ -20,6 +20,7 @@ // local imports #import "CHIPUIViewUtils.h" #import "DefaultsUtils.h" +#import "DeviceSelector.h" #import // system imports @@ -68,9 +69,10 @@ @interface QRCodeViewController () @property (strong, nonatomic) UILabel * errorLabel; @property (readwrite) CHIPDeviceController * chipController; -@property (readonly) CHIPToolPersistentStorageDelegate * persistentStorage; @property (strong, nonatomic) NFCNDEFReaderSession * session; +@property (strong, nonatomic) CHIPSetupPayload * setupPayload; +@property (strong, nonatomic) DeviceSelector * deviceList; @end @implementation QRCodeViewController { @@ -148,6 +150,17 @@ - (void)setupUI [_nfcScanButton.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES; [_nfcScanButton.heightAnchor constraintEqualToConstant:40].active = YES; + _deviceList = [DeviceSelector new]; + [_deviceList setEnabled:NO]; + + UILabel * deviceIDLabel = [UILabel new]; + deviceIDLabel.text = @"Paired Devices:"; + UIView * deviceIDView = [CHIPUIViewUtils viewWithLabel:deviceIDLabel textField:_deviceList]; + [stackView addArrangedSubview:deviceIDView]; + + deviceIDView.translatesAutoresizingMaskIntoConstraints = false; + [deviceIDView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = true; + // Results view _setupPayloadView = [UIView new]; [self.view addSubview:_setupPayloadView]; @@ -289,12 +302,9 @@ - (void)viewDidLoad [super viewDidLoad]; [self setupUI]; - _persistentStorage = [[CHIPToolPersistentStorageDelegate alloc] init]; - dispatch_queue_t callbackQueue = dispatch_queue_create("com.zigbee.chip.qrcodevc.callback", DISPATCH_QUEUE_SERIAL); - self.chipController = [CHIPDeviceController sharedController]; + self.chipController = InitializeCHIP(); [self.chipController setPairingDelegate:self queue:callbackQueue]; - [self.chipController setPersistentStorageDelegate:_persistentStorage queue:callbackQueue]; UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)]; [self.view addGestureRecognizer:tap]; @@ -367,6 +377,13 @@ - (void)onNetworkCredentialsRequested:(CHIPNetworkCredentialType)type } } +- (void)onPairingComplete:(NSError *)error +{ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, DISPATCH_TIME_NOW), dispatch_get_main_queue(), ^{ + [self->_deviceList refreshDeviceList]; + }); +} + // MARK: UI Helper methods - (void)manualCodeInitialState @@ -600,9 +617,10 @@ - (void)handleRendezVousBLE:(uint16_t)discriminator setupPINCode:(uint32_t)setup { NSError * error; uint64_t deviceID = CHIPGetNextAvailableDeviceID(); - [self.chipController pairDevice:deviceID discriminator:discriminator setupPINCode:setupPINCode error:&error]; - deviceID++; - CHIPSetNextAvailableDeviceID(deviceID); + if ([self.chipController pairDevice:deviceID discriminator:discriminator setupPINCode:setupPINCode error:&error]) { + deviceID++; + CHIPSetNextAvailableDeviceID(deviceID); + } } - (void)handleRendezVousWiFi:(NSString *)name @@ -669,12 +687,12 @@ - (void)scannedQRCode:(NSString *)qrCode }); CHIPQRCodeSetupPayloadParser * parser = [[CHIPQRCodeSetupPayloadParser alloc] initWithBase41Representation:qrCode]; NSError * error; - CHIPSetupPayload * payload = [parser populatePayload:&error]; + _setupPayload = [parser populatePayload:&error]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ [self postScanningQRCodeState]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, INDICATOR_DELAY), dispatch_get_main_queue(), ^{ - [self displayQRCodeInSetupPayloadView:payload withError:error]; + [self displayQRCodeInSetupPayloadView:self->_setupPayload withError:error]; }); }); } @@ -743,9 +761,9 @@ - (IBAction)enteredManualCode:(id)sender CHIPManualSetupPayloadParser * parser = [[CHIPManualSetupPayloadParser alloc] initWithDecimalStringRepresentation:decimalString]; NSError * error; - CHIPSetupPayload * payload = [parser populatePayload:&error]; + _setupPayload = [parser populatePayload:&error]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, INDICATOR_DELAY), dispatch_get_main_queue(), ^{ - [self displayManualCodeInSetupPayloadView:payload decimalString:decimalString withError:error]; + [self displayManualCodeInSetupPayloadView:self->_setupPayload decimalString:decimalString withError:error]; }); [_manualCodeTextField resignFirstResponder]; } diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/RootViewController.m b/src/darwin/CHIPTool/CHIPTool/View Controllers/RootViewController.m index ad3c80174d5bc4..cc0ea6e6f4f467 100644 --- a/src/darwin/CHIPTool/CHIPTool/View Controllers/RootViewController.m +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/RootViewController.m @@ -22,6 +22,7 @@ #import "OnOffViewController.h" #import "QRCodeViewController.h" #import "TemperatureSensorViewController.h" +#import "UnpairDevicesViewController.h" #import "WifiViewController.h" @implementation RootViewController @@ -41,7 +42,7 @@ - (void)setUpTableView [self.view addSubview:self.tableView]; self.options = @[ @"QRCode scanner", @"Echo client", @"Light on / off cluster", @"Temperature Sensor", @"Bindings", @"Wifi Configuration", - @"Enable Pairing" + @"Enable Pairing", @"Unpair Devices" ]; } @@ -88,6 +89,9 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath case 6: [self pushMultiAdmin]; break; + case 7: + [self pushUnpairDevices]; + break; default: break; } @@ -134,4 +138,10 @@ - (void)pushLightOnOffCluster OnOffViewController * controller = [OnOffViewController new]; [self.navigationController pushViewController:controller animated:YES]; } + +- (void)pushUnpairDevices +{ + UnpairDevicesViewController * controller = [UnpairDevicesViewController new]; + [self.navigationController pushViewController:controller animated:YES]; +} @end diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/UnpairDevices/UnpairDevicesViewController.h b/src/darwin/CHIPTool/CHIPTool/View Controllers/UnpairDevices/UnpairDevicesViewController.h new file mode 100644 index 00000000000000..c6091a44e51c8e --- /dev/null +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/UnpairDevices/UnpairDevicesViewController.h @@ -0,0 +1,26 @@ +/** + * + * 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 +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UnpairDevicesViewController : UIViewController +@end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/UnpairDevices/UnpairDevicesViewController.m b/src/darwin/CHIPTool/CHIPTool/View Controllers/UnpairDevices/UnpairDevicesViewController.m new file mode 100644 index 00000000000000..1b6a6517222e76 --- /dev/null +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/UnpairDevices/UnpairDevicesViewController.m @@ -0,0 +1,139 @@ +/** + * + * 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 "UnpairDevicesViewController.h" +#import "CHIPUIViewUtils.h" +#import "DefaultsUtils.h" +#import "DeviceSelector.h" +#import + +@interface UnpairDevicesViewController () +@property (strong, nonatomic) UISwitch * unpairAllDevicesSwitch; +@property (nonatomic, strong) UILabel * unpairLabel; +@property (nonatomic, strong) UILabel * titleLabel; +@property (nonatomic, strong) UIStackView * stackView; +@property (nonatomic, strong) DeviceSelector * deviceSelector; +@property (strong, nonatomic) UIButton * unpairButton; +@end + +@implementation UnpairDevicesViewController + +// MARK: UIViewController methods + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)]; + [self.view addGestureRecognizer:tap]; + + [self setupUIElements]; +} + +- (void)dismissKeyboard +{ + [_deviceSelector resignFirstResponder]; +} + +// MARK: UI Setup + +- (void)setupUIElements +{ + self.view.backgroundColor = UIColor.whiteColor; + + // Title + _titleLabel = [CHIPUIViewUtils addTitle:@"Unpair Devices" toView:self.view]; + [self setupStackView]; +} + +- (void)setupStackView +{ + // stack view + UIStackView * stackView = [UIStackView new]; + stackView.axis = UILayoutConstraintAxisVertical; + stackView.distribution = UIStackViewDistributionEqualSpacing; + stackView.alignment = UIStackViewAlignmentLeading; + stackView.spacing = 30; + [_stackView removeFromSuperview]; + _stackView = stackView; + [self.view addSubview:stackView]; + + stackView.translatesAutoresizingMaskIntoConstraints = false; + [stackView.topAnchor constraintEqualToAnchor:_titleLabel.bottomAnchor constant:30].active = YES; + [stackView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:30].active = YES; + [stackView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-30].active = YES; + + // Unpair All Devices + UILabel * unpairAllDevices = [UILabel new]; + unpairAllDevices.text = @"Unpair all devices"; + _unpairAllDevicesSwitch = [UISwitch new]; + [_unpairAllDevicesSwitch setOn:YES]; + UIView * openPairingOnAllDevicesView = [CHIPUIViewUtils viewWithLabel:unpairAllDevices toggle:_unpairAllDevicesSwitch]; + [_unpairAllDevicesSwitch addTarget:self action:@selector(unpairAllDevicesButton:) forControlEvents:UIControlEventTouchUpInside]; + [stackView addArrangedSubview:openPairingOnAllDevicesView]; + openPairingOnAllDevicesView.translatesAutoresizingMaskIntoConstraints = false; + [openPairingOnAllDevicesView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES; + + // Device List and picker + _deviceSelector = [DeviceSelector new]; + [_deviceSelector setEnabled:NO]; + + UILabel * deviceIDLabel = [UILabel new]; + deviceIDLabel.text = @"Device ID:"; + UIView * deviceIDView = [CHIPUIViewUtils viewWithLabel:deviceIDLabel textField:_deviceSelector]; + [stackView addArrangedSubview:deviceIDView]; + + deviceIDView.translatesAutoresizingMaskIntoConstraints = false; + [deviceIDView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = true; + + // Unpair devices button + _unpairButton = [UIButton new]; + [_unpairButton setTitle:@"Unpair Devices" forState:UIControlStateNormal]; + [_unpairButton addTarget:self action:@selector(unpairSelectedDevices:) forControlEvents:UIControlEventTouchUpInside]; + _unpairButton.backgroundColor = UIColor.systemBlueColor; + _unpairButton.titleLabel.font = [UIFont systemFontOfSize:17]; + _unpairButton.titleLabel.textColor = [UIColor whiteColor]; + _unpairButton.layer.cornerRadius = 5; + _unpairButton.clipsToBounds = YES; + [stackView addArrangedSubview:_unpairButton]; + + _unpairButton.translatesAutoresizingMaskIntoConstraints = false; + [_unpairButton.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES; +} + +// MARK: UIButton actions + +- (IBAction)unpairAllDevicesButton:(id)sender +{ + if ([_unpairAllDevicesSwitch isOn]) { + [_deviceSelector setEnabled:NO]; + } else { + [_deviceSelector setEnabled:YES]; + } +} + +- (IBAction)unpairSelectedDevices:(id)sender +{ + [_deviceSelector forSelectedDevices:^(uint64_t deviceId) { + CHIPUnpairDeviceWithID(deviceId); + }]; + + [_deviceSelector refreshDeviceList]; + //[_deviceSelector setEnabled:NO]; +} + +@end diff --git a/src/darwin/Framework/CHIP/CHIPDevice.h b/src/darwin/Framework/CHIP/CHIPDevice.h index 7ffc766969e9da..b3a1dba6c27796 100644 --- a/src/darwin/Framework/CHIP/CHIPDevice.h +++ b/src/darwin/Framework/CHIP/CHIPDevice.h @@ -27,6 +27,7 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)openPairingWindow:(NSTimeInterval)duration error:(NSError * __autoreleasing *)error; - (NSString *)openPairingWindowWithPIN:(NSTimeInterval)duration discriminator:(NSUInteger)discriminator + setupPIN:(NSUInteger)setupPIN error:(NSError * __autoreleasing *)error; - (BOOL)isActive; diff --git a/src/darwin/Framework/CHIP/CHIPDevice.mm b/src/darwin/Framework/CHIP/CHIPDevice.mm index 0fdd52a201e407..2881694ff83a3a 100644 --- a/src/darwin/Framework/CHIP/CHIPDevice.mm +++ b/src/darwin/Framework/CHIP/CHIPDevice.mm @@ -58,7 +58,8 @@ - (BOOL)openPairingWindow:(NSTimeInterval)duration error:(NSError * __autoreleas chip::SetupPayload setupPayload; [self.lock lock]; - err = self.cppDevice->OpenPairingWindow(duration, false, 0, setupPayload); + err = self.cppDevice->OpenPairingWindow( + duration, chip::Controller::Device::PairingWindowOption::kOriginalSetupCode, setupPayload); [self.lock unlock]; if (err != CHIP_NO_ERROR) { @@ -74,11 +75,12 @@ - (BOOL)openPairingWindow:(NSTimeInterval)duration error:(NSError * __autoreleas - (NSString *)openPairingWindowWithPIN:(NSTimeInterval)duration discriminator:(NSUInteger)discriminator + setupPIN:(NSUInteger)setupPIN error:(NSError * __autoreleasing *)error { CHIP_ERROR err = CHIP_NO_ERROR; - uint16_t u16Descriminator = 0; + chip::SetupPayload setupPayload; if (discriminator > 0xfff) { CHIP_LOG_ERROR("Error: Discriminator %tu is too large. Max value %d", discriminator, 0xfff); @@ -87,13 +89,15 @@ - (NSString *)openPairingWindowWithPIN:(NSTimeInterval)duration } return nil; } else { - u16Descriminator = (uint16_t) discriminator; + setupPayload.discriminator = (uint16_t) discriminator; } - chip::SetupPayload setupPayload; + setupPIN &= ((1 << chip::kSetupPINCodeFieldLengthInBits) - 1); + setupPayload.setUpPINCode = (uint32_t) setupPIN; [self.lock lock]; - err = self.cppDevice->OpenPairingWindow(duration, true, u16Descriminator, setupPayload); + err = self.cppDevice->OpenPairingWindow( + duration, chip::Controller::Device::PairingWindowOption::kTokenWithProvidedPIN, setupPayload); [self.lock unlock]; if (err != CHIP_NO_ERROR) { diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.mm b/src/darwin/Framework/CHIP/CHIPDeviceController.mm index 27a50286339076..25d90a10e31faf 100644 --- a/src/darwin/Framework/CHIP/CHIPDeviceController.mm +++ b/src/darwin/Framework/CHIP/CHIPDeviceController.mm @@ -192,11 +192,14 @@ - (void)setPairingDelegate:(id)delegate queue:(dispat - (void)setPersistentStorageDelegate:(id)delegate queue:(dispatch_queue_t)queue { - [self.lock lock]; - _persistentStorageDelegateBridge->setFrameworkDelegate(delegate, queue); - [self.lock unlock]; - _persistentStorageDelegateBridge->SetKeyValue( - CHIP_COMMISSIONER_DEVICE_ID_KEY, [[NSString stringWithFormat:@"%llx", _localDeviceId] UTF8String]); + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self.lock lock]; + _persistentStorageDelegateBridge->setFrameworkDelegate(delegate, queue); + [self.lock unlock]; + _persistentStorageDelegateBridge->SetKeyValue( + CHIP_COMMISSIONER_DEVICE_ID_KEY, [[NSString stringWithFormat:@"%llx", _localDeviceId] UTF8String]); + }); } - (void)sendWiFiCredentials:(NSString *)ssid password:(NSString *)password diff --git a/src/transport/PASESession.cpp b/src/transport/PASESession.cpp index 961097362a319c..b1c35f222b80dc 100644 --- a/src/transport/PASESession.cpp +++ b/src/transport/PASESession.cpp @@ -210,12 +210,19 @@ CHIP_ERROR PASESession::ComputePASEVerifier(uint32_t setUpPINCode, uint32_t pbkd sizeof(PASEVerifier), &verifier[0][0]); } -CHIP_ERROR PASESession::GeneratePASEVerifier(PASEVerifier & verifier, uint32_t & setupPIN) +CHIP_ERROR PASESession::GeneratePASEVerifier(PASEVerifier & verifier, bool useRandomPIN, uint32_t & setupPIN) { - ReturnErrorOnFailure(DRBG_get_bytes(reinterpret_cast(&setupPIN), sizeof(setupPIN))); + if (useRandomPIN) + { + ReturnErrorOnFailure(DRBG_get_bytes(reinterpret_cast(&setupPIN), sizeof(setupPIN))); - // Use only kSetupPINCodeFieldLengthInBits bits out of the code - setupPIN &= ((1 << kSetupPINCodeFieldLengthInBits) - 1); + // Use only kSetupPINCodeFieldLengthInBits bits out of the code + setupPIN &= ((1 << kSetupPINCodeFieldLengthInBits) - 1); + } + else if (setupPIN >= (1 << kSetupPINCodeFieldLengthInBits)) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } return PASESession::ComputePASEVerifier(setupPIN, kSpake2p_Iteration_Count, reinterpret_cast(kSpake2pKeyExchangeSalt), diff --git a/src/transport/PASESession.h b/src/transport/PASESession.h index 12b3baa9b58158..4f563b4efdb4d9 100644 --- a/src/transport/PASESession.h +++ b/src/transport/PASESession.h @@ -136,10 +136,17 @@ class DLL_EXPORT PASESession CHIP_ERROR Pair(const Transport::PeerAddress peerAddress, const PASEVerifier & verifier, Optional myNodeId, NodeId peerNodeId, uint16_t myKeyId, SessionEstablishmentDelegate * delegate); - static CHIP_ERROR ComputePASEVerifier(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen, - PASEVerifier & verifier); - - static CHIP_ERROR GeneratePASEVerifier(PASEVerifier & verifier, uint32_t & setupPIN); + /** + * @brief + * Generate a new PASE verifier. + * + * @param verifier The generated PASE verifier + * @param useRandomPIN Generate a random setup PIN, if true. Else, use the provided PIN + * @param setupPIN Provided setup PIN (if useRandomPIN is false), or the generated PIN + * + * @return CHIP_ERROR The result of PASE verifier generation + */ + static CHIP_ERROR GeneratePASEVerifier(PASEVerifier & verifier, bool useRandomPIN, uint32_t & setupPIN); /** * @brief @@ -225,6 +232,9 @@ class DLL_EXPORT PASESession CHIP_ERROR Init(Optional myNodeId, uint16_t myKeyId, uint32_t setupCode, SessionEstablishmentDelegate * delegate); + static CHIP_ERROR ComputePASEVerifier(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen, + PASEVerifier & verifier); + CHIP_ERROR SetupSpake2p(uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen); CHIP_ERROR SendPBKDFParamRequest();