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