| /* |
| * |
| * Copyright (c) 2013-2017 Nest Labs, Inc. |
| * Copyright (c) 2018-2020 Google LLC. |
| * All rights reserved. |
| * |
| * 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. |
| */ |
| |
| /** |
| * @file |
| * This file implements NLWeaveDeviceManager interface |
| * |
| */ |
| |
| #import <Foundation/Foundation.h> |
| #import "NLWeaveStack.h" |
| #import "NLLogging.h" |
| |
| #include <Weave/Core/WeaveError.h> |
| |
| #include <Weave/Support/CodeUtils.h> |
| |
| #include <WeaveDeviceManager.h> |
| |
| #include <net/if.h> |
| |
| #import "NLWeaveBleDelegate.h" |
| #import "NLWeaveDeviceManager_Protected.h" |
| #import "NLWeaveDeviceDescriptor_Protected.h" |
| #import "NLNetworkInfo_Protected.h" |
| #import "NLProfileStatusError.h" |
| #import "NLWeaveError_Protected.h" |
| #include <Weave/Profiles/device-description/DeviceDescription.h> |
| #import "NLIdentifyDeviceCriteria_Protected.h" |
| #import "Base64Encoding.h" |
| #import "NLWirelessRegConfig_Protected.h" |
| |
| static void onIdentifyDeviceComplete(nl::Weave::DeviceManager::WeaveDeviceManager * deviceMgr, void * appReqState, |
| const nl::Weave::DeviceManager::DeviceDescription::WeaveDeviceDescriptor * devdesc); |
| |
| @interface NLWeaveDeviceManager () { |
| nl::Weave::DeviceManager::WeaveDeviceManager * _mWeaveCppDM; |
| dispatch_queue_t _mWeaveWorkQueue; |
| dispatch_queue_t _mAppCallbackQueue; |
| |
| // Note that these context variables are independent from context variables in the C++ Weave Device Manager, |
| // for the C++ Weave Device Manager only takes one pointer as the app context, which is not enough to hold all |
| // context information we need. |
| WDMCompletionBlock _mCompletionHandler; |
| WDMFailureBlock _mFailureHandler; |
| NSString * _mRequestName; |
| |
| CBPeripheral * _blePeripheral; |
| } |
| |
| - (NSString *)GetCurrentRequest; |
| |
| @end |
| |
| @implementation NLWeaveDeviceManager |
| |
| @synthesize blePeripheral = _blePeripheral; |
| @synthesize resultCallbackQueue = _mAppCallbackQueue; |
| |
| /** |
| @note |
| This function can only be called by the ARC runtime |
| */ |
| - (void)dealloc |
| { |
| // This method can only be called by ARC |
| // Let's not rely on this unpredictable mechanism for de-initialization |
| // application shall call ShutdownStack if it want to cleanly destroy everything before application termination |
| WDM_LOG_METHOD_SIG(); |
| |
| [self MarkTransactionCompleted]; |
| |
| _mRequestName = @"dealloc-Shutdown"; |
| |
| // we need to force the queue to be Weave work queue, as dealloc could be |
| // called at random queues (most probably from UI, when the app de-reference this device manager) |
| dispatch_sync(_mWeaveWorkQueue, ^() { |
| [self Shutdown_Internal]; |
| }); |
| } |
| |
| - (instancetype)init:(NSString *)name |
| weaveWorkQueue:(dispatch_queue_t)weaveWorkQueue |
| appCallbackQueue:(dispatch_queue_t)appCallbackQueue |
| exchangeMgr:(nl::Weave::WeaveExchangeManager *)exchangeMgr |
| securityMgr:(nl::Weave::WeaveSecurityManager *)securityMgr |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| self = [super init]; |
| VerifyOrExit(nil != self, err = WEAVE_ERROR_NO_MEMORY); |
| |
| _mWeaveWorkQueue = weaveWorkQueue; |
| _mAppCallbackQueue = appCallbackQueue; |
| |
| _name = name; |
| |
| _mWeaveCppDM = new nl::Weave::DeviceManager::WeaveDeviceManager(); |
| VerifyOrExit(NULL != _mWeaveCppDM, err = WEAVE_ERROR_NO_MEMORY); |
| |
| err = _mWeaveCppDM->Init(exchangeMgr, securityMgr); |
| SuccessOrExit(err); |
| |
| _mWeaveCppDM->SetConnectTimeout(60000); |
| |
| // simple bridge shall not increase our reference count |
| _mWeaveCppDM->AppState = (__bridge void *) self; |
| |
| [self MarkTransactionCompleted]; |
| |
| exit: |
| id result = nil; |
| if (WEAVE_NO_ERROR == err) { |
| result = self; |
| } else { |
| WDM_LOG_ERROR(@"Error in init : (%d) %@\n", err, [NSString stringWithUTF8String:nl::ErrorStr(err)]); |
| |
| [self Shutdown_Internal]; |
| } |
| return result; |
| } |
| |
| - (void)MarkTransactionCompleted |
| { |
| _mRequestName = nil; |
| _mCompletionHandler = nil; |
| _mFailureHandler = nil; |
| } |
| |
| - (NSString *)GetCurrentRequest |
| { |
| return _mRequestName; |
| } |
| |
| - (void)DispatchAsyncFailureBlock:(WEAVE_ERROR)code taskName:(NSString *)taskName handler:(WDMFailureBlock)handler |
| { |
| NSError * error = |
| [NSError errorWithDomain:@"com.nest.error" |
| code:code |
| userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithUTF8String:nl::ErrorStr(code)], |
| @"error", nil]]; |
| [self DispatchAsyncFailureBlockWithError:error taskName:taskName handler:handler]; |
| } |
| |
| - (void)DispatchAsyncFailureBlockWithError:(NSError *)error taskName:(NSString *)taskName handler:(WDMFailureBlock)handler |
| { |
| if (NULL != handler) { |
| // we use async because we don't need to wait for completion of this final completion report |
| dispatch_async(_mAppCallbackQueue, ^() { |
| WDM_LOG_DEBUG(@"%@: Calling failure handler for %@", _name, taskName); |
| handler(_owner, error); |
| }); |
| } else { |
| WDM_LOG_DEBUG(@"%@: Skipping failure handler for %@", _name, taskName); |
| } |
| } |
| |
| - (void)DispatchAsyncDefaultFailureBlockWithCode:(WEAVE_ERROR)code |
| { |
| NSError * error = [NSError errorWithDomain:@"com.nest.error" code:code userInfo:nil]; |
| [self DispatchAsyncDefaultFailureBlock:error]; |
| } |
| |
| - (void)DispatchAsyncDefaultFailureBlock:(NSError *)error |
| { |
| NSString * taskName = _mRequestName; |
| WDMFailureBlock failureHandler = _mFailureHandler; |
| |
| [self MarkTransactionCompleted]; |
| [self DispatchAsyncFailureBlockWithError:error taskName:taskName handler:failureHandler]; |
| } |
| |
| - (void)DispatchAsyncCompletionBlock:(id)data |
| { |
| WDMCompletionBlock completionHandler = _mCompletionHandler; |
| |
| [self MarkTransactionCompleted]; |
| |
| if (nil != completionHandler) { |
| dispatch_async(_mAppCallbackQueue, ^() { |
| completionHandler(_owner, data); |
| }); |
| } |
| } |
| |
| - (void)DispatchAsyncResponseBlock:(id)data |
| { |
| WDMCompletionBlock completionHandler = _mCompletionHandler; |
| |
| if (nil != completionHandler) { |
| dispatch_async(_mAppCallbackQueue, ^() { |
| completionHandler(_owner, data); |
| }); |
| } |
| } |
| |
| - (NSString *)toErrorString:(WEAVE_ERROR)err |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| __block NSString * msg = nil; |
| |
| dispatch_sync(_mWeaveWorkQueue, ^() { |
| msg = [NSString stringWithUTF8String:nl::ErrorStr(err)]; |
| }); |
| |
| return msg; |
| } |
| |
| - (NSString *)statusReportToString:(NSUInteger)profileId statusCode:(NSInteger)statusCode |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * report = nil; |
| |
| const char * result = nl::StatusReportStr((uint32_t) profileId, statusCode); |
| |
| if (result) { |
| report = [NSString stringWithUTF8String:result]; |
| } |
| |
| return report; |
| } |
| |
| - (void)Shutdown_Internal |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| // there is no need to release Objective C objects, as we have ARC for them |
| if (_mWeaveCppDM) { |
| WDM_LOG_ERROR(@"Shutdown C++ Weave Device Manager"); |
| |
| _mWeaveCppDM->Shutdown(); |
| |
| delete _mWeaveCppDM; |
| _mWeaveCppDM = NULL; |
| |
| if (_blePeripheral) |
| { |
| // autoclose is disabled when running weave connect ble, close ble after woble stack is |
| // destroyed |
| // release reference to the CBPeripheral |
| // since device manager is the only one who holds a strong reference to this peripheral, |
| // releasing it here cause immediate destruction and hence disconnection |
| [[[NLWeaveStack sharedStack] BleDelegate] forceBleDisconnect_Sync:_blePeripheral]; |
| _blePeripheral = nil; |
| } |
| } |
| |
| [self DispatchAsyncCompletionBlock:nil]; |
| } |
| |
| - (void)Shutdown:(WDMCompletionBlock)completionHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| // Note that conceptually we probably should not call shutdown while we're still closing the device manager and vice versa, |
| // but both Shutdown and Close are implemented in a synchronous way so there is really no chance for them to be intertwined. |
| if (nil != _mRequestName) { |
| WDM_LOG_ERROR(@"%@: Forcefully shutdown while we're still executing %@, continue shutdown", _name, _mRequestName); |
| } |
| |
| [self MarkTransactionCompleted]; |
| |
| _mCompletionHandler = completionHandler; |
| _mRequestName = @"Shutdown"; |
| [self Shutdown_Internal]; |
| }); |
| } |
| |
| - (void)Close:(WDMCompletionBlock)completionHandler failure:(WDMFailureBlock)failureHandler; |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"Close"; |
| |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| bool IsOKay = true; |
| if (nil != _mRequestName) { |
| // Note that conceptually we probably should not call shutdown while we're still closing the device manager and vice |
| // versa, but both Shutdown and Close are implemented in a synchronous way so there is really no chance for them to be |
| // intertwined. |
| if ([_mRequestName isEqualToString:@"Shutdown"]) { |
| IsOKay = false; |
| } |
| } |
| |
| if (IsOKay) { |
| // Note that we're already in Weave work queue, which means all callbacks for the previous or current request |
| // has either happened/completed or would be canceled by this call to Close. Therefore, it should be safe |
| // to wipe out request context variables like _mRequestName and _mCompletionHandler. |
| |
| _mWeaveCppDM->Close(); |
| |
| if (_blePeripheral) { |
| [[[NLWeaveStack sharedStack] BleDelegate] forceBleDisconnect_Sync:_blePeripheral]; |
| // autoclose is disabled when running weave connect ble, close ble after woble stack is |
| // destroyed |
| // release reference to the CBPeripheral |
| // since device manager is the only one who holds a strong reference to this peripheral, |
| // releasing it here cause immediate destruction and hence disconnection |
| _blePeripheral = nil; |
| } |
| |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| [self DispatchAsyncCompletionBlock:nil]; |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| - (BOOL)isConnected |
| { |
| __block bool result = false; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| // we use sync so the result is immediately available to the caller upon return |
| dispatch_sync(_mWeaveWorkQueue, ^() { |
| result = _mWeaveCppDM->IsConnected(); |
| }); |
| |
| return result ? YES : NO; |
| } |
| |
| - (BOOL)isValidPairingCode:(NSString *)pairingCode; |
| { |
| __block bool result = false; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| if ([pairingCode length] != 0) { |
| // note we're not executing in any specific queue, as this subroutine is supposed to be 'static' |
| result = nl::Weave::DeviceManager::WeaveDeviceManager::IsValidPairingCode([pairingCode UTF8String]); |
| } |
| |
| return result ? YES : NO; |
| } |
| |
| - (WEAVE_ERROR)GetDeviceId:(uint64_t *)deviceId |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block uint64_t result = 0; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppDM, err = WEAVE_ERROR_INCORRECT_STATE); |
| VerifyOrExit(NULL != deviceId, err = WEAVE_ERROR_INVALID_ARGUMENT); |
| |
| // need this bracket to use Verify macros |
| { |
| // we use sync so the result is immediately available to the caller upon return |
| dispatch_sync(_mWeaveWorkQueue, ^() { |
| err = _mWeaveCppDM->GetDeviceId(result); |
| |
| if (err == WEAVE_ERROR_INCORRECT_STATE) { |
| WDM_LOG_DEBUG(@"Got incorrect state error from GetDeviceId, ignore"); |
| |
| err = WEAVE_NO_ERROR; // No exception, just return 0. |
| result = 0; |
| } |
| }); |
| } |
| |
| exit: |
| if ((WEAVE_NO_ERROR == err) && (NULL != deviceId)) { |
| *deviceId = result; |
| } |
| return err; |
| } |
| |
| - (WEAVE_ERROR)GetDeviceMgrPtr:(long long *)deviceMgrPtr |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| WDM_LOG_METHOD_SIG(); |
| *deviceMgrPtr = (long long) _mWeaveCppDM; |
| |
| return err; |
| } |
| |
| - (WEAVE_ERROR)GetDeviceAddress:(NSMutableString *)strAddr; |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block NSString * strResult = nil; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != strAddr, err = WEAVE_ERROR_INVALID_ARGUMENT); |
| |
| // need this bracket to use Verify macros |
| { |
| // we use sync so the result is immediately available to the caller upon return |
| dispatch_sync(_mWeaveWorkQueue, ^() { |
| nl::Inet::IPAddress devAddr; |
| err = _mWeaveCppDM->GetDeviceAddress(devAddr); |
| if (WEAVE_NO_ERROR == err) { |
| char devAddrStrBuf[32]; |
| strResult = [NSString stringWithUTF8String:devAddr.ToString(devAddrStrBuf, sizeof(devAddrStrBuf))]; |
| } else { |
| strResult = @""; |
| } |
| }); |
| } |
| |
| [strAddr setString:strResult]; |
| |
| if (err == WEAVE_ERROR_INCORRECT_STATE) { |
| err = WEAVE_NO_ERROR; // No exception, just return null. |
| } |
| |
| exit: |
| |
| return err; |
| } |
| |
| static void HandleSimpleOperationComplete(nl::Weave::DeviceManager::WeaveDeviceManager * deviceMgr, void * reqState) |
| { |
| WDM_LOG_DEBUG(@"HandleSimpleOperationComplete"); |
| |
| NLWeaveDeviceManager * dm = (__bridge NLWeaveDeviceManager *) reqState; |
| // ignore the pointer to C++ device manager |
| (void) deviceMgr; |
| [dm DispatchAsyncCompletionBlock:nil]; |
| } |
| |
| static void onIdentifyDeviceComplete(nl::Weave::DeviceManager::WeaveDeviceManager * deviceMgr, void * appReqState, |
| const nl::Weave::DeviceManager::DeviceDescription::WeaveDeviceDescriptor * devdesc) |
| { |
| WDM_LOG_DEBUG(@"onIdentifyDeviceComplete"); |
| |
| NLWeaveDeviceManager * dm = (__bridge NLWeaveDeviceManager *) appReqState; |
| // ignore the pointer to C++ device manager |
| (void) deviceMgr; |
| [dm DispatchAsyncCompletionBlock:[NLWeaveDeviceDescriptor createUsing:*devdesc]]; |
| } |
| |
| static void onWeaveError(nl::Weave::DeviceManager::WeaveDeviceManager * deviceMgr, void * appReqState, WEAVE_ERROR code, |
| nl::Weave::DeviceManager::DeviceStatus * devStatus) |
| { |
| WDM_LOG_DEBUG(@"onWeaveError"); |
| |
| NSError * error = nil; |
| NSDictionary * userInfo = nil; |
| |
| NLWeaveDeviceManager * dm = (__bridge NLWeaveDeviceManager *) appReqState; |
| // ignore the pointer to C++ device manager |
| (void) deviceMgr; |
| |
| WDM_LOG_DEBUG(@"%@: Received error response to request %@, deviceMgrErr = %d, devStatus = %p\n", dm.name, |
| [dm GetCurrentRequest], code, devStatus); |
| |
| NLWeaveRequestError requestError; |
| if (devStatus != NULL && code == WEAVE_ERROR_STATUS_REPORT_RECEIVED) { |
| NLProfileStatusError * statusError = [[NLProfileStatusError alloc] |
| initWithProfileId:devStatus->StatusProfileId |
| statusCode:devStatus->StatusCode |
| errorCode:devStatus->SystemErrorCode |
| statusReport:[dm statusReportToString:devStatus->StatusProfileId statusCode:devStatus->StatusCode]]; |
| requestError = NLWeaveRequestError_ProfileStatusError; |
| userInfo = @{@"WeaveRequestErrorType" : @(requestError), @"errorInfo" : statusError}; |
| |
| WDM_LOG_DEBUG(@"%@: status error: %@", dm.name, userInfo); |
| } else { |
| NLWeaveError * weaveError = [[NLWeaveError alloc] initWithWeaveError:code |
| report:[NSString stringWithUTF8String:nl::ErrorStr(code)]]; |
| requestError = NLWeaveRequestError_WeaveError; |
| userInfo = @{@"WeaveRequestErrorType" : @(requestError), @"errorInfo" : weaveError}; |
| } |
| |
| error = [NSError errorWithDomain:@"com.nest.error" code:code userInfo:userInfo]; |
| |
| [dm DispatchAsyncDefaultFailureBlock:error]; |
| } |
| |
| - (void)identifyDevice:(WDMCompletionBlock)completionHandler failure:(WDMFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"IdentifyDevice"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| _mFailureHandler = failureHandler; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->IdentifyDevice((__bridge void *) self, onIdentifyDeviceComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| - (void)rendezvousWithDevicePairingCode:(NSString *)pairingCode |
| completion:(WDMCompletionBlock)completionHandler |
| failure:(WDMFailureBlock)failureHandler |
| { |
| // Note that NLIdentifyDeviceCriteria::create an empty criteria, which shall meet all devices |
| // The prior implementation for this function, however, puts a limitation on the device mode |
| NLIdentifyDeviceCriteria * criteria = [NLIdentifyDeviceCriteria create]; |
| criteria.TargetModes = NLTargetDeviceModeUserSelectedMode; |
| |
| [self rendezvousWithDevicePairingCode:pairingCode |
| identifyDeviceCriteria:criteria |
| completion:completionHandler |
| failure:failureHandler]; |
| } |
| |
| - (void)rendezvousWithDevicePairingCode:(NSString *)pairingCode |
| identifyDeviceCriteria:(NLIdentifyDeviceCriteria *)identifyDeviceCriteria |
| completion:(WDMCompletionBlock)completionHandler |
| failure:(WDMFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"RendezvousDevice"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| _mFailureHandler = failureHandler; |
| |
| nl::Weave::Profiles::DeviceDescription::IdentifyDeviceCriteria deviceCriteria = |
| [identifyDeviceCriteria toIdentifyDeviceCriteria]; |
| |
| // note that RendezvousDevice interanlly makes a copy of the pairing code before return |
| WEAVE_ERROR err = _mWeaveCppDM->RendezvousDevice( |
| [pairingCode UTF8String], deviceCriteria, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| - (void)rendezvousWithDeviceAccessToken:(NSString *)accessToken |
| identifyDeviceCriteria:(NLIdentifyDeviceCriteria *)identifyDeviceCriteria |
| completion:(WDMCompletionBlock)completionHandler |
| failure:(WDMFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"RendezvousDevice"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| _mFailureHandler = failureHandler; |
| |
| nl::Weave::Profiles::DeviceDescription::IdentifyDeviceCriteria criteria = |
| [identifyDeviceCriteria toIdentifyDeviceCriteria]; |
| |
| Base64Encoding * base64coder = [Base64Encoding createBase64StringEncoding]; |
| NSData * accessTokenData = [base64coder decode:accessToken]; |
| |
| // Note: accessTokenData is not supposed to be longer than uint32_t_max bytes |
| // Weave, in general, uses unsigned 32-bit to represent data length |
| uint32_t accessTokenLen = (uint32_t)[accessTokenData length]; |
| uint8_t * pAccessToken = (uint8_t *) [accessTokenData bytes]; |
| |
| // note that RendezvousDevice interanlly makes a copy of the access token before return |
| WEAVE_ERROR err = _mWeaveCppDM->RendezvousDevice( |
| pAccessToken, accessTokenLen, criteria, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| - (void)passiveRendezvousWithCompletion:(WDMCompletionBlock)completionHandler failure:(WDMFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"PassiveRendezvous"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| _mFailureHandler = failureHandler; |
| |
| WEAVE_ERROR err |
| = _mWeaveCppDM->PassiveRendezvousDevice((__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| - (void)passiveRendezvousWithDevicePairingCode:(NSString *)pairingCode |
| completion:(WDMCompletionBlock)completionHandler |
| failure:(WDMFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"PassiveRendezvous"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| _mFailureHandler = failureHandler; |
| |
| // note that PassiveRendezvousDevice interanlly makes a copy of the pairing code before return |
| WEAVE_ERROR err = _mWeaveCppDM->PassiveRendezvousDevice( |
| [pairingCode UTF8String], (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| - (void)passiveRendezvousWithDeviceAccessToken:(NSString *)accessToken |
| completion:(WDMCompletionBlock)completionHandler |
| failure:(WDMFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"PassiveRendezvous"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| _mFailureHandler = failureHandler; |
| |
| Base64Encoding * base64coder = [Base64Encoding createBase64StringEncoding]; |
| NSData * accessTokenData = [base64coder decode:accessToken]; |
| |
| // Note: accessTokenData is not supposed to be longer than uint32_t_max bytes |
| // Weave, in general, uses unsigned 32-bit to represent data length |
| uint32_t accessTokenLen = (uint32_t)[accessTokenData length]; |
| uint8_t * pAccessToken = (uint8_t *) [accessTokenData bytes]; |
| |
| // note that PassiveRendezvousDevice interanlly makes a copy of the access token before return |
| WEAVE_ERROR err = _mWeaveCppDM->PassiveRendezvousDevice( |
| pAccessToken, accessTokenLen, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| - (void)remotePassiveRendezvousWithDevicePairingCode:(NSString *)pairingCode |
| IPAddress:(NSString *)IPAddress |
| rendezvousTimeout:(uint16_t)rendezvousTimeoutSec |
| inactivityTimeout:(uint16_t)inactivityTimeoutSec |
| completion:(WDMCompletionBlock)completionHandler |
| failure:(WDMFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"RemotePassiveRendezvous"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| _mFailureHandler = failureHandler; |
| |
| nl::Inet::IPAddress rendezvousAddr; |
| const char * rendezvousAddrStr = [IPAddress UTF8String]; |
| if (!nl::Inet::IPAddress::IPAddress::FromString(rendezvousAddrStr, rendezvousAddr)) { |
| rendezvousAddr = nl::Inet::IPAddress::Any; |
| } |
| |
| // note that RemotePassiveRendezvous interanlly makes a copy of the pairing code before return |
| WEAVE_ERROR err = _mWeaveCppDM->RemotePassiveRendezvous(rendezvousAddr, [pairingCode UTF8String], rendezvousTimeoutSec, |
| inactivityTimeoutSec, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| - (NSInteger)setRendezvousAddress:(NSString *)aRendezvousAddress |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| const char * rendezvousAddrStr = [aRendezvousAddress UTF8String]; |
| nl::Inet::IPAddress rendezvousAddr; |
| |
| if (!nl::Inet::IPAddress::FromString(rendezvousAddrStr, rendezvousAddr)) { |
| ExitNow(err = WEAVE_ERROR_INVALID_ADDRESS); |
| } |
| |
| // need this bracket to use Verify macros |
| { |
| // we use sync so the result is immediately available to the caller upon return |
| dispatch_sync(_mWeaveWorkQueue, ^() { |
| err = _mWeaveCppDM->SetWiFiRendezvousAddress(rendezvousAddr); |
| }); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| static void onDeviceEnumerationResponse(nl::Weave::DeviceManager::WeaveDeviceManager * deviceMgr, void * appReqState, |
| const nl::Weave::DeviceManager::DeviceDescription::WeaveDeviceDescriptor * devdesc, nl::Inet::IPAddress deviceAddr, |
| nl::Inet::InterfaceId deviceIntf) |
| { |
| WDM_LOG_DEBUG(@"onDeviceEnumerationResponse"); |
| |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| NLWeaveDeviceManager * dm = (__bridge NLWeaveDeviceManager *) appReqState; |
| NSString * deviceAddrStr; |
| NSDictionary * deviceEnumerationResponsePlist; |
| char devAddrCStr[INET6_ADDRSTRLEN + IF_NAMESIZE + 2]; // Include space for "<addr>%<interface name>" and NULL terminator |
| |
| // ignore the pointer to C++ device manager |
| (void) deviceMgr; |
| |
| VerifyOrExit(deviceAddr.ToString(devAddrCStr, sizeof(devAddrCStr)) != NULL, err = WEAVE_ERROR_NO_MEMORY); |
| |
| // Add "%" separator character, with NULL terminator, per IETF RFCs 4001 and 4007 |
| VerifyOrExit(snprintf(&(devAddrCStr[strlen(devAddrCStr)]), 2, "%%") > 0, err = nl::Weave::System::MapErrorPOSIX(errno)); |
| |
| // Concatenate zone index (aka interface name) to IP address, with NULL terminator, per IETF RFCs 4001 and 4007 |
| err = nl::Inet::GetInterfaceName(deviceIntf, &(devAddrCStr[strlen(devAddrCStr)]), IF_NAMESIZE + 1); |
| SuccessOrExit(err); |
| |
| // create NSString from IPAddress, including IPv6 zone identifier |
| deviceAddrStr = [NSString stringWithUTF8String:devAddrCStr]; |
| |
| deviceEnumerationResponsePlist = |
| @ { @"deviceAddress" : deviceAddrStr, @"deviceDescriptor" : [NLWeaveDeviceDescriptor createUsing:*devdesc] }; |
| |
| [dm DispatchAsyncResponseBlock:deviceEnumerationResponsePlist]; |
| |
| exit: |
| WDM_LOG_ERROR(@"Error in onDeviceEnumerationResponse: (%d) %@\n", err, [NSString stringWithUTF8String:nl::ErrorStr(err)]); |
| } |
| |
| - (void)startDeviceEnumerationWithIdentifyDeviceCriteria:(NLIdentifyDeviceCriteria *)identifyDeviceCriteria |
| completion:(WDMCompletionBlock)completionBlock |
| failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"DeviceEnumeration"; |
| |
| // we use async for the results that are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| nl::Weave::Profiles::DeviceDescription::IdentifyDeviceCriteria deviceCriteria = |
| [identifyDeviceCriteria toIdentifyDeviceCriteria]; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->StartDeviceEnumeration( |
| (__bridge void *) self, deviceCriteria, onDeviceEnumerationResponse, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)stopDeviceEnumeration |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| dispatch_sync(_mWeaveWorkQueue, ^() { |
| _mWeaveCppDM->StopDeviceEnumeration(); |
| }); |
| |
| [self MarkTransactionCompleted]; |
| } |
| |
| - (void)connectDevice:(uint64_t)deviceId |
| deviceAddress:(NSString *)deviceAddress |
| completion:(WDMCompletionBlock)completionHandler |
| failure:(WDMFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"ConnectDevice"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| _mFailureHandler = failureHandler; |
| |
| nl::Inet::IPAddress deviceAddr; |
| nl::Inet::IPAddress::FromString([deviceAddress UTF8String], deviceAddr); |
| |
| WEAVE_ERROR err = _mWeaveCppDM->ConnectDevice( |
| deviceId, deviceAddr, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| - (void)reconnectDevice:(WDMCompletionBlock)completionHandler failure:(WDMFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"ReconnectDevice"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| _mFailureHandler = failureHandler; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->ReconnectDevice((__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| - (void)connectBle:(CBPeripheral *)peripheral |
| completion:(WDMCompletionBlock)completionHandler |
| failure:(WDMFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"ConnectBle"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| _mFailureHandler = failureHandler; |
| _blePeripheral = peripheral; |
| |
| // this will be called when the preparation completes one Weave work queue |
| _BleConnectionPreparationCompleteHandler = ^(NLWeaveDeviceManager * dm, WEAVE_ERROR err) { |
| if (WEAVE_NO_ERROR == err) { |
| err = _mWeaveCppDM->ConnectBle( |
| (__bridge void *) _blePeripheral, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| } |
| if (WEAVE_NO_ERROR != err) { |
| [dm DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| }; |
| |
| [[[NLWeaveStack sharedStack] BleDelegate] prepareNewBleConnection:self]; |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| - (void)connectBleWithPairingCode:(CBPeripheral *)peripheral |
| pairingCode:(NSString *)pairingCode |
| completion:(WDMCompletionBlock)completionHandler |
| failure:(WDMFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"ConnectBle"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| _mFailureHandler = failureHandler; |
| _blePeripheral = peripheral; |
| |
| // this will be called when the preparation completes one Weave work queue |
| _BleConnectionPreparationCompleteHandler = ^(NLWeaveDeviceManager * dm, WEAVE_ERROR err) { |
| if (WEAVE_NO_ERROR == err) { |
| const char * pairingCodeStr = [pairingCode UTF8String]; |
| |
| err = _mWeaveCppDM->ConnectBle((__bridge void *) _blePeripheral, pairingCodeStr, (__bridge void *) self, |
| HandleSimpleOperationComplete, onWeaveError); |
| } |
| if (WEAVE_NO_ERROR != err) { |
| [dm DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| }; |
| |
| [[[NLWeaveStack sharedStack] BleDelegate] prepareNewBleConnection:self]; |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| static void onGetCameraAuthDataComplete( |
| nl::Weave::DeviceManager::WeaveDeviceManager * deviceMgr, void * reqState, const char * macAddress, const char * signedPayload) |
| { |
| WDM_LOG_DEBUG(@"onGetCameraAuthDataComplete"); |
| |
| NLWeaveDeviceManager * dm = (__bridge NLWeaveDeviceManager *) reqState; |
| // ignore the pointer to C++ device manager |
| (void) deviceMgr; |
| |
| NSString * macAddressStr = [NSString stringWithUTF8String:macAddress]; |
| NSString * signedPayloadStr = [NSString stringWithUTF8String:signedPayload]; |
| |
| WDM_LOG_DEBUG(@"Camera MAC = %s, payload = %s\n", macAddress, signedPayload); |
| |
| NSDictionary * cameraAuthDataPlist = @ { @"macAddress" : macAddressStr, @"signedPayload" : signedPayloadStr }; |
| |
| [dm DispatchAsyncCompletionBlock:cameraAuthDataPlist]; |
| } |
| |
| - (void)getCameraAuthData:(NSString *)nonce completion:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"GetCameraAuthData"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| const char * nonceStr = [nonce UTF8String]; |
| |
| WEAVE_ERROR err |
| = _mWeaveCppDM->GetCameraAuthData(nonceStr, (__bridge void *) self, onGetCameraAuthDataComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)connectBleWithDeviceAccessToken:(CBPeripheral *)peripheral |
| accessToken:(NSString *)accessToken |
| completion:(WDMCompletionBlock)completionHandler |
| failure:(WDMFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"ConnectBle"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| _mFailureHandler = failureHandler; |
| _blePeripheral = peripheral; |
| |
| // this will be called when the preparation completes one Weave work queue |
| _BleConnectionPreparationCompleteHandler = ^(NLWeaveDeviceManager * dm, WEAVE_ERROR err) { |
| if (WEAVE_NO_ERROR == err) { |
| Base64Encoding * base64coder = [Base64Encoding createBase64StringEncoding]; |
| NSData * accessTokenData = [base64coder decode:accessToken]; |
| |
| // Note: accessTokenData is not supposed to be longer than uint32_t_max bytes |
| // Weave, in general, uses unsigned 32-bit to represent data length |
| uint32_t accessTokenLen = (uint32_t)[accessTokenData length]; |
| uint8_t * pAccessToken = (uint8_t *) [accessTokenData bytes]; |
| |
| err = _mWeaveCppDM->ConnectBle((__bridge void *) _blePeripheral, pAccessToken, accessTokenLen, |
| (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| } |
| |
| if (WEAVE_NO_ERROR != err) { |
| [dm DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| }; |
| |
| [[[NLWeaveStack sharedStack] BleDelegate] prepareNewBleConnection:self]; |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| static void onGetWirelessRegulatoryConfigComplete(nl::Weave::DeviceManager::WeaveDeviceManager * deviceMgr, void * reqState, |
| const nl::Weave::Profiles::NetworkProvisioning::WirelessRegConfig * regConfig) |
| { |
| WDM_LOG_DEBUG(@"onGetWirelessRegulatoryConfigComplete"); |
| |
| NLWeaveDeviceManager * dm = (__bridge NLWeaveDeviceManager *) reqState; |
| // ignore the pointer to C++ device manager |
| (void) deviceMgr; |
| |
| [dm DispatchAsyncCompletionBlock:[NLWirelessRegConfig createUsing:regConfig]]; |
| } |
| |
| - (void)getWirelessRegulatoryConfig:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"GetWirelessRegulatoryConfig"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->GetWirelessRegulatoryConfig( |
| (__bridge void *) self, onGetWirelessRegulatoryConfigComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)setWirelessRegulatoryConfig:(NLWirelessRegConfig *)nlWirelessRegConfig |
| completion:(WDMCompletionBlock)completionBlock |
| failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"SetWirelessRegulatoryConfig"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| nl::Weave::Profiles::NetworkProvisioning::WirelessRegConfig wirelessRegConfig = |
| [nlWirelessRegConfig toWirelessRegConfig]; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->SetWirelessRegulatoryConfig( |
| &wirelessRegConfig, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| static void onNetworkScanComplete( |
| nl::Weave::DeviceManager::WeaveDeviceManager * deviceMgr, void * reqState, uint16_t netCount, const NetworkInfo * netInfoList) |
| { |
| WDM_LOG_DEBUG(@"onNetworkScanComplete"); |
| |
| NLWeaveDeviceManager * dm = (__bridge NLWeaveDeviceManager *) reqState; |
| // ignore the pointer to C++ device manager |
| (void) deviceMgr; |
| |
| NSMutableArray * networkInfoList = [NSMutableArray arrayWithCapacity:netCount]; |
| |
| WDM_LOG_DEBUG(@"Count = %u\n", netCount); |
| |
| for (uint32_t i = 0; i < netCount; i++) { |
| NetworkInfo * pNetworkInfoElement = (NetworkInfo *) &netInfoList[i]; |
| NLNetworkInfo * nlNetworkInfo = [NLNetworkInfo createUsing:pNetworkInfoElement]; |
| [networkInfoList addObject:nlNetworkInfo]; |
| } |
| |
| [dm DispatchAsyncCompletionBlock:networkInfoList]; |
| } |
| |
| - (void)scanNetworks:(NLNetworkType)networkType completion:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"ScanNetworks"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| bool isValidType = false; |
| nl::Weave::Profiles::NetworkProvisioning::NetworkType type; |
| |
| switch (networkType) { |
| case kNLNetworkType_NotSpecified: |
| type = nl::Weave::Profiles::NetworkProvisioning::kNetworkType_NotSpecified; |
| isValidType = true; |
| break; |
| case kNLNetworkType_WiFi: |
| type = nl::Weave::Profiles::NetworkProvisioning::kNetworkType_WiFi; |
| isValidType = true; |
| break; |
| default: |
| WDM_LOG_ERROR(@"%@: invalid network type, abort", _name); |
| type = nl::Weave::Profiles::NetworkProvisioning::kNetworkType_NotSpecified; |
| isValidType = false; |
| } |
| |
| if (isValidType) { |
| WEAVE_ERROR err = _mWeaveCppDM->ScanNetworks(type, (__bridge void *) self, onNetworkScanComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| [self DispatchAsyncDefaultFailureBlockWithCode:WEAVE_ERROR_INVALID_ARGUMENT]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| static void onAddNetworkComplete(nl::Weave::DeviceManager::WeaveDeviceManager * deviceMgr, void * reqState, uint32_t networkId) |
| { |
| WDM_LOG_DEBUG(@"onAddNetworkComplete"); |
| |
| NLWeaveDeviceManager * dm = (__bridge NLWeaveDeviceManager *) reqState; |
| // ignore the pointer to C++ device manager |
| (void) deviceMgr; |
| |
| WDM_LOG_DEBUG(@"networkId = %u\n", networkId); |
| |
| [dm DispatchAsyncCompletionBlock:@(networkId)]; |
| } |
| |
| - (void)addNetwork:(NLNetworkInfo *)nlNetworkInfo |
| completion:(WDMCompletionBlock)completionBlock |
| failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"AddNetwork"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| NetworkInfo networkInfo = [nlNetworkInfo toNetworkInfo]; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->AddNetwork(&networkInfo, (__bridge void *) self, onAddNetworkComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)updateNetwork:(NLNetworkInfo *)nlNetworkInfo |
| completion:(WDMCompletionBlock)completionBlock |
| failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"updateNetwork"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| NetworkInfo networkInfo = [nlNetworkInfo toNetworkInfo]; |
| |
| WEAVE_ERROR err |
| = _mWeaveCppDM->UpdateNetwork(&networkInfo, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)removeNetwork:(NLNetworkID)networkId completion:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"removeNetwork"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->RemoveNetwork( |
| (uint32_t) networkId, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)getNetworks:(uint8_t)flags completion:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"getNetworks"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->GetNetworks(flags, (__bridge void *) self, onNetworkScanComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)enableNetwork:(NLNetworkID)networkId completion:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"enableNetwork"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->EnableNetwork( |
| (uint32_t) networkId, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)disableNetwork:(NLNetworkID)networkId completion:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"disableNetwork"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->DisableNetwork( |
| (uint32_t) networkId, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)testNetworkConnectivity:(NLNetworkID)networkId |
| completion:(WDMCompletionBlock)completionBlock |
| failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"testNetworkConnectivity"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->TestNetworkConnectivity( |
| (uint32_t) networkId, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| static void onGetRendezvousModeComplete( |
| nl::Weave::DeviceManager::WeaveDeviceManager * deviceMgr, void * reqState, uint16_t modeFlags) |
| { |
| WDM_LOG_DEBUG(@"onAddNetworkComplete"); |
| |
| NLWeaveDeviceManager * dm = (__bridge NLWeaveDeviceManager *) reqState; |
| // ignore the pointer to C++ device manager |
| (void) deviceMgr; |
| |
| WDM_LOG_DEBUG(@"networkId = %u\n", modeFlags); |
| |
| [dm DispatchAsyncCompletionBlock:@(modeFlags)]; |
| } |
| |
| - (void)getRendezvousMode:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"getRendezvousMode"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->GetRendezvousMode((__bridge void *) self, onGetRendezvousModeComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)setRendezvousMode:(uint16_t)rendezvousFlags |
| completion:(WDMCompletionBlock)completionBlock |
| failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"SetRendezvousMode"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->SetRendezvousMode( |
| (uint16_t) rendezvousFlags, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (WEAVE_ERROR)setAutoReconnect:(BOOL)autoReconnect |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppDM, err = WEAVE_ERROR_INCORRECT_STATE); |
| |
| // need this bracket to use Verify macros |
| { |
| // we use sync so the result is immediately available to the caller upon return |
| dispatch_sync(_mWeaveWorkQueue, ^() { |
| err = _mWeaveCppDM->SetAutoReconnect(autoReconnect ? true : false); |
| }); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| - (void)createFabric:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"CreateFabric"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->CreateFabric((__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)leaveFabric:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"LeaveFabric"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->LeaveFabric((__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| static void onGetFabricConfigComplete(nl::Weave::DeviceManager::WeaveDeviceManager * deviceMgr, void * reqState, |
| const uint8_t * fabricConfig, uint32_t fabricConfigLen) |
| { |
| WDM_LOG_DEBUG(@"onGetFabricConfigComplete"); |
| |
| NLWeaveDeviceManager * dm = (__bridge NLWeaveDeviceManager *) reqState; |
| // ignore the pointer to C++ device manager |
| (void) deviceMgr; |
| |
| [dm DispatchAsyncCompletionBlock:[NSData dataWithBytes:fabricConfig length:fabricConfigLen]]; |
| } |
| |
| - (void)getFabricConfig:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"GetFabricConfig"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->GetFabricConfig((__bridge void *) self, onGetFabricConfigComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this reques |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)joinExistingFabric:(NSData *)fabricConfig |
| completion:(WDMCompletionBlock)completionBlock |
| failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"JoinExistingFabric"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| uint16_t fabricConfigLen = fabricConfig ? (uint16_t)[fabricConfig length] : 0; |
| uint8_t * fabricConfigBuf = (uint8_t *) [fabricConfig bytes]; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->JoinExistingFabric( |
| fabricConfigBuf, fabricConfigLen, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)registerServicePairAccount:(NLServiceInfo *)nlServiceInfo |
| completion:(WDMCompletionBlock)completionBlock |
| failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"RegisterServicePairAccount"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| const char * pAccountIdStr = [nlServiceInfo.accountId UTF8String]; |
| |
| NSData * serviceConfigData = [nlServiceInfo decodeServiceConfig]; |
| uint16_t serviceConfigLen = (uint16_t)[serviceConfigData length]; |
| uint8_t * pServiceConfig = (uint8_t *) [serviceConfigData bytes]; |
| |
| NSData * data = [NSData dataWithBytes:[nlServiceInfo.pairingToken UTF8String] |
| length:[nlServiceInfo.pairingToken lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; |
| uint16_t pairingTokenLen = (uint16_t)[nlServiceInfo.pairingToken length]; |
| uint8_t * pPairingToken = (uint8_t *) [data bytes]; |
| |
| data = [nlServiceInfo.pairingInitData dataUsingEncoding:NSUTF8StringEncoding]; |
| uint16_t pairingInitDataLen = (uint16_t) data.length; |
| uint8_t * pPairingInitData = (uint8_t *) [data bytes]; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->RegisterServicePairAccount(nlServiceInfo.serviceId, pAccountIdStr, pServiceConfig, |
| serviceConfigLen, pPairingToken, pairingTokenLen, pPairingInitData, pairingInitDataLen, (__bridge void *) self, |
| HandleSimpleOperationComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)updateService:(NLServiceInfo *)nlServiceInfo |
| completion:(WDMCompletionBlock)completionBlock |
| failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"UpdateService"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| NSData * serviceConfigData = [nlServiceInfo decodeServiceConfig]; |
| uint16_t serviceConfigLen = [serviceConfigData length]; |
| uint8_t * pServiceConfig = (uint8_t *) [serviceConfigData bytes]; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->UpdateService(nlServiceInfo.serviceId, pServiceConfig, serviceConfigLen, |
| (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)unregisterService:(uint64_t)serviceId completion:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"UnregisterService"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err |
| = _mWeaveCppDM->UnregisterService(serviceId, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)getLastNetworkProvisioningResult:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"GetLastNetworkProvisioningResult"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->GetLastNetworkProvisioningResult( |
| (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)armFailSafe:(uint8_t)armMode |
| failSafeToken:(uint32_t)failSafeToken |
| completion:(WDMCompletionBlock)completionBlock |
| failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"ArmFailSafe"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->ArmFailSafe( |
| armMode, failSafeToken, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)disarmFailSafe:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"DisarmFailSafe"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->DisarmFailSafe((__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)resetConfig:(uint16_t)resetFlags completion:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"ResetConfig"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err |
| = _mWeaveCppDM->ResetConfig(resetFlags, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)enableConnectionMonitor:(NSInteger)intervalMs |
| timeout:(NSInteger)timeoutMs |
| completion:(WDMCompletionBlock)completionBlock |
| failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"EnableConnectionMonitor"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->EnableConnectionMonitor( |
| intervalMs, timeoutMs, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)disableConnectionMonitor:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"DisableConnectionMonitor"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err |
| = _mWeaveCppDM->DisableConnectionMonitor((__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)startSystemTest:(uint32_t)profileId |
| testId:(uint32_t)testId |
| completion:(WDMCompletionBlock)completionBlock |
| failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"StartSystemTest"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->StartSystemTest( |
| (__bridge void *) self, profileId, testId, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| - (void)ping:(WDMCompletionBlock)completionHandler failure:(WDMFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"Ping"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionHandler; |
| _mFailureHandler = failureHandler; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->Ping((__bridge void *) self, HandleSimpleOperationComplete, onWeaveError); |
| |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureHandler]; |
| } |
| }); |
| } |
| |
| static void onPairTokenComplete(nl::Weave::DeviceManager::WeaveDeviceManager * deviceMgr, void * reqState, |
| const uint8_t * pairingTokenBundle, uint32_t pairingTokenBundleLen) |
| { |
| WDM_LOG_DEBUG(@"onPairTokenComplete"); |
| |
| NLWeaveDeviceManager * dm = (__bridge NLWeaveDeviceManager *) reqState; |
| // ignore the pointer to C++ device manager |
| (void) deviceMgr; |
| |
| [dm DispatchAsyncCompletionBlock:[NSData dataWithBytes:pairingTokenBundle length:pairingTokenBundleLen]]; |
| } |
| |
| - (void)pairToken:(NSData *)pairingToken completion:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"pairToken"; |
| |
| // we use async for the results are sent back to caller via async means also |
| dispatch_async(_mWeaveWorkQueue, ^() { |
| if (nil == _mRequestName) { |
| _mRequestName = taskName; |
| _mCompletionHandler = completionBlock; |
| _mFailureHandler = failureBlock; |
| |
| uint16_t pairingTokenLen = pairingToken ? (uint16_t)[pairingToken length] : 0; |
| uint8_t * pairingTokenBuf = (uint8_t *) [pairingToken bytes]; |
| |
| WEAVE_ERROR err = _mWeaveCppDM->PairToken( |
| pairingTokenBuf, pairingTokenLen, (__bridge void *) self, onPairTokenComplete, onWeaveError); |
| if (WEAVE_NO_ERROR != err) { |
| [self DispatchAsyncDefaultFailureBlockWithCode:err]; |
| } |
| } else { |
| WDM_LOG_ERROR(@"%@: Attemp to %@ while we're still executing %@, ignore", _name, taskName, _mRequestName); |
| |
| // do not change _mRequestName, as we're rejecting this request |
| [self DispatchAsyncFailureBlock:WEAVE_ERROR_INCORRECT_STATE taskName:taskName handler:failureBlock]; |
| } |
| }); |
| } |
| |
| @end |