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