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 #ifndef LOG_TAG
16 #define LOG_TAG "bt_napi_gatt_client"
17 #endif
18
19 #include "napi_bluetooth_gatt_client.h"
20 #include <unistd.h>
21 #include "bluetooth_errorcode.h"
22 #include "bluetooth_host.h"
23 #include "bluetooth_log.h"
24 #include "napi_async_callback.h"
25 #include "napi_bluetooth_ble_utils.h"
26 #include "napi_bluetooth_error.h"
27 #include "napi_bluetooth_event.h"
28 #include "napi_bluetooth_host.h"
29 #include "napi_bluetooth_utils.h"
30 #include "napi_event_subscribe_module.h"
31 #include "../parser/napi_parser_utils.h"
32
33
34 namespace OHOS {
35 namespace Bluetooth {
36 using namespace std;
37
38 thread_local napi_ref NapiGattClient::consRef_ = nullptr;
39
CheckCreateGattClientDeviceParams(napi_env env,napi_callback_info info,napi_value & outResult)40 static napi_status CheckCreateGattClientDeviceParams(napi_env env, napi_callback_info info, napi_value &outResult)
41 {
42 size_t expectedArgsCount = ARGS_SIZE_ONE;
43 size_t argc = expectedArgsCount;
44 napi_value argv[ARGS_SIZE_ONE] = {0};
45
46 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
47 NAPI_BT_RETURN_IF(argc != expectedArgsCount, "expect 1 args", napi_invalid_arg);
48
49 std::string deviceId {};
50 if (!ParseString(env, deviceId, argv[0])) {
51 HILOGE("expect string");
52 return napi_string_expected;
53 }
54 if (!IsValidAddress(deviceId)) {
55 HILOGE("Invalid deviceId: %{public}s", deviceId.c_str());
56 return napi_invalid_arg;
57 }
58
59 napi_value constructor = nullptr;
60 NAPI_BT_CALL_RETURN(napi_get_reference_value(env, NapiGattClient::consRef_, &constructor));
61 NAPI_BT_CALL_RETURN(napi_new_instance(env, constructor, argc, argv, &outResult));
62 return napi_ok;
63 }
64
CreateGattClientDevice(napi_env env,napi_callback_info info)65 napi_value NapiGattClient::CreateGattClientDevice(napi_env env, napi_callback_info info)
66 {
67 HILOGI("enter");
68 napi_value result;
69 auto status = CheckCreateGattClientDeviceParams(env, info, result);
70 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
71 return result;
72 }
73
DefineGattClientJSClass(napi_env env)74 void NapiGattClient::DefineGattClientJSClass(napi_env env)
75 {
76 napi_property_descriptor properties[] = {
77 DECLARE_NAPI_FUNCTION("connect", Connect),
78 DECLARE_NAPI_FUNCTION("disconnect", Disconnect),
79 DECLARE_NAPI_FUNCTION("close", Close),
80 DECLARE_NAPI_FUNCTION("getDeviceName", GetDeviceName),
81 DECLARE_NAPI_FUNCTION("getServices", GetServices),
82 DECLARE_NAPI_FUNCTION("readCharacteristicValue", ReadCharacteristicValue),
83 DECLARE_NAPI_FUNCTION("readDescriptorValue", ReadDescriptorValue),
84 DECLARE_NAPI_FUNCTION("getRssiValue", GetRssiValue),
85 DECLARE_NAPI_FUNCTION("setBLEMtuSize", SetBLEMtuSize),
86 DECLARE_NAPI_FUNCTION("on", On),
87 DECLARE_NAPI_FUNCTION("off", Off),
88 #ifdef BLUETOOTH_API_SINCE_10
89 DECLARE_NAPI_FUNCTION("writeCharacteristicValue", WriteCharacteristicValueEx),
90 DECLARE_NAPI_FUNCTION("writeDescriptorValue", WriteDescriptorValueEx),
91 DECLARE_NAPI_FUNCTION("setCharacteristicChangeNotification", setCharacteristicChangeNotification),
92 DECLARE_NAPI_FUNCTION("setCharacteristicChangeIndication", setCharacteristicChangeIndication),
93 #else
94 DECLARE_NAPI_FUNCTION("writeCharacteristicValue", WriteCharacteristicValue),
95 DECLARE_NAPI_FUNCTION("writeDescriptorValue", WriteDescriptorValue),
96 DECLARE_NAPI_FUNCTION("setNotifyCharacteristicChanged", SetNotifyCharacteristicChanged),
97 #endif
98 };
99
100 napi_value constructor = nullptr;
101 napi_define_class(env, "GattClientDevice", NAPI_AUTO_LENGTH, GattClientConstructor, nullptr,
102 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
103 napi_create_reference(env, constructor, 1, &consRef_);
104 }
105
GattClientConstructor(napi_env env,napi_callback_info info)106 napi_value NapiGattClient::GattClientConstructor(napi_env env, napi_callback_info info)
107 {
108 HILOGI("enter");
109 napi_value thisVar = nullptr;
110
111 size_t expectedArgsCount = ARGS_SIZE_ONE;
112 size_t argc = expectedArgsCount;
113 napi_value argv[ARGS_SIZE_ONE] = {0};
114
115 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
116
117 string deviceId;
118 ParseString(env, deviceId, argv[PARAM0]);
119 SetGattClientDeviceId(deviceId);
120
121 NapiGattClient *gattClient = new NapiGattClient(deviceId);
122
123 auto status = napi_wrap(
124 env, thisVar, gattClient,
125 [](napi_env env, void* data, void* hint) {
126 NapiGattClient* client = static_cast<NapiGattClient*>(data);
127 if (client) {
128 delete client;
129 client = nullptr;
130 }
131 },
132 nullptr,
133 nullptr);
134 if (status != napi_ok) {
135 HILOGE("napi_wrap failed");
136 delete gattClient;
137 gattClient = nullptr;
138 }
139
140 return thisVar;
141 }
142
NapiGetGattClient(napi_env env,napi_value thisVar)143 static NapiGattClient *NapiGetGattClient(napi_env env, napi_value thisVar)
144 {
145 NapiGattClient *gattClient = nullptr;
146 auto status = napi_unwrap(env, thisVar, (void **)&gattClient);
147 if (status != napi_ok) {
148 return nullptr;
149 }
150 return gattClient;
151 }
152
NapiGetGattClient(napi_env env,napi_callback_info info)153 static NapiGattClient *NapiGetGattClient(napi_env env, napi_callback_info info)
154 {
155 size_t argc = 0;
156 napi_value thisVar = nullptr;
157 if (napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr) != napi_ok) {
158 return nullptr;
159 }
160 return NapiGetGattClient(env, thisVar);
161 }
162
GetCharacteristic(const std::shared_ptr<GattClient> & client,const UUID & serviceUuid,const UUID & characterUuid)163 static GattCharacteristic *GetCharacteristic(const std::shared_ptr<GattClient> &client,
164 const UUID &serviceUuid, const UUID &characterUuid)
165 {
166 GattCharacteristic *character = nullptr;
167 if (client) {
168 auto service = client->GetService(serviceUuid);
169 if (service.has_value()) {
170 character = service->get().GetCharacteristic(characterUuid);
171 }
172 }
173 return character;
174 }
175
FindCharacteristic(std::vector<GattService> & service,const NapiBleCharacteristic & napiCharacter)176 static GattCharacteristic *FindCharacteristic(std::vector<GattService> &service,
177 const NapiBleCharacteristic &napiCharacter)
178 {
179 GattCharacteristic *character = nullptr;
180 for (auto &svc : service) {
181 if (svc.GetUuid().Equals(napiCharacter.serviceUuid)) {
182 character = svc.GetCharacteristic(napiCharacter.characteristicValueHandle);
183 if (character && character->GetUuid().Equals(napiCharacter.characteristicUuid)) {
184 return character;
185 }
186 }
187 }
188 return nullptr;
189 }
190
GetCharacteristic(const std::shared_ptr<GattClient> & client,const NapiBleCharacteristic & napiCharacter)191 static GattCharacteristic *GetCharacteristic(const std::shared_ptr<GattClient> &client,
192 const NapiBleCharacteristic &napiCharacter)
193 {
194 if (client) {
195 if (napiCharacter.characteristicValueHandle > 0) {
196 std::vector<GattService> &services = client->GetService();
197 return FindCharacteristic(services, napiCharacter);
198 } else {
199 GattCharacteristic *character = GetCharacteristic(client, napiCharacter.serviceUuid,
200 napiCharacter.characteristicUuid);
201 return character;
202 }
203 }
204 return nullptr;
205 }
206
GetGattcCharacteristic(const std::shared_ptr<GattClient> & client,const NapiBleCharacteristic & napiCharacter)207 static GattCharacteristic *GetGattcCharacteristic(const std::shared_ptr<GattClient> &client,
208 const NapiBleCharacteristic &napiCharacter)
209 {
210 GattCharacteristic *character = GetCharacteristic(client, napiCharacter);
211 if (character) {
212 character->SetValue(napiCharacter.characteristicValue.data(), napiCharacter.characteristicValue.size());
213 }
214 return character;
215 }
216
GetGattcDescriptor(const std::shared_ptr<GattClient> & client,const NapiBleDescriptor & napiDescriptor)217 static GattDescriptor *GetGattcDescriptor(const std::shared_ptr<GattClient> &client,
218 const NapiBleDescriptor &napiDescriptor)
219 {
220 GattDescriptor *descriptor = nullptr;
221 if (client) {
222 auto *character = GetCharacteristic(client, napiDescriptor.serviceUuid, napiDescriptor.characteristicUuid);
223 if (character == nullptr) {
224 HILOGE("character is nullptr");
225 return nullptr;
226 }
227 descriptor = character->GetDescriptor(napiDescriptor.descriptorUuid);
228 if (descriptor) {
229 descriptor->SetValue(napiDescriptor.descriptorValue.data(), napiDescriptor.descriptorValue.size());
230 }
231 }
232 return descriptor;
233 }
234
On(napi_env env,napi_callback_info info)235 napi_value NapiGattClient::On(napi_env env, napi_callback_info info)
236 {
237 NapiGattClient *napiGattClient = NapiGetGattClient(env, info);
238 if (napiGattClient && napiGattClient->GetCallback()) {
239 auto status = napiGattClient->GetCallback()->eventSubscribe_.Register(env, info);
240 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
241 }
242 return NapiGetUndefinedRet(env);
243 }
244
Off(napi_env env,napi_callback_info info)245 napi_value NapiGattClient::Off(napi_env env, napi_callback_info info)
246 {
247 NapiGattClient *napiGattClient = NapiGetGattClient(env, info);
248 if (napiGattClient && napiGattClient->GetCallback()) {
249 auto status = napiGattClient->GetCallback()->eventSubscribe_.Deregister(env, info);
250 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
251 }
252 return NapiGetUndefinedRet(env);
253 }
254
CheckGattClientNoArgc(napi_env env,napi_callback_info info,NapiGattClient ** outGattClient)255 static napi_status CheckGattClientNoArgc(napi_env env, napi_callback_info info, NapiGattClient **outGattClient)
256 {
257 size_t argc = 0;
258 napi_value thisVar = nullptr;
259 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr));
260 NAPI_BT_RETURN_IF(argc != 0, "No need arguments.", napi_invalid_arg);
261 NapiGattClient *gattClient = NapiGetGattClient(env, thisVar);
262 NAPI_BT_RETURN_IF(gattClient == nullptr || outGattClient == nullptr, "gattClient is nullptr.", napi_invalid_arg);
263
264 *outGattClient = gattClient;
265 return napi_ok;
266 }
267
Connect(napi_env env,napi_callback_info info)268 napi_value NapiGattClient::Connect(napi_env env, napi_callback_info info)
269 {
270 HILOGI("enter");
271 NapiGattClient *gattClient = nullptr;
272 auto status = CheckGattClientNoArgc(env, info, &gattClient);
273 NAPI_BT_ASSERT_RETURN_FALSE(env, status == napi_ok, BT_ERR_INVALID_PARAM);
274 NAPI_BT_ASSERT_RETURN_UNDEF(env, gattClient->GetCallback() != nullptr, BT_ERR_INTERNAL_ERROR);
275
276 std::shared_ptr<GattClient> client = gattClient->GetClient();
277 NAPI_BT_ASSERT_RETURN_FALSE(env, client != nullptr, BT_ERR_INTERNAL_ERROR);
278
279 int ret = client->Connect(gattClient->GetCallback(), false, GATT_TRANSPORT_TYPE_LE);
280 HILOGI("ret: %{public}d", ret);
281 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
282 return NapiGetBooleanTrue(env);
283 }
284
Disconnect(napi_env env,napi_callback_info info)285 napi_value NapiGattClient::Disconnect(napi_env env, napi_callback_info info)
286 {
287 HILOGI("enter");
288 NapiGattClient* gattClient = nullptr;
289 auto status = CheckGattClientNoArgc(env, info, &gattClient);
290 NAPI_BT_ASSERT_RETURN_FALSE(env, status == napi_ok, BT_ERR_INVALID_PARAM);
291
292 std::shared_ptr<GattClient> client = gattClient->GetClient();
293 NAPI_BT_ASSERT_RETURN_FALSE(env, client != nullptr, BT_ERR_INTERNAL_ERROR);
294
295 int ret = client->Disconnect();
296 HILOGI("ret: %{public}d", ret);
297 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
298 return NapiGetBooleanTrue(env);
299 }
300
ParseGattClientReadCharacteristicValue(napi_env env,napi_callback_info info,NapiGattClient ** outGattClient,GattCharacteristic ** outCharacter)301 static napi_status ParseGattClientReadCharacteristicValue(napi_env env, napi_callback_info info,
302 NapiGattClient **outGattClient, GattCharacteristic **outCharacter)
303 {
304 size_t expectedArgsCount = ARGS_SIZE_TWO;
305 size_t argc = expectedArgsCount;
306 napi_value argv[ARGS_SIZE_TWO] = {0};
307 napi_value thisVar = nullptr;
308 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
309 NAPI_BT_RETURN_IF(argc != expectedArgsCount && argc != expectedArgsCount - CALLBACK_SIZE,
310 "Requires 1 or 2 arguments.", napi_invalid_arg);
311 NapiGattClient *gattClient = NapiGetGattClient(env, thisVar);
312 NAPI_BT_RETURN_IF(gattClient == nullptr || outGattClient == nullptr, "gattClient is nullptr.", napi_invalid_arg);
313
314 NapiBleCharacteristic napiCharacter;
315 NAPI_BT_CALL_RETURN(NapiParseGattCharacteristic(env, argv[PARAM0], napiCharacter));
316 GattCharacteristic *character = GetGattcCharacteristic(gattClient->GetClient(), napiCharacter);
317 NAPI_BT_RETURN_IF(character == nullptr || outCharacter == nullptr, "Not found character", napi_invalid_arg);
318
319 *outGattClient = gattClient;
320 *outCharacter = character;
321 return napi_ok;
322 }
323
ReadCharacteristicValue(napi_env env,napi_callback_info info)324 napi_value NapiGattClient::ReadCharacteristicValue(napi_env env, napi_callback_info info)
325 {
326 HILOGI("enter");
327 NapiGattClient *client = nullptr;
328 GattCharacteristic *character = nullptr;
329 auto status = ParseGattClientReadCharacteristicValue(env, info, &client, &character);
330 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok && client && character, BT_ERR_INVALID_PARAM);
331 NAPI_BT_ASSERT_RETURN_UNDEF(env, client->GetCallback() != nullptr, BT_ERR_INTERNAL_ERROR);
332
333 auto func = [gattClient = client->GetClient(), character]() {
334 if (character == nullptr) {
335 HILOGE("character is nullptr");
336 return NapiAsyncWorkRet(BT_ERR_INTERNAL_ERROR);
337 }
338 int ret = BT_ERR_INTERNAL_ERROR;
339 if (gattClient) {
340 ret = gattClient->ReadCharacteristic(*character);
341 }
342 return NapiAsyncWorkRet(ret);
343 };
344 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK);
345 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
346 bool success = client->GetCallback()->asyncWorkMap_.TryPush(NapiAsyncType::GATT_CLIENT_READ_CHARACTER, asyncWork);
347 NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
348
349 asyncWork->Run();
350 return asyncWork->GetRet();
351 }
352
ParseGattClientReadDescriptorValue(napi_env env,napi_callback_info info,NapiGattClient ** outGattClient,GattDescriptor ** outDescriptor)353 static napi_status ParseGattClientReadDescriptorValue(napi_env env, napi_callback_info info,
354 NapiGattClient **outGattClient, GattDescriptor **outDescriptor)
355 {
356 size_t expectedArgsCount = ARGS_SIZE_TWO;
357 size_t argc = expectedArgsCount;
358 napi_value argv[ARGS_SIZE_TWO] = {0};
359 napi_value thisVar = nullptr;
360 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
361 NAPI_BT_RETURN_IF(argc != expectedArgsCount && argc != expectedArgsCount - CALLBACK_SIZE,
362 "Requires 1 or 2 arguments.", napi_invalid_arg);
363
364 NapiGattClient *gattClient = NapiGetGattClient(env, thisVar);
365 NAPI_BT_RETURN_IF(outGattClient == nullptr || gattClient == nullptr, "gattClient is nullptr.", napi_invalid_arg);
366
367 NapiBleDescriptor napiDescriptor;
368 NAPI_BT_CALL_RETURN(NapiParseGattDescriptor(env, argv[PARAM0], napiDescriptor));
369 GattDescriptor *descriptor = GetGattcDescriptor(gattClient->GetClient(), napiDescriptor);
370 NAPI_BT_RETURN_IF(outDescriptor == nullptr || descriptor == nullptr, "Not found Descriptor", napi_invalid_arg);
371
372 *outGattClient = gattClient;
373 *outDescriptor = descriptor;
374 return napi_ok;
375 }
376
ReadDescriptorValue(napi_env env,napi_callback_info info)377 napi_value NapiGattClient::ReadDescriptorValue(napi_env env, napi_callback_info info)
378 {
379 HILOGI("enter");
380 NapiGattClient *client = nullptr;
381 GattDescriptor *descriptor = nullptr;
382 auto status = ParseGattClientReadDescriptorValue(env, info, &client, &descriptor);
383 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok && client && descriptor, BT_ERR_INVALID_PARAM);
384 NAPI_BT_ASSERT_RETURN_UNDEF(env, client->GetCallback() != nullptr, BT_ERR_INTERNAL_ERROR);
385
386 auto func = [gattClient = client->GetClient(), descriptor]() {
387 if (descriptor == nullptr) {
388 HILOGE("descriptor is nullptr");
389 return NapiAsyncWorkRet(BT_ERR_INTERNAL_ERROR);
390 }
391 int ret = BT_ERR_INTERNAL_ERROR;
392 if (gattClient) {
393 ret = gattClient->ReadDescriptor(*descriptor);
394 }
395 return NapiAsyncWorkRet(ret);
396 };
397 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK);
398 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
399 bool success = client->GetCallback()->asyncWorkMap_.TryPush(NapiAsyncType::GATT_CLIENT_READ_DESCRIPTOR, asyncWork);
400 NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
401
402 asyncWork->Run();
403 return asyncWork->GetRet();
404 }
405
ParseGattClientGetServices(napi_env env,napi_callback_info info,NapiGattClient ** outGattClient)406 static napi_status ParseGattClientGetServices(napi_env env, napi_callback_info info, NapiGattClient **outGattClient)
407 {
408 size_t argc = ARGS_SIZE_ONE;
409 napi_value argv[ARGS_SIZE_ONE] = {nullptr};
410 napi_value thisVar = nullptr;
411 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
412 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ZERO && argc != ARGS_SIZE_ONE, "Requires 0 or 1 arguments.", napi_invalid_arg);
413 NapiGattClient *gattClient = NapiGetGattClient(env, thisVar);
414 NAPI_BT_RETURN_IF(gattClient == nullptr || outGattClient == nullptr, "gattClient is nullptr.", napi_invalid_arg);
415
416 *outGattClient = gattClient;
417 return napi_ok;
418 }
419
GetServices(napi_env env,napi_callback_info info)420 napi_value NapiGattClient::GetServices(napi_env env, napi_callback_info info)
421 {
422 HILOGI("enter");
423 NapiGattClient *client = nullptr;
424 auto status = ParseGattClientGetServices(env, info, &client);
425 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok && client, BT_ERR_INVALID_PARAM);
426
427 auto func = [gattClient = client->GetClient()]() {
428 if (gattClient == nullptr) {
429 return NapiAsyncWorkRet(BT_ERR_INTERNAL_ERROR);
430 }
431
432 HILOGI("start discover services");
433 std::shared_ptr<NapiNativeObject> object {nullptr};
434 int ret = gattClient->DiscoverServices();
435 if (ret == BT_NO_ERROR) {
436 HILOGI("start get services");
437 object = std::make_shared<NapiNativeGattServiceArray>(gattClient->GetService());
438 }
439 return NapiAsyncWorkRet(ret, object);
440 };
441
442 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
443 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
444 asyncWork->Run();
445 return asyncWork->GetRet();
446 }
447
Close(napi_env env,napi_callback_info info)448 napi_value NapiGattClient::Close(napi_env env, napi_callback_info info)
449 {
450 HILOGI("enter");
451 NapiGattClient* gattClient = nullptr;
452 auto status = CheckGattClientNoArgc(env, info, &gattClient);
453 NAPI_BT_ASSERT_RETURN_FALSE(env, status == napi_ok, BT_ERR_INVALID_PARAM);
454
455 std::shared_ptr<GattClient> client = gattClient->GetClient();
456 NAPI_BT_ASSERT_RETURN_FALSE(env, client != nullptr, BT_ERR_INTERNAL_ERROR);
457
458 int ret = client->Close();
459 HILOGI("ret: %{public}d", ret);
460 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
461 return NapiGetBooleanTrue(env);
462 }
463
CheckSetBLEMtuSize(napi_env env,napi_callback_info info,int32_t & mtuSize,NapiGattClient ** outGattClient)464 static napi_status CheckSetBLEMtuSize(napi_env env, napi_callback_info info,
465 int32_t &mtuSize, NapiGattClient **outGattClient)
466 {
467 size_t expectedArgsCount = ARGS_SIZE_ONE;
468 size_t argc = expectedArgsCount;
469 napi_value argv[ARGS_SIZE_ONE] = {0};
470 napi_value thisVar = nullptr;
471 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
472 NAPI_BT_RETURN_IF(argc != expectedArgsCount, "Requires 1 arguments.", napi_invalid_arg);
473 NapiGattClient *gattClient = NapiGetGattClient(env, thisVar);
474 NAPI_BT_RETURN_IF(gattClient == nullptr || outGattClient == nullptr, "gattClient is nullptr.", napi_invalid_arg);
475
476 NAPI_BT_CALL_RETURN(NapiParseInt32(env, argv[PARAM0], mtuSize));
477 *outGattClient = gattClient;
478
479 return napi_ok;
480 }
481
SetBLEMtuSize(napi_env env,napi_callback_info info)482 napi_value NapiGattClient::SetBLEMtuSize(napi_env env, napi_callback_info info)
483 {
484 HILOGI("enter");
485 NapiGattClient* gattClient = nullptr;
486 int32_t mtuSize = 0;
487
488 auto status = CheckSetBLEMtuSize(env, info, mtuSize, &gattClient);
489 NAPI_BT_ASSERT_RETURN_FALSE(env, status == napi_ok, BT_ERR_INVALID_PARAM);
490
491 std::shared_ptr<GattClient> client = gattClient->GetClient();
492 NAPI_BT_ASSERT_RETURN_FALSE(env, client != nullptr, BT_ERR_INTERNAL_ERROR);
493
494 int ret = client->RequestBleMtuSize(mtuSize);
495 HILOGI("ret: %{public}d", ret);
496 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
497 return NapiGetBooleanTrue(env);
498 }
499
ParseGattClientReadRssiValue(napi_env env,napi_callback_info info,NapiGattClient ** outGattClient)500 static napi_status ParseGattClientReadRssiValue(napi_env env, napi_callback_info info, NapiGattClient **outGattClient)
501 {
502 size_t expectedArgsCount = ARGS_SIZE_ONE;
503 size_t argc = expectedArgsCount;
504 napi_value argv[ARGS_SIZE_ONE] = {0};
505 napi_value thisVar = nullptr;
506 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
507 NAPI_BT_RETURN_IF(argc != expectedArgsCount && argc != expectedArgsCount - CALLBACK_SIZE,
508 "Requires 0 or 1 arguments.", napi_invalid_arg);
509 NapiGattClient *gattClient = NapiGetGattClient(env, thisVar);
510 NAPI_BT_RETURN_IF(outGattClient == nullptr || gattClient == nullptr, "gattClient is nullptr.", napi_invalid_arg);
511 *outGattClient = gattClient;
512 return napi_ok;
513 }
514
GetRssiValue(napi_env env,napi_callback_info info)515 napi_value NapiGattClient::GetRssiValue(napi_env env, napi_callback_info info)
516 {
517 HILOGI("enter");
518 NapiGattClient *napiGattClient = nullptr;
519 auto status = ParseGattClientReadRssiValue(env, info, &napiGattClient);
520 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok && napiGattClient, BT_ERR_INVALID_PARAM);
521 NAPI_BT_ASSERT_RETURN_UNDEF(env, napiGattClient->GetCallback() != nullptr, BT_ERR_INTERNAL_ERROR);
522
523 auto func = [gattClient = napiGattClient->GetClient()] {
524 int ret = BT_ERR_INTERNAL_ERROR;
525 if (gattClient) {
526 ret = gattClient->ReadRemoteRssiValue();
527 }
528 return NapiAsyncWorkRet(ret);
529 };
530 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK);
531 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
532 bool success = napiGattClient->GetCallback()->asyncWorkMap_.TryPush(GATT_CLIENT_READ_REMOTE_RSSI_VALUE, asyncWork);
533 NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
534
535 asyncWork->Run();
536 return asyncWork->GetRet();
537 }
538
CheckGattClientGetDeviceName(napi_env env,napi_callback_info info)539 static napi_status CheckGattClientGetDeviceName(napi_env env, napi_callback_info info)
540 {
541 size_t argc = ARGS_SIZE_ONE;
542 napi_value argv[ARGS_SIZE_ONE] = {nullptr};
543 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, NULL));
544 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ZERO && argc != ARGS_SIZE_ONE, "Requires 0 or 1 arguments.", napi_invalid_arg);
545 return napi_ok;
546 }
547
GetDeviceName(napi_env env,napi_callback_info info)548 napi_value NapiGattClient::GetDeviceName(napi_env env, napi_callback_info info)
549 {
550 HILOGD("start");
551
552 auto status = CheckGattClientGetDeviceName(env, info);
553 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
554 NapiGattClient *napiGattClient = NapiGetGattClient(env, info);
555 std::string deviceAddr = "";
556 if (napiGattClient && napiGattClient->GetDevice()) {
557 deviceAddr = napiGattClient->GetDevice()->GetDeviceAddr();
558 }
559 auto func = [deviceAddr]() {
560 std::string deviceName = "";
561 int32_t err = BluetoothHost::GetDefaultHost().GetRemoteDevice(
562 deviceAddr, BT_TRANSPORT_BLE).GetDeviceName(deviceName);
563
564 HILOGI("err: %{public}d, deviceName: %{public}s", err, deviceName.c_str());
565 auto object = std::make_shared<NapiNativeString>(deviceName);
566 return NapiAsyncWorkRet(err, object);
567 };
568 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
569 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
570 asyncWork->Run();
571 return asyncWork->GetRet();
572 }
573
574 #ifdef BLUETOOTH_API_SINCE_10
575
CheckWriteCharacteristicValueEx(napi_env env,napi_callback_info info,GattCharacteristic ** outCharacteristic,NapiGattClient ** outGattClient,std::vector<uint8_t> & outValue)576 static napi_status CheckWriteCharacteristicValueEx(napi_env env, napi_callback_info info,
577 GattCharacteristic **outCharacteristic, NapiGattClient **outGattClient, std::vector<uint8_t> &outValue)
578 {
579 size_t argc = ARGS_SIZE_THREE;
580 napi_value argv[ARGS_SIZE_THREE] = {0};
581 napi_value thisVar = nullptr;
582 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
583 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO && argc != ARGS_SIZE_THREE, "Requires 2 or 3 arguments.", napi_invalid_arg);
584 NapiGattClient *gattClient = NapiGetGattClient(env, thisVar);
585 NAPI_BT_RETURN_IF(gattClient == nullptr || outGattClient == nullptr, "gattClient is nullptr.", napi_invalid_arg);
586
587 NapiBleCharacteristic napiCharacter;
588 NAPI_BT_CALL_RETURN(NapiParseGattCharacteristic(env, argv[PARAM0], napiCharacter));
589 GattCharacteristic *character = GetGattcCharacteristic(gattClient->GetClient(), napiCharacter);
590 NAPI_BT_RETURN_IF(character == nullptr || outCharacteristic == nullptr, "Not found character", napi_invalid_arg);
591
592 int writeType = GattCharacteristic::WriteType::DEFAULT;
593 NAPI_BT_CALL_RETURN(NapiParseGattWriteType(env, argv[PARAM1], writeType));
594 character->SetWriteType(writeType);
595
596 outValue = std::move(napiCharacter.characteristicValue);
597 *outGattClient = gattClient;
598 *outCharacteristic = character;
599
600 return napi_ok;
601 }
602
WriteCharacteristicValueEx(napi_env env,napi_callback_info info)603 napi_value NapiGattClient::WriteCharacteristicValueEx(napi_env env, napi_callback_info info)
604 {
605 HILOGI("enter");
606 GattCharacteristic* character = nullptr;
607 NapiGattClient* client = nullptr;
608
609 std::vector<uint8_t> value {};
610 auto status = CheckWriteCharacteristicValueEx(env, info, &character, &client, value);
611 NAPI_BT_ASSERT_RETURN_FALSE(env, status == napi_ok && character && client, BT_ERR_INVALID_PARAM);
612 NAPI_BT_ASSERT_RETURN_UNDEF(env, client->GetCallback() != nullptr, BT_ERR_INTERNAL_ERROR);
613
614 auto func = [gattClient = client->GetClient(), character]() {
615 if (character == nullptr) {
616 HILOGE("character is nullptr");
617 return NapiAsyncWorkRet(BT_ERR_INTERNAL_ERROR);
618 }
619 int ret = BT_ERR_INTERNAL_ERROR;
620 if (gattClient) {
621 ret = gattClient->WriteCharacteristic(*character);
622 }
623 return NapiAsyncWorkRet(ret);
624 };
625
626 bool isNeedCallback = character->GetWriteType() == GattCharacteristic::WriteType::DEFAULT;
627 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(
628 env, info, func, isNeedCallback ? ASYNC_WORK_NEED_CALLBACK : ASYNC_WORK_NO_NEED_CALLBACK);
629 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
630 // GattCharacteristic write need callback, write no response is not needed.
631 if (isNeedCallback) {
632 bool success = client->GetCallback()->asyncWorkMap_.TryPush(GATT_CLIENT_WRITE_CHARACTER, asyncWork);
633 NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
634 }
635
636 asyncWork->Run();
637 return asyncWork->GetRet();
638 }
639
CheckWriteDescriptorValueEx(napi_env env,napi_callback_info info,GattDescriptor ** outDescriptor,NapiGattClient ** outGattClient)640 static napi_status CheckWriteDescriptorValueEx(napi_env env, napi_callback_info info,
641 GattDescriptor **outDescriptor, NapiGattClient **outGattClient)
642 {
643 size_t argc = ARGS_SIZE_TWO;
644 napi_value argv[ARGS_SIZE_TWO] = {0};
645 napi_value thisVar = nullptr;
646 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
647 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO, "Requires 1 or 2 arguments.", napi_invalid_arg);
648 NapiGattClient *gattClient = NapiGetGattClient(env, thisVar);
649 NAPI_BT_RETURN_IF(gattClient == nullptr || outGattClient == nullptr, "gattClient is nullptr.", napi_invalid_arg);
650
651 NapiBleDescriptor napiDescriptor;
652 NAPI_BT_CALL_RETURN(NapiParseGattDescriptor(env, argv[PARAM0], napiDescriptor));
653 GattDescriptor *descriptor = GetGattcDescriptor(gattClient->GetClient(), napiDescriptor);
654 NAPI_BT_RETURN_IF(descriptor == nullptr, "Not found Descriptor", napi_invalid_arg);
655
656 *outGattClient = gattClient;
657 *outDescriptor = descriptor;
658 return napi_ok;
659 }
660
WriteDescriptorValueEx(napi_env env,napi_callback_info info)661 napi_value NapiGattClient::WriteDescriptorValueEx(napi_env env, napi_callback_info info)
662 {
663 HILOGI("enter");
664 NapiGattClient* client = nullptr;
665 GattDescriptor* descriptor = nullptr;
666 auto status = CheckWriteDescriptorValueEx(env, info, &descriptor, &client);
667 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok && client && descriptor, BT_ERR_INVALID_PARAM);
668 NAPI_BT_ASSERT_RETURN_UNDEF(env, client->GetCallback() != nullptr, BT_ERR_INTERNAL_ERROR);
669
670 auto func = [gattClient = client->GetClient(), descriptor]() {
671 if (descriptor == nullptr) {
672 HILOGE("descriptor is nullptr");
673 return NapiAsyncWorkRet(BT_ERR_INTERNAL_ERROR);
674 }
675 int ret = BT_ERR_INTERNAL_ERROR;
676 if (gattClient) {
677 ret = gattClient->WriteDescriptor(*descriptor);
678 }
679 return NapiAsyncWorkRet(ret);
680 };
681 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK);
682 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
683 bool success = client->GetCallback()->asyncWorkMap_.TryPush(GATT_CLIENT_WRITE_DESCRIPTOR, asyncWork);
684 NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
685
686 asyncWork->Run();
687 return asyncWork->GetRet();
688 }
689
CheckSetCharacteristicChange(napi_env env,napi_callback_info info,GattCharacteristic ** outCharacteristic,bool & enable,NapiGattClient ** outGattClient)690 static napi_status CheckSetCharacteristicChange(napi_env env, napi_callback_info info,
691 GattCharacteristic **outCharacteristic, bool &enable, NapiGattClient **outGattClient)
692 {
693 size_t argc = ARGS_SIZE_THREE;
694 napi_value argv[ARGS_SIZE_THREE] = {0};
695 napi_value thisVar = nullptr;
696 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
697 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO && argc != ARGS_SIZE_THREE, "Requires 2 or 3 arguments.", napi_invalid_arg);
698 NapiGattClient *gattClient = NapiGetGattClient(env, thisVar);
699 NAPI_BT_RETURN_IF(gattClient == nullptr || outGattClient == nullptr, "gattClient is nullptr.", napi_invalid_arg);
700
701 NapiBleCharacteristic napiCharacter;
702 NAPI_BT_CALL_RETURN(NapiParseGattCharacteristic(env, argv[PARAM0], napiCharacter));
703 GattCharacteristic *character = GetGattcCharacteristic(gattClient->GetClient(), napiCharacter);
704 NAPI_BT_RETURN_IF(character == nullptr || outCharacteristic == nullptr, "Not found character", napi_invalid_arg);
705
706 NAPI_BT_CALL_RETURN(NapiParseBoolean(env, argv[PARAM1], enable));
707 *outGattClient = gattClient;
708 *outCharacteristic = character;
709 return napi_ok;
710 }
711
setCharacteristicChangeInner(napi_env env,napi_callback_info info,bool isNotify)712 static napi_value setCharacteristicChangeInner(napi_env env, napi_callback_info info, bool isNotify)
713 {
714 GattCharacteristic *character = nullptr;
715 bool enable = false;
716 NapiGattClient *client = nullptr;
717
718 auto status = CheckSetCharacteristicChange(env, info, &character, enable, &client);
719 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok && client && character, BT_ERR_INVALID_PARAM);
720 NAPI_BT_ASSERT_RETURN_UNDEF(env, client->GetCallback() != nullptr, BT_ERR_INTERNAL_ERROR);
721
722 auto func = [gattClient = client->GetClient(), character, enable, isNotify]() {
723 if (character == nullptr) {
724 HILOGE("character is nullptr");
725 return NapiAsyncWorkRet(BT_ERR_INTERNAL_ERROR);
726 }
727 int ret = BT_ERR_INTERNAL_ERROR;
728 if (gattClient) {
729 if (isNotify) {
730 ret = gattClient->SetNotifyCharacteristic(*character, enable);
731 } else {
732 ret = gattClient->SetIndicateCharacteristic(*character, enable);
733 }
734 }
735 return NapiAsyncWorkRet(ret);
736 };
737 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NEED_CALLBACK);
738 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
739 bool success = client->GetCallback()->asyncWorkMap_.TryPush(GATT_CLIENT_ENABLE_CHARACTER_CHANGED, asyncWork);
740 NAPI_BT_ASSERT_RETURN_UNDEF(env, success, BT_ERR_INTERNAL_ERROR);
741
742 asyncWork->Run();
743 return asyncWork->GetRet();
744 }
745
setCharacteristicChangeNotification(napi_env env,napi_callback_info info)746 napi_value NapiGattClient::setCharacteristicChangeNotification(napi_env env, napi_callback_info info)
747 {
748 HILOGI("enter");
749 return setCharacteristicChangeInner(env, info, true);
750 }
751
setCharacteristicChangeIndication(napi_env env,napi_callback_info info)752 napi_value NapiGattClient::setCharacteristicChangeIndication(napi_env env, napi_callback_info info)
753 {
754 HILOGI("enter");
755 return setCharacteristicChangeInner(env, info, false);
756 }
757
758 #else // ! BLUETOOTH_API_SINCE_10
759
CheckWriteCharacteristicValue(napi_env env,napi_callback_info info,GattCharacteristic ** outCharacteristic,NapiGattClient ** outGattClient,std::vector<uint8_t> & outValue)760 static napi_status CheckWriteCharacteristicValue(napi_env env, napi_callback_info info,
761 GattCharacteristic **outCharacteristic, NapiGattClient **outGattClient, std::vector<uint8_t> &outValue)
762 {
763 size_t expectedArgsCount = ARGS_SIZE_ONE;
764 size_t argc = expectedArgsCount;
765 napi_value argv[ARGS_SIZE_ONE] = {0};
766 napi_value thisVar = nullptr;
767 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
768 NAPI_BT_RETURN_IF(argc != expectedArgsCount, "Requires 1 arguments.", napi_invalid_arg);
769 NapiGattClient *gattClient = NapiGetGattClient(env, thisVar);
770 NAPI_BT_RETURN_IF(gattClient == nullptr || outGattClient == nullptr, "gattClient is nullptr.", napi_invalid_arg);
771
772 NapiBleCharacteristic napiCharacter;
773 NAPI_BT_CALL_RETURN(NapiParseGattCharacteristic(env, argv[PARAM0], napiCharacter));
774 GattCharacteristic *character = GetGattcCharacteristic(gattClient->GetClient(), napiCharacter);
775 NAPI_BT_RETURN_IF(character == nullptr, "Not found character", napi_invalid_arg);
776
777 outValue = std::move(napiCharacter.characteristicValue);
778 *outGattClient = gattClient;
779 *outCharacteristic = character;
780
781 return napi_ok;
782 }
783
WriteCharacteristicValue(napi_env env,napi_callback_info info)784 napi_value NapiGattClient::WriteCharacteristicValue(napi_env env, napi_callback_info info)
785 {
786 HILOGI("enter");
787 GattCharacteristic* characteristic = nullptr;
788 NapiGattClient* gattClient = nullptr;
789
790 std::vector<uint8_t> value {};
791 auto status = CheckWriteCharacteristicValue(env, info, &characteristic, &gattClient, value);
792 NAPI_BT_ASSERT_RETURN_FALSE(env, status == napi_ok, BT_ERR_INVALID_PARAM);
793 std::shared_ptr<GattClient> client = gattClient->GetClient();
794 NAPI_BT_ASSERT_RETURN_FALSE(env, client != nullptr, BT_ERR_INTERNAL_ERROR);
795 int ret = client->WriteCharacteristic(*characteristic, std::move(value));
796 HILOGI("ret: %{public}d", ret);
797 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
798 return NapiGetBooleanTrue(env);
799 }
800
CheckWriteDescriptorValue(napi_env env,napi_callback_info info,GattDescriptor ** outDescriptor,NapiGattClient ** outGattClient)801 static napi_status CheckWriteDescriptorValue(napi_env env, napi_callback_info info,
802 GattDescriptor **outDescriptor, NapiGattClient **outGattClient)
803 {
804 size_t expectedArgsCount = ARGS_SIZE_ONE;
805 size_t argc = expectedArgsCount;
806 napi_value argv[ARGS_SIZE_ONE] = {0};
807 napi_value thisVar = nullptr;
808 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
809 NAPI_BT_RETURN_IF(argc != expectedArgsCount, "Requires 1 arguments.", napi_invalid_arg);
810 NapiGattClient *gattClient = NapiGetGattClient(env, thisVar);
811 NAPI_BT_RETURN_IF(gattClient == nullptr || outGattClient == nullptr, "gattClient is nullptr.", napi_invalid_arg);
812
813 NapiBleDescriptor napiDescriptor;
814 NAPI_BT_CALL_RETURN(NapiParseGattDescriptor(env, argv[PARAM0], napiDescriptor));
815 GattDescriptor *descriptor = GetGattcDescriptor(gattClient->GetClient(), napiDescriptor);
816 NAPI_BT_RETURN_IF(descriptor == nullptr, "Not found Descriptor", napi_invalid_arg);
817
818 *outGattClient = gattClient;
819 *outDescriptor = descriptor;
820 return napi_ok;
821 }
822
WriteDescriptorValue(napi_env env,napi_callback_info info)823 napi_value NapiGattClient::WriteDescriptorValue(napi_env env, napi_callback_info info)
824 {
825 HILOGI("enter");
826 GattDescriptor* descriptor = nullptr;
827 NapiGattClient* gattClient = nullptr;
828
829 auto status = CheckWriteDescriptorValue(env, info, &descriptor, &gattClient);
830 NAPI_BT_ASSERT_RETURN_FALSE(env, status == napi_ok, BT_ERR_INVALID_PARAM);
831
832 std::shared_ptr<GattClient> client = gattClient->GetClient();
833 NAPI_BT_ASSERT_RETURN_FALSE(env, client != nullptr, BT_ERR_INTERNAL_ERROR);
834
835 int ret = client->WriteDescriptor(*descriptor);
836 HILOGI("ret: %{public}d", ret);
837 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
838 return NapiGetBooleanTrue(env);
839 }
840
CheckSetNotifyCharacteristicChanged(napi_env env,napi_callback_info info,GattCharacteristic ** outCharacteristic,bool & enableNotify,NapiGattClient ** outGattClient)841 static napi_status CheckSetNotifyCharacteristicChanged(napi_env env, napi_callback_info info,
842 GattCharacteristic **outCharacteristic, bool &enableNotify, NapiGattClient **outGattClient)
843 {
844 size_t expectedArgsCount = ARGS_SIZE_TWO;
845 size_t argc = expectedArgsCount;
846 napi_value argv[ARGS_SIZE_TWO] = {0};
847 napi_value thisVar = nullptr;
848 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
849 NAPI_BT_RETURN_IF(argc != expectedArgsCount, "Requires 2 arguments.", napi_invalid_arg);
850 NapiGattClient *gattClient = NapiGetGattClient(env, thisVar);
851 NAPI_BT_RETURN_IF(gattClient == nullptr || outGattClient == nullptr, "gattClient is nullptr.", napi_invalid_arg);
852
853 NapiBleCharacteristic napiCharacter;
854 NAPI_BT_CALL_RETURN(NapiParseGattCharacteristic(env, argv[PARAM0], napiCharacter));
855 GattCharacteristic *character = GetGattcCharacteristic(gattClient->GetClient(), napiCharacter);
856 NAPI_BT_RETURN_IF(character == nullptr, "Not found character", napi_invalid_arg);
857
858 NAPI_BT_CALL_RETURN(NapiParseBoolean(env, argv[PARAM1], enableNotify));
859 *outGattClient = gattClient;
860 *outCharacteristic = character;
861 return napi_ok;
862 }
863
SetNotifyCharacteristicChanged(napi_env env,napi_callback_info info)864 napi_value NapiGattClient::SetNotifyCharacteristicChanged(napi_env env, napi_callback_info info)
865 {
866 HILOGI("enter");
867 GattCharacteristic* characteristic = nullptr;
868 bool enableNotify = false;
869 NapiGattClient* gattClient = nullptr;
870
871 auto status = CheckSetNotifyCharacteristicChanged(env, info, &characteristic, enableNotify, &gattClient);
872 NAPI_BT_ASSERT_RETURN_FALSE(env, status == napi_ok, BT_ERR_INVALID_PARAM);
873
874 std::shared_ptr<GattClient> client = gattClient->GetClient();
875 NAPI_BT_ASSERT_RETURN_FALSE(env, client != nullptr, BT_ERR_INTERNAL_ERROR);
876
877 int ret = client->SetNotifyCharacteristic(*characteristic, enableNotify);
878 HILOGI("ret: %{public}d", ret);
879 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
880 return NapiGetBooleanTrue(env);
881 }
882
883 #endif
884
885 } // namespace Bluetooth
886 } // namespace OHOS
887