| /* |
| * |
| * Copyright (c) 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 NLGenericTraitUpdatableDataSink interface. |
| * This is WEAVE_CONFIG_DATA_MANAGEMENT_EXPERIMENTAL feature. |
| * |
| */ |
| |
| #import <Foundation/Foundation.h> |
| #import "NLWeaveStack.h" |
| #import "NLLogging.h" |
| |
| #include <Weave/Core/WeaveCore.h> |
| #include <Weave/Core/WeaveError.h> |
| #include <Weave/Support/CodeUtils.h> |
| #include <Weave/Support/NLDLLUtil.h> |
| #include <Weave/Profiles/WeaveProfiles.h> |
| #include <Weave/Profiles/common/CommonProfile.h> |
| #include <Weave/Profiles/data-management/Current/WdmManagedNamespace.h> |
| #include <Weave/Profiles/data-management/DataManagement.h> |
| #include <Weave/Profiles/data-management/SubscriptionClient.h> |
| #include <WeaveDeviceManager.h> |
| #include <WeaveDataManagementClient.h> |
| |
| #import "NLProfileStatusError.h" |
| #import "NLWeaveError_Protected.h" |
| #import "NLWdmClient_Protected.h" |
| #import "NLGenericTraitUpdatableDataSink_Protected.h" |
| #include <iostream> |
| #include <vector> |
| |
| using namespace nl::Weave::Profiles; |
| using namespace nl::Weave::Profiles::DataManagement; |
| #if WEAVE_CONFIG_DATA_MANAGEMENT_CLIENT_EXPERIMENTAL |
| @interface NLGenericTraitUpdatableDataSink () { |
| nl::Weave::DeviceManager::GenericTraitUpdatableDataSink * _mWeaveCppGenericTraitUpdatableDataSink; |
| NLWdmClient * _mNLWdmClient; |
| dispatch_queue_t _mWeaveWorkQueue; |
| dispatch_queue_t _mAppCallbackQueue; |
| |
| // Note that these context variables are independent from context variables in the C++ Weave Data Management, |
| // for the C++ Weave Data Management only takes one pointer as the app context, which is not enough to hold all |
| // context information we need. |
| GenericTraitUpdatableDataSinkCompletionBlock _mCompletionHandler; |
| GenericTraitUpdatableDataSinkFailureBlock _mFailureHandler; |
| NSString * _mRequestName; |
| } |
| |
| - (NSString *)GetCurrentRequest; |
| @end |
| |
| @implementation NLGenericTraitUpdatableDataSink |
| @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 GenericTraitUpdatableDataSink) |
| dispatch_sync(_mWeaveWorkQueue, ^() { |
| [self shutdown_Internal]; |
| }); |
| } |
| |
| - (instancetype)init:(NSString *)name |
| weaveWorkQueue:(dispatch_queue_t)weaveWorkQueue |
| appCallbackQueue:(dispatch_queue_t)appCallbackQueue |
| genericTraitUpdatableDataSinkPtr:(nl::Weave::DeviceManager::GenericTraitUpdatableDataSink *)dataSinkPtr |
| nlWdmClient:(NLWdmClient *)nlWdmClient |
| { |
| 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; |
| _mWeaveCppGenericTraitUpdatableDataSink = dataSinkPtr; |
| _mNLWdmClient = nlWdmClient; |
| |
| // simple bridge shall not increase our reference count |
| _mWeaveCppGenericTraitUpdatableDataSink->mpAppState = (__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; |
| } |
| |
| static void onGenericUpdatableDataSinkComplete(void * dataSink, void * reqState) |
| { |
| WDM_LOG_DEBUG(@"onGenericUpdatableDataSinkComplete"); |
| |
| NLGenericTraitUpdatableDataSink * sink = (__bridge NLGenericTraitUpdatableDataSink *) reqState; |
| [sink DispatchAsyncCompletionBlock:nil]; |
| } |
| |
| static void onGenericUpdatableDataSinkError( |
| void * dataSink, void * appReqState, WEAVE_ERROR code, nl::Weave::DeviceManager::DeviceStatus * devStatus) |
| { |
| WDM_LOG_DEBUG(@"onGenericUpdatableDataSinkError with error code %d\n", code); |
| |
| NSError * error = nil; |
| NSDictionary * userInfo = nil; |
| |
| NLGenericTraitUpdatableDataSink * nlDataSink = (__bridge NLGenericTraitUpdatableDataSink *) appReqState; |
| // ignore the pointer to C++ GenericTraitUpdatableDataSink |
| (void) dataSink; |
| |
| WDM_LOG_DEBUG(@"%@: Received error response to request %@, wdmClientErr = %d, devStatus = %p\n", nlDataSink.name, |
| [nlDataSink 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:[nlDataSink statusReportToString:devStatus->StatusProfileId statusCode:devStatus->StatusCode]]; |
| requestError = NLWeaveRequestError_ProfileStatusError; |
| userInfo = @{@"WeaveRequestErrorType" : @(requestError), @"errorInfo" : statusError}; |
| |
| WDM_LOG_DEBUG(@"%@: status error: %@", nlDataSink.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]; |
| |
| [nlDataSink DispatchAsyncDefaultFailureBlock:error]; |
| } |
| |
| - (void)markTransactionCompleted |
| { |
| _mRequestName = nil; |
| _mCompletionHandler = nil; |
| _mFailureHandler = nil; |
| } |
| |
| - (NSString *)GetCurrentRequest |
| { |
| return _mRequestName; |
| } |
| |
| - (void)DispatchAsyncFailureBlock:(WEAVE_ERROR)code |
| taskName:(NSString *)taskName |
| handler:(GenericTraitUpdatableDataSinkFailureBlock)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:(GenericTraitUpdatableDataSinkFailureBlock)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; |
| GenericTraitUpdatableDataSinkFailureBlock failureHandler = _mFailureHandler; |
| |
| [self markTransactionCompleted]; |
| [self DispatchAsyncFailureBlockWithError:error taskName:taskName handler:failureHandler]; |
| } |
| |
| - (void)DispatchAsyncCompletionBlock:(id)data |
| { |
| GenericTraitUpdatableDataSinkCompletionBlock completionHandler = _mCompletionHandler; |
| |
| [self markTransactionCompleted]; |
| |
| if (nil != completionHandler) { |
| dispatch_async(_mAppCallbackQueue, ^() { |
| completionHandler(_owner, data); |
| }); |
| } |
| } |
| |
| - (void)DispatchAsyncResponseBlock:(id)data |
| { |
| GenericTraitUpdatableDataSinkCompletionBlock 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(); |
| |
| if (_mNLWdmClient != nil) { |
| [_mNLWdmClient removeDataSinkRef:(long long) _mWeaveCppGenericTraitUpdatableDataSink]; |
| _mNLWdmClient = nil; |
| } |
| |
| if (_mWeaveCppGenericTraitUpdatableDataSink != nil) { |
| _mWeaveCppGenericTraitUpdatableDataSink->Clear(); |
| _mWeaveCppGenericTraitUpdatableDataSink = nil; |
| } |
| } |
| |
| - (void)close |
| { |
| WDM_LOG_METHOD_SIG(); |
| [self markTransactionCompleted]; |
| [self shutdown_Internal]; |
| } |
| |
| - (void)clear |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, 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, ^() { |
| _mWeaveCppGenericTraitUpdatableDataSink->Clear(); |
| }); |
| } |
| exit: |
| return; |
| } |
| |
| - (void)refreshData:(GenericTraitUpdatableDataSinkCompletionBlock)completionHandler |
| failure:(GenericTraitUpdatableDataSinkFailureBlock)failureHandler |
| { |
| WDM_LOG_METHOD_SIG(); |
| |
| NSString * taskName = @"RefreshData"; |
| |
| // 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 copy]; |
| _mFailureHandler = [failureHandler copy]; |
| |
| WEAVE_ERROR err = _mWeaveCppGenericTraitUpdatableDataSink->RefreshData( |
| (__bridge void *) self, onGenericUpdatableDataSinkComplete, onGenericUpdatableDataSinkError); |
| |
| 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]; |
| } |
| }); |
| } |
| |
| - (WEAVE_ERROR)setSigned:(int64_t)val path:(NSString *)path conditional:(BOOL)isConditional |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block bool isConditionalBool = isConditional; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, 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 = _mWeaveCppGenericTraitUpdatableDataSink->SetData([path UTF8String], val, isConditionalBool); |
| }); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| - (WEAVE_ERROR)setUnsigned:(uint64_t)val path:(NSString *)path conditional:(BOOL)isConditional |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block bool isConditionalBool = isConditional; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, 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 = _mWeaveCppGenericTraitUpdatableDataSink->SetData([path UTF8String], val, isConditionalBool); |
| }); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| - (WEAVE_ERROR)setDouble:(double)val path:(NSString *)path conditional:(BOOL)isConditional |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block bool isConditionalBool = isConditional; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, 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 = _mWeaveCppGenericTraitUpdatableDataSink->SetData([path UTF8String], val, isConditionalBool); |
| }); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| - (WEAVE_ERROR)setBoolean:(BOOL)val path:(NSString *)path conditional:(BOOL)isConditional |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block bool isConditionalBool = isConditional; |
| __block bool valBool = val; |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, 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 = _mWeaveCppGenericTraitUpdatableDataSink->SetBoolean([path UTF8String], valBool, isConditionalBool); |
| }); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| - (WEAVE_ERROR)setString:(NSString *)val path:(NSString *)path conditional:(BOOL)isConditional |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block bool isConditionalBool = isConditional; |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, 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 = _mWeaveCppGenericTraitUpdatableDataSink->SetString([path UTF8String], [val UTF8String], isConditionalBool); |
| }); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| - (WEAVE_ERROR)setNull:(NSString *)path conditional:(BOOL)isConditional |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block bool isConditionalBool = isConditional; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, 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 = _mWeaveCppGenericTraitUpdatableDataSink->SetNull([path UTF8String], isConditionalBool); |
| }); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| - (WEAVE_ERROR)setBytes:(NSData *)val path:(NSString *)path conditional:(BOOL)isConditional |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block bool isConditionalBool = isConditional; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, 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, ^() { |
| uint32_t valLen = (uint32_t)[val length]; |
| uint8_t * pVal = (uint8_t *) [val bytes]; |
| err = _mWeaveCppGenericTraitUpdatableDataSink->SetBytes([path UTF8String], pVal, valLen, isConditionalBool); |
| }); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| - (WEAVE_ERROR)setStringArray:(NSArray *)stringArray path:(NSString *)path conditional:(BOOL)isConditional |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block bool isConditionalBool = isConditional; |
| |
| std::vector<std::string> stringVector; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, err = WEAVE_ERROR_INCORRECT_STATE); |
| |
| for (id object in stringArray) { |
| stringVector.push_back(std::string([object UTF8String])); |
| } |
| // 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 = _mWeaveCppGenericTraitUpdatableDataSink->SetStringArray([path UTF8String], stringVector, isConditionalBool); |
| }); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| - (WEAVE_ERROR)setSigned:(int64_t)val path:(NSString *)path |
| { |
| return [self setSigned:val path:path conditional:NO]; |
| } |
| |
| - (WEAVE_ERROR)setUnsigned:(uint64_t)val path:(NSString *)path |
| |
| { |
| return [self setUnsigned:val path:path conditional:NO]; |
| } |
| |
| - (WEAVE_ERROR)setDouble:(double)val path:(NSString *)path |
| |
| { |
| return [self setDouble:val path:path conditional:NO]; |
| } |
| |
| - (WEAVE_ERROR)setBoolean:(BOOL)val path:(NSString *)path |
| { |
| return [self setBoolean:val path:path conditional:NO]; |
| } |
| |
| - (WEAVE_ERROR)setString:(NSString *)val path:(NSString *)path |
| { |
| return [self setString:val path:path conditional:NO]; |
| } |
| |
| - (WEAVE_ERROR)setNull:(NSString *)path |
| { |
| return [self setNull:path conditional:NO]; |
| } |
| |
| - (WEAVE_ERROR)setBytes:(NSData *)val path:(NSString *)path |
| { |
| return [self setBytes:val path:path conditional:NO]; |
| } |
| |
| - (WEAVE_ERROR)setStringArray:(NSArray *)stringArray path:(NSString *)path |
| { |
| return [self setStringArray:stringArray path:path conditional:NO]; |
| } |
| |
| - (WEAVE_ERROR)getSigned:(int64_t *)val path:(NSString *)path |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block int64_t result = 0; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, err = WEAVE_ERROR_INCORRECT_STATE); |
| VerifyOrExit(NULL != val, 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 = _mWeaveCppGenericTraitUpdatableDataSink->GetData([path UTF8String], result); |
| }); |
| } |
| |
| exit: |
| if ((WEAVE_NO_ERROR == err) && (NULL != val)) { |
| *val = result; |
| } |
| |
| return err; |
| } |
| |
| - (WEAVE_ERROR)getUnsigned:(uint64_t *)val path:(NSString *)path |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block uint64_t result = 0; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, err = WEAVE_ERROR_INCORRECT_STATE); |
| VerifyOrExit(NULL != val, 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 = _mWeaveCppGenericTraitUpdatableDataSink->GetData([path UTF8String], result); |
| }); |
| } |
| |
| exit: |
| if ((WEAVE_NO_ERROR == err) && (NULL != val)) { |
| *val = result; |
| } |
| |
| return err; |
| } |
| |
| - (WEAVE_ERROR)getDouble:(double *)val path:(NSString *)path |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block double result = 0; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, err = WEAVE_ERROR_INCORRECT_STATE); |
| VerifyOrExit(NULL != val, 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 = _mWeaveCppGenericTraitUpdatableDataSink->GetData([path UTF8String], result); |
| }); |
| } |
| |
| exit: |
| if ((WEAVE_NO_ERROR == err) && (NULL != val)) { |
| *val = result; |
| } |
| |
| return err; |
| } |
| |
| - (WEAVE_ERROR)getBoolean:(BOOL *)val path:(NSString *)path |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block bool result = false; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, err = WEAVE_ERROR_INCORRECT_STATE); |
| VerifyOrExit(NULL != val, 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 = _mWeaveCppGenericTraitUpdatableDataSink->GetBoolean([path UTF8String], result); |
| }); |
| } |
| |
| exit: |
| if ((WEAVE_NO_ERROR == err) && (NULL != val)) { |
| *val = result; |
| } |
| |
| return err; |
| } |
| |
| - (WEAVE_ERROR)getString:(NSString **)val path:(NSString *)path |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block nl::Weave::DeviceManager::BytesData bytesData; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, err = WEAVE_ERROR_INCORRECT_STATE); |
| |
| // need this bracket to use Verify macros |
| { |
| // we use sync so the bytesData is immediately available to the caller upon return |
| dispatch_sync(_mWeaveWorkQueue, ^() { |
| err = _mWeaveCppGenericTraitUpdatableDataSink->GetBytes([path UTF8String], &bytesData); |
| }); |
| } |
| |
| exit: |
| if ((WEAVE_NO_ERROR == err) && (NULL != val)) |
| { |
| *val = [[NSString alloc] initWithBytes:bytesData.mpDataBuf length:bytesData.mDataLen encoding:NSUTF8StringEncoding]; |
| } |
| return err; |
| } |
| |
| - (WEAVE_ERROR)isNull:(BOOL *)val path:(NSString *)path; |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block bool result = false; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, err = WEAVE_ERROR_INCORRECT_STATE); |
| VerifyOrExit(NULL != val, 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 = _mWeaveCppGenericTraitUpdatableDataSink->IsNull([path UTF8String], result); |
| }); |
| } |
| |
| exit: |
| if ((WEAVE_NO_ERROR == err) && (NULL != val)) { |
| *val = result; |
| } |
| |
| return err; |
| } |
| |
| - (WEAVE_ERROR)getBytes:(NSData **)val path:(NSString *)path |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block nl::Weave::DeviceManager::BytesData bytesData; |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, err = WEAVE_ERROR_INCORRECT_STATE); |
| VerifyOrExit(NULL != val, err = WEAVE_ERROR_INVALID_ARGUMENT); |
| |
| // need this bracket to use Verify macros |
| { |
| // we use sync so the bytesData is immediately available to the caller upon return |
| dispatch_sync(_mWeaveWorkQueue, ^() { |
| err = _mWeaveCppGenericTraitUpdatableDataSink->GetBytes([path UTF8String], &bytesData); |
| }); |
| } |
| |
| exit: |
| if ((WEAVE_NO_ERROR == err) && (NULL != val)) |
| { |
| *val = [NSData dataWithBytes:bytesData.mpDataBuf length:bytesData.mDataLen]; |
| } |
| |
| return err; |
| } |
| |
| - (WEAVE_ERROR)getStringArray:(NSMutableArray **)val path:(NSString *)path |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block std::vector<std::string> stringVector; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, err = WEAVE_ERROR_INCORRECT_STATE); |
| VerifyOrExit(NULL != val, err = WEAVE_ERROR_INVALID_ARGUMENT); |
| |
| // need this bracket to use Verify macros |
| { |
| // we use sync so the stringVector is immediately available to the caller upon return |
| dispatch_sync(_mWeaveWorkQueue, ^() { |
| err = _mWeaveCppGenericTraitUpdatableDataSink->GetStringArray([path UTF8String], stringVector); |
| }); |
| } |
| |
| exit: |
| if ((WEAVE_NO_ERROR == err) && (NULL != val)) |
| { |
| *val = [[NSMutableArray alloc] init]; |
| for (auto iter = stringVector.begin(); iter < stringVector.end(); iter++) { |
| [*val addObject:[NSString stringWithCString:iter->c_str() encoding:[NSString defaultCStringEncoding]]]; |
| } |
| } |
| return err; |
| } |
| |
| - (WEAVE_ERROR)getVersion:(uint64_t *)val |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| __block uint64_t result = 0; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, err = WEAVE_ERROR_INCORRECT_STATE); |
| VerifyOrExit(NULL != val, 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, ^() { |
| result = _mWeaveCppGenericTraitUpdatableDataSink->GetVersion(); |
| }); |
| } |
| |
| exit: |
| if ((WEAVE_NO_ERROR == err) && (NULL != val)) { |
| *val = result; |
| } |
| |
| return err; |
| } |
| |
| - (WEAVE_ERROR)deleteData:(NSString *)path |
| { |
| __block WEAVE_ERROR err = WEAVE_NO_ERROR; |
| |
| WDM_LOG_METHOD_SIG(); |
| |
| VerifyOrExit(NULL != _mWeaveCppGenericTraitUpdatableDataSink, 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 = _mWeaveCppGenericTraitUpdatableDataSink->DeleteData([path UTF8String]); |
| }); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| @end |
| #endif // WEAVE_CONFIG_DATA_MANAGEMENT_CLIENT_EXPERIMENTAL |