• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 #include "napi_bluetooth_ble.h"
16 
17 #include "napi_bluetooth_ble_advertise_callback.h"
18 #include "napi_bluetooth_ble_central_manager_callback.h"
19 #include "napi_bluetooth_error.h"
20 #include "napi_bluetooth_gatt_client.h"
21 #include "napi_bluetooth_gatt_server.h"
22 #include "napi_bluetooth_utils.h"
23 #include "napi_bluetooth_ble_utils.h"
24 
25 #include "bluetooth_ble_advertiser.h"
26 #include "bluetooth_ble_central_manager.h"
27 #include "bluetooth_errorcode.h"
28 #include "bluetooth_utils.h"
29 #include "../parser/napi_parser_utils.h"
30 
31 #include <memory>
32 namespace OHOS {
33 namespace Bluetooth {
34 namespace {
35 struct SysStopBLEContext {
36     napi_async_work work = nullptr;
37     napi_ref callbackSuccess = nullptr;
38     napi_ref callbackFail = nullptr;
39     napi_ref callbackComplete = nullptr;
40 };
41 
42 namespace {
BleAdvertiserGetInstance(void)43 BleAdvertiser *BleAdvertiserGetInstance(void)
44 {
45     static BleAdvertiser instance;
46     return &instance;
47 }
48 
BleCentralManagerGetInstance(void)49 BleCentralManager *BleCentralManagerGetInstance(void)
50 {
51     static BleCentralManager instance(NapiBluetoothBleCentralManagerCallback::GetInstance());
52     return &instance;
53 }
54 }  // namespace {}
55 
GetPropertyValueByNamed(napi_env env,napi_value object,std::string_view propertyName,napi_valuetype type)56 napi_value GetPropertyValueByNamed(napi_env env, napi_value object, std::string_view propertyName, napi_valuetype type)
57 {
58     napi_value value = nullptr;
59     bool hasProperty = false;
60     napi_valuetype paraType = napi_undefined;
61 
62     NAPI_CALL(env, napi_has_named_property(env, object, propertyName.data(), &hasProperty));
63     if (hasProperty) {
64         NAPI_CALL(env, napi_get_named_property(env, object, propertyName.data(), &value));
65         NAPI_CALL(env, napi_typeof(env, value, &paraType));
66         if (paraType != type) {
67             return NapiGetNull(env);
68         }
69     }
70     return value;
71 }
72 
RegisterBLEObserver(napi_env env,napi_value val,int32_t callbackIndex,const std::string & type)73 void RegisterBLEObserver(napi_env env, napi_value val, int32_t callbackIndex, const std::string &type)
74 {
75     std::shared_ptr<BluetoothCallbackInfo> pCallbackInfo = std::make_shared<BluetoothCallbackInfo>();
76     pCallbackInfo->env_ = env;
77     napi_create_reference(env, val, 1, &pCallbackInfo->callback_);
78     RegisterSysBLEObserver(pCallbackInfo, callbackIndex, type);
79 }
80 
ParseScanParameters(napi_env env,napi_value arg,ScanOptions & info)81 bool ParseScanParameters(napi_env env, napi_value arg, ScanOptions &info)
82 {
83     napi_value interval = GetPropertyValueByNamed(env, arg, "interval", napi_number);
84     if (interval) {
85         napi_get_value_int32(env, interval, &info.interval);
86         HILOGI("Scan interval is %{public}d", info.interval);
87     } else {
88         info.interval = 0;
89     }
90 
91     std::array<std::string, ARGS_SIZE_THREE> funcArray {"success", "fail", "complete"};
92 
93     for (size_t i = 0; i < funcArray.size(); i++) {
94         napi_value value = GetPropertyValueByNamed(env, arg, funcArray[i], napi_function);
95         if (value) {
96             RegisterBLEObserver(env, value, i, REGISTER_SYS_BLE_SCAN_TYPE);
97         } else {
98             UnregisterSysBLEObserver(REGISTER_SYS_BLE_SCAN_TYPE);
99             return false;
100         }
101     }
102     return true;
103 }
104 
SysStartBLEScan(napi_env env,napi_callback_info info)105 napi_value SysStartBLEScan(napi_env env, napi_callback_info info)
106 {
107     size_t argc = ARGS_SIZE_ONE;
108     napi_value argv[] = {nullptr};
109     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
110     if (argc != 1) {
111         return NapiGetNull(env);
112     }
113 
114     napi_valuetype valueType = napi_undefined;
115     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
116     if (valueType != napi_object) {
117         return NapiGetNull(env);
118     }
119     ScanOptions scanOptions;
120     if (!ParseScanParameters(env, argv[PARAM0], scanOptions)) {
121         HILOGE("SysStartBLEScan Input parameter parsing failed!");
122         return NapiGetNull(env);
123     }
124 
125     BleScanSettings settinngs;
126     settinngs.SetReportDelay(scanOptions.interval);
127     settinngs.SetScanMode(static_cast<int32_t>(scanOptions.dutyMode));
128 
129     BleCentralManagerGetInstance()->StartScan(settinngs);
130     return NapiGetNull(env);
131 }
132 
SysStopBLEScanExec(napi_env env,void * data)133 void SysStopBLEScanExec(napi_env env, void *data)
134 {
135     HILOGI("SysStopBLEScanExec");
136     BleCentralManagerGetInstance()->StopScan();
137     UnregisterSysBLEObserver(REGISTER_SYS_BLE_SCAN_TYPE);
138 }
139 
SysStopBLEScanComplete(napi_env env,napi_status status,void * data)140 void SysStopBLEScanComplete(napi_env env, napi_status status, void *data)
141 {
142     NAPI_CALL_RETURN_VOID(env, (data == nullptr ? napi_invalid_arg : napi_ok));
143     std::unique_ptr<SysStopBLEContext> context(static_cast<SysStopBLEContext *>(data));
144 
145     napi_value undefine = nullptr;
146     NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefine));
147     napi_value funcComplete = nullptr;
148     napi_value funcSuccess = nullptr;
149     napi_value callbackResult = nullptr;
150     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, context->callbackSuccess, &funcSuccess));
151     NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefine, funcSuccess, 0, nullptr, &callbackResult));
152     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, context->callbackComplete, &funcComplete));
153     NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefine, funcComplete, 0, nullptr, &callbackResult));
154     NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, context->callbackSuccess));
155     NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, context->callbackComplete));
156     NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, context->callbackFail));
157     NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, context->work));
158     HILOGI("SysStopBLEScanComplete end");
159 }
160 
SysStopBLEScan(napi_env env,napi_callback_info info)161 napi_value SysStopBLEScan(napi_env env, napi_callback_info info)
162 {
163     size_t argc = ARGS_SIZE_ONE;
164     napi_value argv[] = {nullptr};
165     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
166     if (argc != 1) {
167         return NapiGetNull(env);
168     }
169 
170     napi_valuetype valueType = napi_undefined;
171     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
172     if (valueType != napi_object) {
173         return NapiGetNull(env);
174     }
175 
176     std::unique_ptr<SysStopBLEContext> context = std::make_unique<SysStopBLEContext>();
177 
178     std::array<std::string, ARGS_SIZE_THREE> funcArray {"success", "fail", "complete"};
179     for (size_t i = 0; i < funcArray.size(); i++) {
180         napi_value value = GetPropertyValueByNamed(env, argv[PARAM0], funcArray[i], napi_function);
181         if (value) {
182             napi_create_reference(env, value, 1,
183                 &(i == PARAM0 ? context->callbackSuccess :
184                                 (i == PARAM1 ? context->callbackFail : context->callbackComplete)));
185         } else {
186             HILOGE("SysStopBLEScan Input parameter parsing failed!");
187             return NapiGetNull(env);
188         }
189     }
190 
191     napi_value resourceName = nullptr;
192     NAPI_CALL(env, napi_create_string_utf8(env, "SysStopBLEScan", NAPI_AUTO_LENGTH, &resourceName));
193     SysStopBLEContext *pContext = context.release();
194     napi_status status = napi_create_async_work(env, nullptr, resourceName, SysStopBLEScanExec,
195         SysStopBLEScanComplete, static_cast<void *>(pContext), &pContext->work);
196     if (status != napi_ok) {
197         delete pContext;
198         return NapiGetNull(env);
199     }
200 
201     if (napi_queue_async_work(env, pContext->work) != napi_ok) {
202         delete pContext;
203     }
204     return NapiGetNull(env);
205 }
206 
ParseDeviceFoundParameters(napi_env env,napi_value arg)207 bool ParseDeviceFoundParameters(napi_env env, napi_value arg)
208 {
209     std::array<std::string, ARGS_SIZE_TWO> funcArray {"success", "fail"};
210 
211     for (size_t i = 0; i < funcArray.size(); i++) {
212         napi_value value = GetPropertyValueByNamed(env, arg, funcArray[i], napi_function);
213         if (value) {
214             RegisterBLEObserver(env, value, i, REGISTER_SYS_BLE_FIND_DEVICE_TYPE);
215         } else {
216             UnregisterSysBLEObserver(REGISTER_SYS_BLE_FIND_DEVICE_TYPE);
217             return false;
218         }
219     }
220     return true;
221 }
222 
SysSubscribeBLEFound(napi_env env,napi_callback_info info)223 napi_value SysSubscribeBLEFound(napi_env env, napi_callback_info info)
224 {
225     size_t argc = ARGS_SIZE_ONE;
226     napi_value argv[] = {nullptr};
227     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
228     if (argc != 1) {
229         return NapiGetNull(env);
230     }
231 
232     napi_valuetype valueType = napi_undefined;
233     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valueType));
234     if (valueType != napi_object) {
235         return NapiGetNull(env);
236     }
237     if (!ParseDeviceFoundParameters(env, argv[PARAM0])) {
238         HILOGE("SysSubscribeBLEFound Input parameter parsing failed!");
239     }
240     return NapiGetNull(env);
241 }
242 
SysUnsubscribeBLEFound(napi_env env,napi_callback_info info)243 napi_value SysUnsubscribeBLEFound(napi_env env, napi_callback_info info)
244 {
245     UnregisterSysBLEObserver(REGISTER_SYS_BLE_FIND_DEVICE_TYPE);
246     return NapiGetNull(env);
247 }
248 } // namespace
249 
DefineSystemBLEInterface(napi_env env,napi_value exports)250 void DefineSystemBLEInterface(napi_env env, napi_value exports)
251 {
252     napi_property_descriptor desc[] = {
253         DECLARE_NAPI_FUNCTION("startBLEScan", SysStartBLEScan),
254         DECLARE_NAPI_FUNCTION("stopBLEScan", SysStopBLEScan),
255         DECLARE_NAPI_FUNCTION("subscribeBLEFound", SysSubscribeBLEFound),
256         DECLARE_NAPI_FUNCTION("unsubscribeBLEFound", SysUnsubscribeBLEFound),
257     };
258     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
259     HILOGI("DefineSystemBLEInterface init");
260 }
261 
On(napi_env env,napi_callback_info info)262 static napi_value On(napi_env env, napi_callback_info info)
263 {
264     HILOGI("enter");
265     auto CheckBleOnFunc = [env, info]() -> napi_status {
266         size_t argc = ARGS_SIZE_TWO;
267         napi_value argv[ARGS_SIZE_TWO] = {nullptr};
268         napi_value thisVar = nullptr;
269         NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
270         NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Requires 2 arguments", napi_invalid_arg);
271 
272         std::string type {};
273         NAPI_BT_CALL_RETURN(NapiParseString(env, argv[PARAM0], type));
274         if (type != REGISTER_BLE_FIND_DEVICE_TYPE) {
275             HILOGE("Invalid type: %{public}s", type.c_str());
276             return napi_invalid_arg;
277         }
278 
279         NAPI_BT_CALL_RETURN(NapiIsFunction(env, argv[PARAM1]));
280         auto napiScanCallback = std::make_shared<NapiCallback>(env, argv[PARAM1]);
281         NapiBluetoothBleCentralManagerCallback::GetInstance().SetNapiScanCallback(napiScanCallback);
282         return napi_ok;
283     };
284 
285     auto status = CheckBleOnFunc();
286     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
287     return NapiGetUndefinedRet(env);
288 }
289 
Off(napi_env env,napi_callback_info info)290 static napi_value Off(napi_env env, napi_callback_info info)
291 {
292     HILOGI("enter");
293     auto CheckBleOffFunc = [env, info]() -> napi_status {
294         size_t argc = ARGS_SIZE_TWO;
295         napi_value argv[ARGS_SIZE_TWO] = {nullptr};
296         napi_value thisVar = nullptr;
297         NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
298         NAPI_BT_RETURN_IF(
299             argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO, "Requires 1 or 2 arguments", napi_invalid_arg);
300 
301         std::string type {};
302         NAPI_BT_CALL_RETURN(NapiParseString(env, argv[PARAM0], type));
303         if (type != REGISTER_BLE_FIND_DEVICE_TYPE) {
304             HILOGE("Invalid type: %{public}s", type.c_str());
305             return napi_invalid_arg;
306         }
307         NapiBluetoothBleCentralManagerCallback::GetInstance().SetNapiScanCallback(nullptr);
308         return napi_ok;
309     };
310 
311     auto status = CheckBleOffFunc();
312     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
313     return NapiGetUndefinedRet(env);
314 }
315 
DefineBLEJSObject(napi_env env,napi_value exports)316 void DefineBLEJSObject(napi_env env, napi_value exports)
317 {
318     HILOGI("enter");
319     PropertyInit(env, exports);
320     napi_property_descriptor desc[] = {
321         DECLARE_NAPI_FUNCTION("createGattServer", NapiGattServer::CreateGattServer),
322         DECLARE_NAPI_FUNCTION("createGattClientDevice", NapiGattClient::CreateGattClientDevice),
323         DECLARE_NAPI_FUNCTION("startBLEScan", StartBLEScan),
324         DECLARE_NAPI_FUNCTION("stopBLEScan", StopBLEScan),
325         DECLARE_NAPI_FUNCTION("on", On),
326         DECLARE_NAPI_FUNCTION("off", Off),
327         DECLARE_NAPI_FUNCTION("getConnectedBLEDevices", GetConnectedBLEDevices),
328 #ifdef BLUETOOTH_API_SINCE_10
329         DECLARE_NAPI_FUNCTION("startAdvertising", StartAdvertising),
330         DECLARE_NAPI_FUNCTION("stopAdvertising", StopAdvertising),
331 #endif
332     };
333 
334 #ifdef BLUETOOTH_API_SINCE_10
335     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
336 #else
337     napi_value BLEObject = nullptr;
338     napi_create_object(env, &BLEObject);
339     napi_define_properties(env, BLEObject, sizeof(desc) / sizeof(desc[0]), desc);
340     napi_set_named_property(env, exports, "BLE", BLEObject);
341 #endif
342 }
343 
ConvertMatchMode(ScanOptions & params,int32_t matchMode)344 static void ConvertMatchMode(ScanOptions &params, int32_t matchMode)
345 {
346     switch (matchMode) {
347         case MatchMode::MATCH_MODE_AGGRESSIVE:
348             params.MatchMode = MatchMode::MATCH_MODE_AGGRESSIVE;
349             break;
350         case MatchMode::MATCH_MODE_STICKY:
351             params.MatchMode = MatchMode::MATCH_MODE_STICKY;
352             break;
353         default:
354             break;
355     }
356 }
357 
ConvertDutyMode(ScanOptions & params,int32_t dutyMode)358 static void ConvertDutyMode(ScanOptions &params, int32_t dutyMode)
359 {
360     switch (dutyMode) {
361         case static_cast<int32_t>(ScanDuty::SCAN_MODE_LOW_POWER):
362             params.dutyMode = ScanDuty::SCAN_MODE_LOW_POWER;
363             break;
364         case static_cast<int32_t>(ScanDuty::SCAN_MODE_BALANCED):
365             params.dutyMode = ScanDuty::SCAN_MODE_BALANCED;
366             break;
367         case static_cast<int32_t>(ScanDuty::SCAN_MODE_LOW_LATENCY):
368             params.dutyMode = ScanDuty::SCAN_MODE_LOW_LATENCY;
369             break;
370         default:
371             break;
372     }
373 }
374 
ParseScanParameters(const napi_env & env,const napi_callback_info & info,const napi_value & scanArg,ScanOptions & params)375 static napi_status ParseScanParameters(
376     const napi_env &env, const napi_callback_info &info, const napi_value &scanArg, ScanOptions &params)
377 {
378     (void)info;
379     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, scanArg, {"interval", "dutyMode", "matchMode"}));
380 
381     bool exist = false;
382     int32_t interval = 0;
383     NAPI_BT_CALL_RETURN(ParseInt32Params(env, scanArg, "interval", exist, interval));
384     if (exist) {
385         HILOGI("Scan interval is %{public}d", interval);
386         params.interval = interval;
387     }
388 
389     int32_t dutyMode = 0;
390     NAPI_BT_CALL_RETURN(ParseInt32Params(env, scanArg, "dutyMode", exist, dutyMode));
391     if (exist) {
392         HILOGI("Scan dutyMode is %{public}d", dutyMode);
393         ConvertDutyMode(params, dutyMode);
394     }
395 
396     int32_t matchMode = 0;
397     NAPI_BT_CALL_RETURN(ParseInt32Params(env, scanArg, "matchMode", exist, matchMode));
398     if (exist) {
399         HILOGI("Scan matchMode is %{public}d", matchMode);
400         ConvertMatchMode(params, matchMode);
401     }
402     return napi_ok;
403 }
404 
ParseScanFilterDeviceIdParameters(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)405 static napi_status ParseScanFilterDeviceIdParameters(
406     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
407 {
408     bool exist = false;
409     std::string deviceId {};
410     NAPI_BT_CALL_RETURN(ParseStringParams(env, scanFilter, "deviceId", exist, deviceId));
411     if (exist) {
412         if (!IsValidAddress(deviceId)) {
413             HILOGE("Invalid deviceId: %{public}s", deviceId.c_str());
414             return napi_invalid_arg;
415         }
416 
417         HILOGI("Scan filter device id is %{public}s", GetEncryptAddr(deviceId).c_str());
418         bleScanFilter.SetDeviceId(deviceId);
419     }
420     return napi_ok;
421 }
422 
ParseScanFilterLocalNameParameters(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)423 static napi_status ParseScanFilterLocalNameParameters(
424     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
425 {
426     bool exist = false;
427     std::string name {};
428     NAPI_BT_CALL_RETURN(ParseStringParams(env, scanFilter, "name", exist, name));
429     if (exist) {
430         if (name.empty()) {
431             HILOGE("name is empty");
432             return napi_invalid_arg;
433         }
434         HILOGI("Scan filter name is %{public}s", name.c_str());
435         bleScanFilter.SetName(name);
436     }
437     return napi_ok;
438 }
439 
ParseScanFilterServiceUuidParameters(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)440 static napi_status ParseScanFilterServiceUuidParameters(
441     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
442 {
443     bool exist = false;
444     UUID uuid {};
445     NAPI_BT_CALL_RETURN(ParseUuidParams(env, scanFilter, "serviceUuid", exist, uuid));
446     if (exist) {
447         HILOGI("Scan filter serviceUuid is %{public}s", uuid.ToString().c_str());
448         bleScanFilter.SetServiceUuid(uuid);
449     }
450 
451     UUID uuidMask {};
452     NAPI_BT_CALL_RETURN(ParseUuidParams(env, scanFilter, "serviceUuidMask", exist, uuidMask));
453     if (exist) {
454         HILOGI("Scan filter serviceUuidMask is %{public}s", uuidMask.ToString().c_str());
455         bleScanFilter.SetServiceUuidMask(uuidMask);
456     }
457     return napi_ok;
458 }
459 
ParseScanFilterSolicitationUuidParameters(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)460 static napi_status ParseScanFilterSolicitationUuidParameters(
461     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
462 {
463     bool exist = false;
464     UUID uuid {};
465     NAPI_BT_CALL_RETURN(ParseUuidParams(env, scanFilter, "serviceSolicitationUuid", exist, uuid));
466     if (exist) {
467         HILOGI("Scan filter serviceSolicitationUuid is %{public}s", uuid.ToString().c_str());
468         bleScanFilter.SetServiceSolicitationUuid(uuid);
469     }
470 
471     UUID uuidMask {};
472     NAPI_BT_CALL_RETURN(ParseUuidParams(env, scanFilter, "serviceSolicitationUuidMask", exist, uuidMask));
473     if (exist) {
474         HILOGI("Scan filter serviceSolicitationUuidMask is %{public}s", uuidMask.ToString().c_str());
475         bleScanFilter.SetServiceSolicitationUuidMask(uuidMask);
476     }
477     return napi_ok;
478 }
479 
ParseScanFilterServiceDataParameters(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)480 static napi_status ParseScanFilterServiceDataParameters(
481     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
482 {
483     bool exist = false;
484     std::vector<uint8_t> data {};
485     NAPI_BT_CALL_RETURN(ParseArrayBufferParams(env, scanFilter, "serviceData", exist, data));
486     if (exist) {
487         bleScanFilter.SetServiceData(std::move(data));
488     }
489 
490     std::vector<uint8_t> dataMask {};
491     NAPI_BT_CALL_RETURN(ParseArrayBufferParams(env, scanFilter, "serviceDataMask", exist, dataMask));
492     if (exist) {
493         bleScanFilter.SetServiceDataMask(std::move(dataMask));
494     }
495     return napi_ok;
496 }
497 
ParseScanFilterManufactureDataParameters(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)498 static napi_status ParseScanFilterManufactureDataParameters(
499     const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
500 {
501     bool exist = false;
502     napi_value result;
503     NAPI_BT_CALL_RETURN(ParseNumberParams(env, scanFilter, "manufactureId", exist, result));
504     if (exist) {
505         uint32_t manufacturerId = 0;
506         NAPI_BT_CALL_RETURN(napi_get_value_uint32(env, result, &manufacturerId));
507         bleScanFilter.SetManufacturerId(manufacturerId);
508         HILOGI("Scan filter manufacturerId is %{public}#x", manufacturerId);
509     }
510 
511     exist = false;
512     std::vector<uint8_t> data {};
513     NAPI_BT_CALL_RETURN(ParseArrayBufferParams(env, scanFilter, "manufactureData", exist, data));
514     if (exist) {
515         bleScanFilter.SetManufactureData(std::move(data));
516     }
517 
518     std::vector<uint8_t> dataMask {};
519     NAPI_BT_CALL_RETURN(ParseArrayBufferParams(env, scanFilter, "manufactureDataMask", exist, dataMask));
520     if (exist) {
521         bleScanFilter.SetManufactureDataMask(std::move(dataMask));
522     }
523     return napi_ok;
524 }
525 
ParseScanFilter(const napi_env & env,napi_value & scanFilter,BleScanFilter & bleScanFilter)526 static napi_status ParseScanFilter(const napi_env &env, napi_value &scanFilter, BleScanFilter &bleScanFilter)
527 {
528     HILOGI("enter");
529     std::vector<std::string> expectedNames {"deviceId", "name", "serviceUuid", "serviceUuidMask",
530         "serviceSolicitationUuid", "serviceSolicitationUuidMask", "serviceData", "serviceDataMask", "manufactureId",
531         "manufactureData", "manufactureDataMask"};
532     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, scanFilter, expectedNames));
533 
534     NAPI_BT_CALL_RETURN(ParseScanFilterDeviceIdParameters(env, scanFilter, bleScanFilter));
535     NAPI_BT_CALL_RETURN(ParseScanFilterLocalNameParameters(env, scanFilter, bleScanFilter));
536     NAPI_BT_CALL_RETURN(ParseScanFilterServiceUuidParameters(env, scanFilter, bleScanFilter));
537     NAPI_BT_CALL_RETURN(ParseScanFilterSolicitationUuidParameters(env, scanFilter, bleScanFilter));
538     NAPI_BT_CALL_RETURN(ParseScanFilterServiceDataParameters(env, scanFilter, bleScanFilter));
539     NAPI_BT_CALL_RETURN(ParseScanFilterManufactureDataParameters(env, scanFilter, bleScanFilter));
540     return napi_ok;
541 }
542 
ParseScanFilterParameters(const napi_env & env,napi_value & args,std::vector<BleScanFilter> & params)543 static napi_status ParseScanFilterParameters(const napi_env &env, napi_value &args, std::vector<BleScanFilter> &params)
544 {
545     HILOGI("enter");
546     NAPI_BT_CALL_RETURN(NapiIsArray(env, args));
547 
548     uint32_t length = 0;
549     NAPI_BT_CALL_RETURN(napi_get_array_length(env, args, &length));
550     NAPI_BT_RETURN_IF(length == 0, "Requires array length > 0", napi_invalid_arg);
551     for (uint32_t i = 0; i < length; i++) {
552         napi_value scanFilter;
553         NAPI_BT_CALL_RETURN(napi_get_element(env, args, i, &scanFilter));
554         NAPI_BT_CALL_RETURN(NapiIsObject(env, scanFilter));
555         BleScanFilter bleScanFilter;
556         NAPI_BT_CALL_RETURN(ParseScanFilter(env, scanFilter, bleScanFilter));
557         params.push_back(bleScanFilter);
558     }
559     return napi_ok;
560 }
561 
CheckBleScanParams(napi_env env,napi_callback_info info,std::vector<BleScanFilter> & outScanfilters,BleScanSettings & outSettinngs)562 static napi_status CheckBleScanParams(napi_env env, napi_callback_info info, std::vector<BleScanFilter> &outScanfilters,
563     BleScanSettings &outSettinngs)
564 {
565     size_t argc = ARGS_SIZE_TWO;
566     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
567     napi_value thisVar = nullptr;
568     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
569     NAPI_BT_RETURN_IF((argc == 0 || argc > ARGS_SIZE_TWO), "Requires 1 or 2 arguments.", napi_invalid_arg);
570 
571     std::vector<BleScanFilter> scanfilters;
572     // Support null param
573     napi_valuetype type = napi_undefined;
574     NAPI_BT_CALL_RETURN(napi_typeof(env, argv[PARAM0], &type));
575     if (type == napi_null) {
576         BleScanFilter emptyFilter;
577         scanfilters.push_back(emptyFilter);
578     } else {
579         NAPI_BT_CALL_RETURN(ParseScanFilterParameters(env, argv[PARAM0], scanfilters));
580     }
581 
582     if (argc == ARGS_SIZE_TWO) {
583         ScanOptions scanOptions;
584         NAPI_BT_CALL_RETURN(ParseScanParameters(env, info, argv[PARAM1], scanOptions));
585         outSettinngs.SetReportDelay(scanOptions.interval);
586         outSettinngs.SetScanMode(static_cast<int32_t>(scanOptions.dutyMode));
587     }
588 
589     outScanfilters = std::move(scanfilters);
590     return napi_ok;
591 }
592 
StartBLEScan(napi_env env,napi_callback_info info)593 napi_value StartBLEScan(napi_env env, napi_callback_info info)
594 {
595     HILOGI("enter");
596     std::vector<BleScanFilter> scanfilters;
597     BleScanSettings settinngs;
598     auto status = CheckBleScanParams(env, info, scanfilters, settinngs);
599     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
600 
601     int ret = BleCentralManagerGetInstance()->ConfigScanFilter(scanfilters);
602     NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == NO_ERROR, ret);
603     ret = BleCentralManagerGetInstance()->StartScan(settinngs);
604     NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == NO_ERROR, ret);
605 
606     return NapiGetUndefinedRet(env);
607 }
608 
StopBLEScan(napi_env env,napi_callback_info info)609 napi_value StopBLEScan(napi_env env, napi_callback_info info)
610 {
611     HILOGI("enter");
612     auto status = CheckEmptyParam(env, info);
613     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
614 
615     int ret = BleCentralManagerGetInstance()->StopScan();
616     NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == NO_ERROR, ret);
617     return NapiGetUndefinedRet(env);
618 }
619 
ParseAdvertisingSettingsParameters(const napi_env & env,const napi_callback_info & info,const napi_value & object,BleAdvertiserSettings & outSettings)620 static napi_status ParseAdvertisingSettingsParameters(
621     const napi_env &env, const napi_callback_info &info, const napi_value &object, BleAdvertiserSettings &outSettings)
622 {
623     HILOGI("enter");
624     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"interval", "txPower", "connectable"}));
625 
626     bool exist = false;
627     uint32_t interval = 0;
628     NAPI_BT_CALL_RETURN(NapiParseObjectUint32Optional(env, object, "interval", interval, exist));
629     if (exist) {
630         HILOGI("interval: %{public}u", interval);
631         outSettings.SetInterval(interval);
632     }
633 
634     int32_t txPower = 0;
635     NAPI_BT_CALL_RETURN(NapiParseObjectInt32Optional(env, object, "txPower", txPower, exist));
636     if (exist) {
637         const int32_t minTxPower = -127;
638         const int32_t maxTxPower = 1;
639         if (txPower < minTxPower || txPower > maxTxPower) {
640             HILOGE("Invalid tx power: %{public}d", txPower);
641             return napi_invalid_arg;
642         }
643         HILOGI("txPower is %{public}d", txPower);
644         outSettings.SetTxPower(txPower);
645     }
646 
647     bool connectable = false;
648     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(env, object, "connectable", connectable, exist));
649     if (exist) {
650         HILOGI("connectable: %{public}d", connectable);
651         outSettings.SetConnectable(connectable);
652     }
653     return napi_ok;
654 }
655 
ParseServiceUuidParameters(napi_env env,napi_value object,BleAdvertiserData & outData)656 static napi_status ParseServiceUuidParameters(napi_env env, napi_value object, BleAdvertiserData &outData)
657 {
658     HILOGI("enter");
659     std::vector<UUID> vec {};
660     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "serviceUuids", vec));
661     for (size_t i = 0; i < vec.size(); ++i) {
662         outData.AddServiceUuid(vec[i]);
663         HILOGI("Service Uuid = %{public}s", vec[i].ToString().c_str());
664     }
665     return napi_ok;
666 }
667 
ParseManufactureDataParameters(napi_env env,napi_value object,BleAdvertiserData & outData)668 static napi_status ParseManufactureDataParameters(napi_env env, napi_value object, BleAdvertiserData &outData)
669 {
670     HILOGI("enter");
671     std::vector<NapiAdvManufactureData> vec {};
672     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "manufactureData", vec));
673     for (size_t i = 0; i < vec.size(); ++i) {
674         outData.AddManufacturerData(vec[i].id, vec[i].value);
675     }
676     return napi_ok;
677 }
678 
ParseServiceDataParameters(napi_env env,napi_value object,BleAdvertiserData & outData)679 static napi_status ParseServiceDataParameters(napi_env env, napi_value object, BleAdvertiserData &outData)
680 {
681     HILOGI("enter");
682     std::vector<NapiAdvServiceData> vec {};
683     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "serviceData", vec));
684     for (size_t i = 0; i < vec.size(); ++i) {
685         outData.AddServiceData(
686             ParcelUuid::FromString(vec[i].uuid),
687             std::string(vec[i].value.begin(), vec[i].value.end()));
688     }
689     return napi_ok;
690 }
691 
ParseAdvertisDataParameters(const napi_env & env,const napi_callback_info & info,const napi_value & object,BleAdvertiserData & outData)692 static napi_status ParseAdvertisDataParameters(const napi_env &env, const napi_callback_info &info,
693     const napi_value &object, BleAdvertiserData &outData)
694 {
695     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(
696         env, object, {"serviceUuids", "manufactureData", "serviceData", "includeDeviceName"}));
697 
698     NAPI_BT_CALL_RETURN(ParseServiceUuidParameters(env, object, outData));
699     NAPI_BT_CALL_RETURN(ParseManufactureDataParameters(env, object, outData));
700     NAPI_BT_CALL_RETURN(ParseServiceDataParameters(env, object, outData));
701     bool exist = false;
702     bool includeDeviceName = false;
703     NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(env, object, "includeDeviceName", includeDeviceName, exist));
704     HILOGI("includeDeviceName: %{public}d", includeDeviceName);
705     outData.SetIncludeDeviceName(includeDeviceName);
706 
707     return napi_ok;
708 }
709 
CheckAdvertisingData(napi_env env,napi_callback_info info,BleAdvertiserSettings & outSettings,BleAdvertiserData & outAdvData,BleAdvertiserData & outRspData)710 napi_status CheckAdvertisingData(napi_env env, napi_callback_info info, BleAdvertiserSettings &outSettings,
711     BleAdvertiserData &outAdvData, BleAdvertiserData &outRspData)
712 {
713     size_t argc = ARGS_SIZE_THREE;
714     napi_value argv[ARGS_SIZE_THREE] = {nullptr};
715     napi_value thisVar = nullptr;
716     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
717     NAPI_BT_RETURN_IF((argc != ARGS_SIZE_TWO && argc != ARGS_SIZE_THREE), "need 2 or 3 arguments.", napi_invalid_arg);
718 
719     BleAdvertiserSettings settings;
720     NAPI_BT_CALL_RETURN(ParseAdvertisingSettingsParameters(env, info, argv[PARAM0], settings));
721     BleAdvertiserData advData;
722     NAPI_BT_CALL_RETURN(ParseAdvertisDataParameters(env, info, argv[PARAM1], advData));
723     BleAdvertiserData rspData;
724     if (argc == ARGS_SIZE_THREE) {
725         NAPI_BT_CALL_RETURN(ParseAdvertisDataParameters(env, info, argv[PARAM2], rspData));
726     }
727 
728     outSettings = std::move(settings);
729     outAdvData = std::move(advData);
730     outRspData = std::move(rspData);
731     return napi_ok;
732 }
733 
StartAdvertising(napi_env env,napi_callback_info info)734 napi_value StartAdvertising(napi_env env, napi_callback_info info)
735 {
736     HILOGI("enter");
737     BleAdvertiserSettings settings;
738     BleAdvertiserData advData;
739     BleAdvertiserData rspData;
740     auto status = CheckAdvertisingData(env, info, settings, advData, rspData);
741     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
742 
743     int ret = BleAdvertiserGetInstance()->StartAdvertising(
744         settings, advData, rspData, NapiBluetoothBleAdvertiseCallback::GetInstance());
745     NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == BT_NO_ERROR, ret);
746     return NapiGetUndefinedRet(env);
747 }
748 
CheckEmptyArgs(napi_env env,napi_callback_info info)749 static napi_status CheckEmptyArgs(napi_env env, napi_callback_info info)
750 {
751     size_t argc = 0;
752     napi_value thisVar = nullptr;
753     NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, nullptr, &thisVar, NULL));
754     NAPI_BT_RETURN_IF(argc > 0, "no needed arguments.", napi_invalid_arg);
755     return napi_ok;
756 }
757 
StopAdvertising(napi_env env,napi_callback_info info)758 napi_value StopAdvertising(napi_env env, napi_callback_info info)
759 {
760     HILOGI("enter");
761     auto status = CheckEmptyArgs(env, info);
762     NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
763 
764     int ret = BleAdvertiserGetInstance()->StopAdvertising(NapiBluetoothBleAdvertiseCallback::GetInstance());
765     NAPI_BT_ASSERT_RETURN_UNDEF(env, ret == BT_NO_ERROR, ret);
766     return NapiGetUndefinedRet(env);
767 }
768 
GetConnectedBLEDevices(napi_env env,napi_callback_info info)769 napi_value GetConnectedBLEDevices(napi_env env, napi_callback_info info)
770 {
771     HILOGI("enter");
772     napi_value result = nullptr;
773     napi_create_array(env, &result);
774 
775     auto status = ConvertStringVectorToJS(env, result, NapiGattServer::deviceList);
776     NAPI_BT_ASSERT_RETURN(env, status == napi_ok, BT_ERR_INTERNAL_ERROR, result);
777     return result;
778 }
779 
PropertyInit(napi_env env,napi_value exports)780 napi_value PropertyInit(napi_env env, napi_value exports)
781 {
782     HILOGI("enter");
783 
784     napi_value matchModeObj = nullptr;
785     napi_value scanDutyObj = nullptr;
786     napi_create_object(env, &matchModeObj);
787     napi_create_object(env, &scanDutyObj);
788 
789     SetNamedPropertyByInteger(env, matchModeObj, MatchMode::MATCH_MODE_STICKY, "MATCH_MODE_STICKY");
790     SetNamedPropertyByInteger(env, matchModeObj, MatchMode::MATCH_MODE_AGGRESSIVE, "MATCH_MODE_AGGRESSIVE");
791     SetNamedPropertyByInteger(
792         env, scanDutyObj, static_cast<int32_t>(ScanDuty::SCAN_MODE_BALANCED), "SCAN_MODE_BALANCED");
793     SetNamedPropertyByInteger(
794         env, scanDutyObj, static_cast<int32_t>(ScanDuty::SCAN_MODE_LOW_LATENCY), "SCAN_MODE_LOW_LATENCY");
795     SetNamedPropertyByInteger(
796         env, scanDutyObj, static_cast<int32_t>(ScanDuty::SCAN_MODE_LOW_POWER), "SCAN_MODE_LOW_POWER");
797 
798 #ifdef BLUETOOTH_API_SINCE_10
799     napi_value gattWriteTypeObj = nullptr;
800     napi_create_object(env, &gattWriteTypeObj);
801     SetNamedPropertyByInteger(env, gattWriteTypeObj, static_cast<int32_t>(NapiGattWriteType::WRITE), "WRITE");
802     SetNamedPropertyByInteger(
803         env, gattWriteTypeObj, static_cast<int32_t>(NapiGattWriteType::WRITE_NO_RESPONSE), "WRITE_NO_RESPONSE");
804 #endif
805 
806     napi_property_descriptor exportFuncs[] = {
807         DECLARE_NAPI_PROPERTY("MatchMode", matchModeObj),
808         DECLARE_NAPI_PROPERTY("ScanDuty", scanDutyObj),
809 #ifdef BLUETOOTH_API_SINCE_10
810         DECLARE_NAPI_PROPERTY("GattWriteType", gattWriteTypeObj),
811 #endif
812     };
813 
814     napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs);
815 
816     return exports;
817 }
818 }  // namespace Bluetooth
819 }  // namespace OHOS
820