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