1 /* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "napi_parser_utils.h" 17 18 #include <string> 19 #include <vector> 20 21 #include "napi_async_callback.h" 22 23 namespace OHOS { 24 namespace Bluetooth { 25 26 // shall check object type is napi_object before, if it's other type, return false 27 // If the 'name' field is not exist, or napi function call error, return false NapiIsObjectPropertyExist(napi_env env,napi_value object,const char * name)28 static bool NapiIsObjectPropertyExist(napi_env env, napi_value object, const char *name) 29 { 30 auto status = NapiIsObject(env, object); 31 if (status != napi_ok) { 32 HILOGE("expect object"); 33 return false; 34 } 35 bool exist = false; 36 status = napi_has_named_property(env, object, name, &exist); 37 if (status != napi_ok) { 38 HILOGE("Get object property failed, name: %{public}s", name); 39 return false; 40 } 41 return exist; 42 } 43 NapiParseGattService(napi_env env,napi_value object,NapiGattService & outService)44 napi_status NapiParseGattService(napi_env env, napi_value object, NapiGattService &outService) 45 { 46 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "isPrimary", "characteristics", 47 "includeServices"})); 48 49 std::string uuid {}; 50 bool isPrimary = true; 51 std::vector<NapiBleCharacteristic> characteristics {}; 52 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 53 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", uuid)); 54 NAPI_BT_CALL_RETURN(NapiParseObjectBoolean(env, object, "isPrimary", isPrimary)); 55 NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "characteristics", characteristics)); 56 if (NapiIsObjectPropertyExist(env, object, "includeServices")) { 57 std::vector<NapiGattService> includeServices {}; 58 NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "includeServices", includeServices)); 59 outService.includeServices = std::move(includeServices); 60 } 61 outService.serviceUuid = UUID::FromString(uuid); 62 outService.isPrimary = isPrimary; 63 outService.characteristics = std::move(characteristics); 64 return napi_ok; 65 } 66 67 namespace { 68 const NapiGattPermission DEFAULT_GATT_PERMISSIONS = { 69 .readable = true, 70 .writeable = true, 71 }; 72 const NapiGattProperties DEFAULT_GATT_PROPERTIES = { 73 .write = true, 74 .writeNoResponse = true, 75 .read = true, 76 }; ConvertGattPermissions(const NapiGattPermission & napiPermissions)77 uint16_t ConvertGattPermissions(const NapiGattPermission &napiPermissions) 78 { 79 uint16_t permissions = 0; 80 if (napiPermissions.readable) { 81 permissions |= static_cast<uint16_t>(GattPermission::READABLE); 82 } 83 if (napiPermissions.writeable) { 84 permissions |= static_cast<uint16_t>(GattPermission::WRITEABLE); 85 } 86 if (napiPermissions.readEncrypted) { 87 permissions |= static_cast<uint16_t>(GattPermission::READ_ENCRYPTED_MITM); 88 } 89 if (napiPermissions.writeEncrypted) { 90 permissions |= static_cast<uint16_t>(GattPermission::WRITE_ENCRYPTED_MITM); 91 } 92 return permissions; 93 } ConvertGattProperties(const NapiGattProperties & napiProperties)94 uint16_t ConvertGattProperties(const NapiGattProperties &napiProperties) 95 { 96 uint16_t properties = 0; 97 if (napiProperties.read) { 98 properties |= static_cast<uint16_t>(GattCharacteristic::READ); 99 } 100 if (napiProperties.write) { 101 properties |= static_cast<uint16_t>(GattCharacteristic::WRITE); 102 } 103 if (napiProperties.writeNoResponse) { 104 properties |= static_cast<uint16_t>(GattCharacteristic::WRITE_WITHOUT_RESPONSE); 105 } 106 if (napiProperties.notify) { 107 properties |= static_cast<uint16_t>(GattCharacteristic::NOTIFY); 108 } 109 if (napiProperties.indicate) { 110 properties |= static_cast<uint16_t>(GattCharacteristic::INDICATE); 111 } 112 return properties; 113 } 114 } // namespace {} 115 NapiParseGattCharacteristic(napi_env env,napi_value object,NapiBleCharacteristic & outCharacteristic)116 napi_status NapiParseGattCharacteristic(napi_env env, napi_value object, NapiBleCharacteristic &outCharacteristic) 117 { 118 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid", 119 "characteristicValue", "descriptors", "properties", "permissions"})); 120 121 std::string serviceUuid {}; 122 std::string characterUuid {}; 123 std::vector<uint8_t> characterValue {}; 124 std::vector<NapiBleDescriptor> descriptors {}; 125 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 126 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid)); 127 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid)); 128 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue)); 129 NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "descriptors", descriptors)); 130 131 NapiGattProperties properties = DEFAULT_GATT_PROPERTIES; 132 if (NapiIsObjectPropertyExist(env, object, "properties")) { 133 NAPI_BT_CALL_RETURN(NapiParseObjectGattProperties(env, object, "properties", properties)); 134 } 135 NapiGattPermission permissions = DEFAULT_GATT_PERMISSIONS; 136 if (NapiIsObjectPropertyExist(env, object, "permissions")) { 137 NAPI_BT_CALL_RETURN(NapiParseObjectGattPermissions(env, object, "permissions", permissions)); 138 } 139 140 outCharacteristic.serviceUuid = UUID::FromString(serviceUuid); 141 outCharacteristic.characteristicUuid = UUID::FromString(characterUuid); 142 outCharacteristic.characteristicValue = std::move(characterValue); 143 outCharacteristic.descriptors = std::move(descriptors); 144 outCharacteristic.properties = ConvertGattProperties(properties); 145 outCharacteristic.permissions = ConvertGattPermissions(permissions); 146 return napi_ok; 147 } 148 NapiParseGattDescriptor(napi_env env,napi_value object,NapiBleDescriptor & outDescriptor)149 napi_status NapiParseGattDescriptor(napi_env env, napi_value object, NapiBleDescriptor &outDescriptor) 150 { 151 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid", 152 "descriptorUuid", "descriptorValue", "permissions"})); 153 154 std::string serviceUuid {}; 155 std::string characterUuid {}; 156 std::string descriptorUuid {}; 157 std::vector<uint8_t> descriptorValue {}; 158 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 159 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid)); 160 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid)); 161 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "descriptorUuid", descriptorUuid)); 162 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "descriptorValue", descriptorValue)); 163 164 NapiGattPermission permissions = DEFAULT_GATT_PERMISSIONS; 165 if (NapiIsObjectPropertyExist(env, object, "permissions")) { 166 NAPI_BT_CALL_RETURN(NapiParseObjectGattPermissions(env, object, "permissions", permissions)); 167 } 168 169 outDescriptor.serviceUuid = UUID::FromString(serviceUuid); 170 outDescriptor.characteristicUuid = UUID::FromString(characterUuid); 171 outDescriptor.descriptorUuid = UUID::FromString(descriptorUuid); 172 outDescriptor.descriptorValue = std::move(descriptorValue); 173 outDescriptor.permissions = ConvertGattPermissions(permissions); 174 return napi_ok; 175 } 176 NapiParseNotifyCharacteristic(napi_env env,napi_value object,NapiNotifyCharacteristic & outCharacter)177 napi_status NapiParseNotifyCharacteristic(napi_env env, napi_value object, NapiNotifyCharacteristic &outCharacter) 178 { 179 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid", 180 "characteristicValue", "confirm"})); 181 182 std::string serviceUuid {}; 183 std::string characterUuid {}; 184 std::vector<uint8_t> characterValue {}; 185 bool confirm = false; 186 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 187 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid)); 188 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid)); 189 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue)); 190 NAPI_BT_CALL_RETURN(NapiParseObjectBoolean(env, object, "confirm", confirm)); 191 192 outCharacter.serviceUuid = UUID::FromString(serviceUuid); 193 outCharacter.characterUuid = UUID::FromString(characterUuid); 194 outCharacter.characterValue = std::move(characterValue); 195 outCharacter.confirm = confirm; 196 return napi_ok; 197 } 198 NapiParseGattsServerResponse(napi_env env,napi_value object,NapiGattsServerResponse & rsp)199 napi_status NapiParseGattsServerResponse(napi_env env, napi_value object, NapiGattsServerResponse &rsp) 200 { 201 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"deviceId", "transId", "status", "offset", 202 "value"})); 203 204 std::string deviceId {}; 205 int transId = 0; 206 int status = 0; 207 int offset = 0; 208 std::vector<uint8_t> value {}; 209 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 210 NAPI_BT_CALL_RETURN(NapiParseObjectBdAddr(env, object, "deviceId", deviceId)); 211 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "transId", transId)); 212 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "status", status)); 213 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "offset", offset)); 214 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "value", value)); 215 216 rsp.deviceId = deviceId; 217 rsp.transId = transId; 218 rsp.status = status; 219 rsp.offset = offset; 220 rsp.value = std::move(value); 221 return napi_ok; 222 } 223 NapiParseObjectGattPermissions(napi_env env,napi_value object,const char * name,NapiGattPermission & outPermissions)224 napi_status NapiParseObjectGattPermissions(napi_env env, napi_value object, const char *name, 225 NapiGattPermission &outPermissions) 226 { 227 napi_value permissionObject; 228 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 229 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, permissionObject)); 230 // Parse permission object 231 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, permissionObject, {"readable", "writeable", 232 "readEncrypted", "writeEncrypted"})); 233 234 bool isExist; 235 NapiGattPermission permissions {}; 236 NAPI_BT_CALL_RETURN( 237 NapiParseObjectBooleanOptional(env, permissionObject, "readable", permissions.readable, isExist)); 238 NAPI_BT_CALL_RETURN( 239 NapiParseObjectBooleanOptional(env, permissionObject, "writeable", permissions.writeable, isExist)); 240 NAPI_BT_CALL_RETURN( 241 NapiParseObjectBooleanOptional(env, permissionObject, "readEncrypted", permissions.readEncrypted, isExist)); 242 NAPI_BT_CALL_RETURN( 243 NapiParseObjectBooleanOptional(env, permissionObject, "writeEncrypted", permissions.writeEncrypted, isExist)); 244 outPermissions = permissions; 245 return napi_ok; 246 } 247 NapiParseObjectGattProperties(napi_env env,napi_value object,const char * name,NapiGattProperties & outProperties)248 napi_status NapiParseObjectGattProperties(napi_env env, napi_value object, const char *name, 249 NapiGattProperties &outProperties) 250 { 251 napi_value propertiesObject; 252 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 253 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, propertiesObject)); 254 // Parse properties object 255 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, propertiesObject, {"write", "writeNoResponse", 256 "read", "notify", "indicate"})); 257 258 bool isExist; 259 NapiGattProperties properties {}; 260 NAPI_BT_CALL_RETURN( 261 NapiParseObjectBooleanOptional(env, propertiesObject, "write", properties.write, isExist)); 262 NAPI_BT_CALL_RETURN( 263 NapiParseObjectBooleanOptional(env, propertiesObject, "writeNoResponse", properties.writeNoResponse, isExist)); 264 NAPI_BT_CALL_RETURN( 265 NapiParseObjectBooleanOptional(env, propertiesObject, "read", properties.read, isExist)); 266 NAPI_BT_CALL_RETURN( 267 NapiParseObjectBooleanOptional(env, propertiesObject, "notify", properties.notify, isExist)); 268 NAPI_BT_CALL_RETURN( 269 NapiParseObjectBooleanOptional(env, propertiesObject, "indicate", properties.indicate, isExist)); 270 outProperties = properties; 271 return napi_ok; 272 } 273 NapiParseBoolean(napi_env env,napi_value value,bool & outBoolean)274 napi_status NapiParseBoolean(napi_env env, napi_value value, bool &outBoolean) 275 { 276 bool boolean = false; 277 NAPI_BT_CALL_RETURN(NapiIsBoolean(env, value)); 278 NAPI_BT_CALL_RETURN(napi_get_value_bool(env, value, &boolean)); 279 outBoolean = boolean; 280 return napi_ok; 281 } 282 NapiParseInt32(napi_env env,napi_value value,int32_t & outNum)283 napi_status NapiParseInt32(napi_env env, napi_value value, int32_t &outNum) 284 { 285 int32_t num = 0; 286 NAPI_BT_CALL_RETURN(NapiIsNumber(env, value)); 287 NAPI_BT_CALL_RETURN(napi_get_value_int32(env, value, &num)); 288 outNum = num; 289 return napi_ok; 290 } 291 NapiParseUint32(napi_env env,napi_value value,uint32_t & outNum)292 napi_status NapiParseUint32(napi_env env, napi_value value, uint32_t &outNum) 293 { 294 uint32_t num = 0; 295 NAPI_BT_CALL_RETURN(NapiIsNumber(env, value)); 296 NAPI_BT_CALL_RETURN(napi_get_value_uint32(env, value, &num)); 297 outNum = num; 298 return napi_ok; 299 } 300 NapiParseString(napi_env env,napi_value value,std::string & outStr)301 napi_status NapiParseString(napi_env env, napi_value value, std::string &outStr) 302 { 303 std::string str {}; 304 NAPI_BT_CALL_RETURN(NapiIsString(env, value)); 305 NAPI_BT_RETURN_IF(!ParseString(env, str, value), "parse string failed", napi_invalid_arg); 306 outStr = std::move(str); 307 return napi_ok; 308 } 309 NapiParseBdAddr(napi_env env,napi_value value,std::string & outAddr)310 napi_status NapiParseBdAddr(napi_env env, napi_value value, std::string &outAddr) 311 { 312 std::string bdaddr {}; 313 NAPI_BT_CALL_RETURN(NapiParseString(env, value, bdaddr)); 314 NAPI_BT_RETURN_IF(!IsValidAddress(bdaddr), "Invalid bdaddr", napi_invalid_arg); 315 outAddr = std::move(bdaddr); 316 return napi_ok; 317 } 318 NapiParseUuid(napi_env env,napi_value value,std::string & outUuid)319 napi_status NapiParseUuid(napi_env env, napi_value value, std::string &outUuid) 320 { 321 std::string uuid {}; 322 NAPI_BT_CALL_RETURN(NapiParseString(env, value, uuid)); 323 NAPI_BT_RETURN_IF(!IsValidUuid(uuid), "Invalid uuid", napi_invalid_arg); 324 outUuid = std::move(uuid); 325 return napi_ok; 326 } 327 NapiParseArrayBuffer(napi_env env,napi_value value,std::vector<uint8_t> & outVec)328 napi_status NapiParseArrayBuffer(napi_env env, napi_value value, std::vector<uint8_t> &outVec) 329 { 330 uint8_t *data = nullptr; 331 size_t size = 0; 332 NAPI_BT_CALL_RETURN(NapiIsArrayBuffer(env, value)); 333 bool isSuccess = ParseArrayBuffer(env, &data, size, value); 334 if (!isSuccess) { 335 HILOGE("Parse arraybuffer failed"); 336 return napi_invalid_arg; 337 } 338 std::vector<uint8_t> vec(data, data + size); 339 outVec = std::move(vec); 340 return napi_ok; 341 } 342 NapiParseGattWriteType(napi_env env,napi_value value,int & outWriteType)343 napi_status NapiParseGattWriteType(napi_env env, napi_value value, int &outWriteType) 344 { 345 int writeType = -1; 346 NAPI_BT_CALL_RETURN(NapiParseInt32(env, value, writeType)); 347 if (writeType == static_cast<int>(NapiGattWriteType::WRITE)) { 348 HILOGI("gattWriteType: WRITE"); 349 outWriteType = GattCharacteristic::WriteType::DEFAULT; 350 } else if (writeType == static_cast<int>(NapiGattWriteType::WRITE_NO_RESPONSE)) { 351 HILOGI("gattWriteType: WRITE_NO_RESPONSE"); 352 outWriteType = GattCharacteristic::WriteType::NO_RESPONSE; 353 } else { 354 HILOGE("Invalid gattWriteType: %{public}d", writeType); 355 return napi_invalid_arg; 356 } 357 return napi_ok; 358 } 359 NapiParseAsyncCallback(napi_env env,napi_callback_info info)360 std::shared_ptr<NapiAsyncCallback> NapiParseAsyncCallback(napi_env env, napi_callback_info info) 361 { 362 size_t argc = ARGS_SIZE_FOUR; 363 napi_value argv[ARGS_SIZE_FOUR] = {nullptr}; 364 auto status = napi_get_cb_info(env, info, &argc, argv, nullptr, NULL); 365 if (status != napi_ok) { 366 HILOGE("napi_get_cb_info failed"); 367 return nullptr; 368 } 369 if (argc > ARGS_SIZE_FOUR) { 370 HILOGE("size of parameters is larger than ARGS_SIZE_FOUR"); 371 return nullptr; 372 } 373 374 // "argc - 1" is AsyncCallback parameter's index 375 auto asyncCallback = std::make_shared<NapiAsyncCallback>(); 376 asyncCallback->env = env; 377 if (argc > 0 && NapiIsFunction(env, argv[argc - 1]) == napi_ok) { 378 HILOGD("callback mode"); 379 asyncCallback->callback = std::make_shared<NapiCallback>(env, argv[argc - 1]); 380 } else { 381 HILOGD("promise mode"); 382 asyncCallback->promise = std::make_shared<NapiPromise>(env); 383 } 384 return asyncCallback; 385 } 386 NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)387 static napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty, 388 bool &outExist) 389 { 390 bool exist = false; 391 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 392 NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &exist)); 393 if (exist) { 394 napi_value property; 395 NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property)); 396 outProperty = property; 397 } 398 outExist = exist; 399 return napi_ok; 400 } NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty)401 napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty) 402 { 403 bool exist = false; 404 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, outProperty, exist)); 405 NAPI_BT_RETURN_IF(!exist, "no needed property", napi_invalid_arg); 406 return napi_ok; 407 } NapiGetObjectPropertyOptional(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)408 napi_status NapiGetObjectPropertyOptional(napi_env env, napi_value object, const char *name, napi_value &outProperty, 409 bool &outExist) 410 { 411 return NapiGetObjectProperty(env, object, name, outProperty, outExist); 412 } 413 NapiParseObjectBoolean(napi_env env,napi_value object,const char * name,bool & outBoolean)414 napi_status NapiParseObjectBoolean(napi_env env, napi_value object, const char *name, bool &outBoolean) 415 { 416 napi_value property; 417 bool boolean = true; 418 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 419 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property)); 420 NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean)); 421 outBoolean = boolean; 422 return napi_ok; 423 } 424 NapiParseObjectUuid(napi_env env,napi_value object,const char * name,std::string & outUuid)425 napi_status NapiParseObjectUuid(napi_env env, napi_value object, const char *name, std::string &outUuid) 426 { 427 napi_value property; 428 std::string uuid {}; 429 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 430 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property)); 431 NAPI_BT_CALL_RETURN(NapiParseUuid(env, property, uuid)); 432 outUuid = std::move(uuid); 433 return napi_ok; 434 } 435 NapiParseObjectArrayBuffer(napi_env env,napi_value object,const char * name,std::vector<uint8_t> & outVec)436 napi_status NapiParseObjectArrayBuffer(napi_env env, napi_value object, const char *name, std::vector<uint8_t> &outVec) 437 { 438 napi_value property; 439 std::vector<uint8_t> vec {}; 440 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 441 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property)); 442 NAPI_BT_CALL_RETURN(NapiParseArrayBuffer(env, property, vec)); 443 outVec = std::move(vec); 444 return napi_ok; 445 } 446 NapiParseObjectBdAddr(napi_env env,napi_value object,const char * name,std::string & outAddr)447 napi_status NapiParseObjectBdAddr(napi_env env, napi_value object, const char *name, std::string &outAddr) 448 { 449 napi_value property; 450 std::string bdaddr {}; 451 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 452 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property)); 453 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, property, bdaddr)); 454 outAddr = std::move(bdaddr); 455 return napi_ok; 456 } 457 NapiParseObjectInt32(napi_env env,napi_value object,const char * name,int32_t & outNum)458 napi_status NapiParseObjectInt32(napi_env env, napi_value object, const char *name, int32_t &outNum) 459 { 460 napi_value property; 461 int32_t num = 0; 462 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 463 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property)); 464 NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num)); 465 outNum = num; 466 return napi_ok; 467 } 468 NapiParseObjectUint32(napi_env env,napi_value object,const char * name,uint32_t & outNum)469 napi_status NapiParseObjectUint32(napi_env env, napi_value object, const char *name, uint32_t &outNum) 470 { 471 napi_value property; 472 uint32_t num = 0; 473 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 474 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property)); 475 NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num)); 476 outNum = num; 477 return napi_ok; 478 } 479 NapiParseObjectBooleanOptional(napi_env env,napi_value object,const char * name,bool & outBoolean,bool & outExist)480 napi_status NapiParseObjectBooleanOptional(napi_env env, napi_value object, const char *name, bool &outBoolean, 481 bool &outExist) 482 { 483 napi_value property; 484 bool exist = false; 485 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 486 NAPI_BT_CALL_RETURN(NapiGetObjectPropertyOptional(env, object, name, property, exist)); 487 if (exist) { 488 bool boolean = true; 489 NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean)); 490 outBoolean = boolean; 491 } 492 outExist = exist; 493 return napi_ok; 494 } NapiParseObjectInt32Optional(napi_env env,napi_value object,const char * name,int32_t & outNum,bool & outExist)495 napi_status NapiParseObjectInt32Optional(napi_env env, napi_value object, const char *name, int32_t &outNum, 496 bool &outExist) 497 { 498 napi_value property; 499 bool exist = false; 500 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 501 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist)); 502 if (exist) { 503 int32_t num = 0; 504 NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num)); 505 outNum = num; 506 } 507 outExist = exist; 508 return napi_ok; 509 } NapiParseObjectUint32Optional(napi_env env,napi_value object,const char * name,uint32_t & outNum,bool & outExist)510 napi_status NapiParseObjectUint32Optional(napi_env env, napi_value object, const char *name, uint32_t &outNum, 511 bool &outExist) 512 { 513 napi_value property; 514 bool exist = false; 515 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 516 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist)); 517 if (exist) { 518 uint32_t num = 0; 519 NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num)); 520 outNum = num; 521 } 522 outExist = exist; 523 return napi_ok; 524 } 525 526 // Parse params template, used for NapiParseArray 527 template <typename T> NapiParseObject(napi_env env,napi_value object,T & outObj)528 napi_status NapiParseObject(napi_env env, napi_value object, T &outObj) 529 { 530 HILOGE("Unimpleted type"); 531 return napi_invalid_arg; 532 } 533 534 template <> NapiParseObject(napi_env env,napi_value object,std::string & outObj)535 napi_status NapiParseObject<std::string>(napi_env env, napi_value object, std::string &outObj) 536 { 537 return NapiParseString(env, object, outObj); 538 } 539 540 template <> NapiParseObject(napi_env env,napi_value object,UUID & outObj)541 napi_status NapiParseObject<UUID>(napi_env env, napi_value object, UUID &outObj) 542 { 543 std::string uuid {}; 544 NAPI_BT_CALL_RETURN(NapiParseUuid(env, object, uuid)); 545 outObj = UUID::FromString(uuid); 546 return napi_ok; 547 } 548 549 template <> NapiParseObject(napi_env env,napi_value object,NapiAdvManufactureData & outObj)550 napi_status NapiParseObject<NapiAdvManufactureData>(napi_env env, napi_value object, NapiAdvManufactureData &outObj) 551 { 552 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"manufactureId", "manufactureValue"})); 553 uint32_t num = 0; 554 std::vector<uint8_t> vec {}; 555 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 556 NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "manufactureId", num)); 557 NAPI_BT_RETURN_IF(num > 0xFFFF, "Invalid manufactureId", napi_invalid_arg); 558 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "manufactureValue", vec)); 559 560 outObj.id = static_cast<uint16_t>(num); 561 outObj.value = std::string(vec.begin(), vec.end()); 562 return napi_ok; 563 } 564 565 template <> NapiParseObject(napi_env env,napi_value object,NapiAdvServiceData & outObj)566 napi_status NapiParseObject<NapiAdvServiceData>(napi_env env, napi_value object, NapiAdvServiceData &outObj) 567 { 568 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "serviceValue"})); 569 std::string uuid {}; 570 std::vector<uint8_t> vec {}; 571 NAPI_BT_CALL_RETURN(NapiIsObject(env, object)); 572 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", uuid)); 573 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "serviceValue", vec)); 574 575 outObj.uuid = std::move(uuid); 576 outObj.value = std::move(vec); 577 return napi_ok; 578 } 579 580 template <> NapiParseObject(napi_env env,napi_value object,NapiGattService & outObj)581 napi_status NapiParseObject<NapiGattService>(napi_env env, napi_value object, NapiGattService &outObj) 582 { 583 return NapiParseGattService(env, object, outObj); 584 } 585 586 template <> NapiParseObject(napi_env env,napi_value object,NapiBleCharacteristic & outObj)587 napi_status NapiParseObject<NapiBleCharacteristic>(napi_env env, napi_value object, NapiBleCharacteristic &outObj) 588 { 589 return NapiParseGattCharacteristic(env, object, outObj); 590 } 591 592 template <> NapiParseObject(napi_env env,napi_value object,NapiBleDescriptor & outObj)593 napi_status NapiParseObject<NapiBleDescriptor>(napi_env env, napi_value object, NapiBleDescriptor &outObj) 594 { 595 return NapiParseGattDescriptor(env, object, outObj); 596 } 597 598 template <typename T> NapiParseArray(napi_env env,napi_value array,std::vector<T> & outVec)599 napi_status NapiParseArray(napi_env env, napi_value array, std::vector<T> &outVec) 600 { 601 std::vector<T> vec {}; 602 603 NAPI_BT_CALL_RETURN(NapiIsArray(env, array)); 604 uint32_t length = 0; 605 NAPI_BT_CALL_RETURN(napi_get_array_length(env, array, &length)); 606 for (uint32_t i = 0; i < length; ++i) { 607 napi_value element; 608 NAPI_BT_CALL_RETURN(napi_get_element(env, array, i, &element)); 609 T object; 610 NAPI_BT_CALL_RETURN(NapiParseObject(env, element, object)); 611 vec.push_back(std::move(object)); 612 } 613 outVec = std::move(vec); 614 return napi_ok; 615 } 616 // // Declaration, ohters will undefined synbol 617 template napi_status NapiParseArray<NapiBleDescriptor>(napi_env env, napi_value array, 618 std::vector<NapiBleDescriptor> &outVec); 619 template napi_status NapiParseArray<NapiBleCharacteristic>(napi_env env, napi_value array, 620 std::vector<NapiBleCharacteristic> &outVec); 621 template napi_status NapiParseArray<NapiGattService>(napi_env env, napi_value array, 622 std::vector<NapiGattService> &outVec); 623 template napi_status NapiParseArray<NapiAdvServiceData>(napi_env env, napi_value array, 624 std::vector<NapiAdvServiceData> &outVec); 625 template napi_status NapiParseArray<NapiAdvManufactureData>(napi_env env, napi_value array, 626 std::vector<NapiAdvManufactureData> &outVec); 627 template napi_status NapiParseArray<UUID>(napi_env env, napi_value array, 628 std::vector<UUID> &outVec); 629 template napi_status NapiParseArray<std::string>(napi_env env, napi_value array, 630 std::vector<std::string> &outVec); 631 632 633 template <typename T> NapiParseObjectArray(napi_env env,napi_value object,const char * name,std::vector<T> & outVec)634 napi_status NapiParseObjectArray(napi_env env, napi_value object, const char *name, std::vector<T> &outVec) 635 { 636 napi_value property; 637 std::vector<T> vec {}; 638 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property)); 639 NAPI_BT_CALL_RETURN(NapiParseArray(env, property, vec)); 640 outVec = std::move(vec); 641 return napi_ok; 642 } 643 // Declaration, ohters will undefined synbol 644 template napi_status NapiParseObjectArray<NapiBleDescriptor>(napi_env env, napi_value object, const char *name, 645 std::vector<NapiBleDescriptor> &outVec); 646 template napi_status NapiParseObjectArray<NapiBleCharacteristic>(napi_env env, napi_value object, const char *name, 647 std::vector<NapiBleCharacteristic> &outVec); 648 template napi_status NapiParseObjectArray<NapiGattService>(napi_env env, napi_value object, const char *name, 649 std::vector<NapiGattService> &outVec); 650 template napi_status NapiParseObjectArray<NapiAdvServiceData>(napi_env env, napi_value object, const char *name, 651 std::vector<NapiAdvServiceData> &outVec); 652 template napi_status NapiParseObjectArray<NapiAdvManufactureData>(napi_env env, napi_value object, const char *name, 653 std::vector<NapiAdvManufactureData> &outVec); 654 template napi_status NapiParseObjectArray<UUID>(napi_env env, napi_value object, const char *name, 655 std::vector<UUID> &outVec); 656 template napi_status NapiParseObjectArray<std::string>(napi_env env, napi_value object, const char *name, 657 std::vector<std::string> &outVec); 658 } // namespace Bluetooth 659 } // namespace OHOS 660