1 /*
2 * Copyright (C) 2025 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 #ifndef LOG_TAG
16 #define LOG_TAG "bt_napi_ble_scanner"
17 #endif
18
19 #include "napi_bluetooth_ble_scanner.h"
20 #include "bluetooth_log.h"
21 #include "bluetooth_errorcode.h"
22 #include "napi_bluetooth_utils.h"
23 #include "napi_bluetooth_error.h"
24
25 namespace OHOS {
26 namespace Bluetooth {
27
28 thread_local napi_ref NapiBleScanner::consRef_ = nullptr;
29
DefineBleScannerJSClass(napi_env env)30 void NapiBleScanner::DefineBleScannerJSClass(napi_env env)
31 {
32 napi_property_descriptor properties[] = {
33 DECLARE_NAPI_FUNCTION("startScan", StartScan),
34 DECLARE_NAPI_FUNCTION("stopScan", StopScan),
35 DECLARE_NAPI_FUNCTION("on", On),
36 DECLARE_NAPI_FUNCTION("off", Off),
37 };
38
39 napi_value constructor = nullptr;
40 napi_define_class(env, "BleScanner", NAPI_AUTO_LENGTH, BleScannerConstructor, nullptr,
41 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
42 napi_create_reference(env, constructor, 1, &consRef_);
43 }
44
BleScannerConstructor(napi_env env,napi_callback_info info)45 napi_value NapiBleScanner::BleScannerConstructor(napi_env env, napi_callback_info info)
46 {
47 napi_value thisVar = nullptr;
48 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
49 NapiBleScanner* bleScanner = new NapiBleScanner();
50
51 auto status = napi_wrap(
52 env, thisVar, bleScanner,
53 [](napi_env env, void* data, void* hint) {
54 NapiBleScanner* scanner = static_cast<NapiBleScanner*>(data);
55 if (scanner) {
56 delete scanner;
57 scanner = nullptr;
58 }
59 },
60 nullptr,
61 nullptr);
62 if (status != napi_ok) {
63 HILOGE("napi_wrap failed");
64 delete bleScanner;
65 bleScanner = nullptr;
66 }
67
68 return thisVar;
69 }
70
CreateBleScanner(napi_env env,napi_callback_info info)71 napi_value NapiBleScanner::CreateBleScanner(napi_env env, napi_callback_info info)
72 {
73 HILOGI("enter");
74 napi_value result;
75 napi_value constructor = nullptr;
76 napi_get_reference_value(env, consRef_, &constructor);
77 napi_new_instance(env, constructor, 0, nullptr, &result);
78 return result;
79 }
80
NapiGetBleScanner(napi_env env,napi_callback_info info)81 static NapiBleScanner *NapiGetBleScanner(napi_env env, napi_callback_info info)
82 {
83 size_t argc = 0;
84 napi_value thisVar = nullptr;
85 if (napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr) != napi_ok) {
86 return nullptr;
87 }
88
89 NapiBleScanner *bleScanner = nullptr;
90 auto status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&bleScanner));
91 if (status != napi_ok) {
92 return nullptr;
93 }
94 return bleScanner;
95 }
96
StartScan(napi_env env,napi_callback_info info)97 napi_value NapiBleScanner::StartScan(napi_env env, napi_callback_info info)
98 {
99 HILOGI("enter");
100 std::vector<BleScanFilter> scanFilters;
101 BleScanSettings settings;
102 auto status = CheckBleScanParams(env, info, scanFilters, settings);
103 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
104
105 NapiBleScanner *napiBleScanner = NapiGetBleScanner(env, info);
106 NAPI_BT_ASSERT_RETURN_UNDEF(env, napiBleScanner != nullptr, BT_ERR_INVALID_PARAM);
107 NAPI_BT_ASSERT_RETURN_UNDEF(env, napiBleScanner->GetBleCentralManager() != nullptr, BT_ERR_INVALID_PARAM);
108 NAPI_BT_ASSERT_RETURN_UNDEF(env, napiBleScanner->GetCallback() != nullptr, BT_ERR_INVALID_PARAM);
109
110 auto func = [napiBleScanner, settings, scanFilters]() {
111 napiBleScanner->GetBleCentralManager()->SetNewApiFlag();
112 int ret = napiBleScanner->GetBleCentralManager()->StartScan(settings, scanFilters);
113 return NapiAsyncWorkRet(ret);
114 };
115
116 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK);
117 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
118 bool success =
119 napiBleScanner->GetCallback()->asyncWorkMap_.TryPush(NapiAsyncType::BLE_START_SCAN, asyncWork);
120 NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
121
122 asyncWork->Run();
123 return asyncWork->GetRet();
124 }
125
StopScan(napi_env env,napi_callback_info info)126 napi_value NapiBleScanner::StopScan(napi_env env, napi_callback_info info)
127 {
128 HILOGI("enter");
129 auto status = CheckEmptyParam(env, info);
130 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
131
132 NapiBleScanner *napiBleScanner = NapiGetBleScanner(env, info);
133 NAPI_BT_ASSERT_RETURN_UNDEF(env, napiBleScanner != nullptr, BT_ERR_INVALID_PARAM);
134 NAPI_BT_ASSERT_RETURN_UNDEF(env, napiBleScanner->GetBleCentralManager() != nullptr, BT_ERR_INVALID_PARAM);
135 NAPI_BT_ASSERT_RETURN_UNDEF(env, napiBleScanner->GetCallback() != nullptr, BT_ERR_INVALID_PARAM);
136
137 auto func = [napiBleScanner]() {
138 int ret = napiBleScanner->GetBleCentralManager()->StopScan();
139 return NapiAsyncWorkRet(ret);
140 };
141
142 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK);
143 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
144 bool success =
145 napiBleScanner->GetCallback()->asyncWorkMap_.TryPush(NapiAsyncType::BLE_STOP_SCAN, asyncWork);
146 NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
147
148 asyncWork->Run();
149 return asyncWork->GetRet();
150 }
151
On(napi_env env,napi_callback_info info)152 napi_value NapiBleScanner::On(napi_env env, napi_callback_info info)
153 {
154 NapiBleScanner *napiBleScanner = NapiGetBleScanner(env, info);
155 if (napiBleScanner && napiBleScanner->GetCallback()) {
156 auto status = napiBleScanner->GetCallback()->eventSubscribe_.Register(env, info);
157 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
158 }
159 return NapiGetUndefinedRet(env);
160 }
161
Off(napi_env env,napi_callback_info info)162 napi_value NapiBleScanner::Off(napi_env env, napi_callback_info info)
163 {
164 NapiBleScanner *napiBleScanner = NapiGetBleScanner(env, info);
165 if (napiBleScanner && napiBleScanner->GetCallback()) {
166 auto status = napiBleScanner->GetCallback()->eventSubscribe_.Deregister(env, info);
167 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
168 }
169 return NapiGetUndefinedRet(env);
170 }
171 } // namespace Bluetooth
172 } // namespace OHOS