• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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