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, ¶Type));
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 ¶ms, 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 ¶ms, 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 ¶ms)
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> ¶ms)
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