• 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 
16 #include "napi_bluetooth_utils.h"
17 #include "napi_bluetooth_ble_utils.h"
18 #include <algorithm>
19 #include <functional>
20 #include <optional>
21 #include "bluetooth_errorcode.h"
22 #include "bluetooth_log.h"
23 #include "napi/native_api.h"
24 #include "napi/native_node_api.h"
25 #include "napi_bluetooth_error.h"
26 #include "securec.h"
27 
28 namespace OHOS {
29 namespace Bluetooth {
30 using namespace std;
ConvertGattServiceToJS(napi_env env,napi_value result,GattService & service)31 void ConvertGattServiceToJS(napi_env env, napi_value result, GattService& service)
32 {
33     napi_value serviceUuid;
34     napi_create_string_utf8(env, service.GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH, &serviceUuid);
35     napi_set_named_property(env, result, "serviceUuid", serviceUuid);
36 
37     napi_value isPrimary;
38     napi_get_boolean(env, service.IsPrimary(), &isPrimary);
39     napi_set_named_property(env, result, "isPrimary", isPrimary);
40     HILOGI("uuid: %{public}s, isPrimary: %{public}d", service.GetUuid().ToString().c_str(), service.IsPrimary());
41 
42     napi_value characteristics;
43     napi_create_array(env, &characteristics);
44     ConvertBLECharacteristicVectorToJS(env, characteristics, service.GetCharacteristics());
45     napi_set_named_property(env, result, "characteristics", characteristics);
46 
47     napi_value includedServices;
48     napi_create_array(env, &includedServices);
49     vector<GattService> services;
50     vector<std::reference_wrapper<GattService>> srvs = service.GetIncludedServices();
51     for (auto &srv : srvs) {
52         services.push_back(srv.get());
53     }
54     ConvertGattServiceVectorToJS(env, includedServices, services);
55     napi_set_named_property(env, result, "includedServices", includedServices);
56 }
57 
ConvertGattServiceVectorToJS(napi_env env,napi_value result,vector<GattService> & services)58 void ConvertGattServiceVectorToJS(napi_env env, napi_value result, vector<GattService>& services)
59 {
60     HILOGI("enter");
61     size_t idx = 0;
62 
63     if (services.empty()) {
64         return;
65     }
66     HILOGI("size: %{public}zu", services.size());
67     for (auto& service : services) {
68         napi_value obj = nullptr;
69         napi_create_object(env, &obj);
70         ConvertGattServiceToJS(env, obj, service);
71         napi_set_element(env, result, idx, obj);
72         idx++;
73     }
74 }
75 
ConvertBLECharacteristicVectorToJS(napi_env env,napi_value result,vector<GattCharacteristic> & characteristics)76 void ConvertBLECharacteristicVectorToJS(napi_env env, napi_value result,
77     vector<GattCharacteristic>& characteristics)
78 {
79     HILOGI("size: %{public}zu", characteristics.size());
80     size_t idx = 0;
81     if (characteristics.empty()) {
82         return;
83     }
84 
85     for (auto &characteristic : characteristics) {
86         napi_value obj = nullptr;
87         napi_create_object(env, &obj);
88         ConvertBLECharacteristicToJS(env, obj, characteristic);
89         napi_set_element(env, result, idx, obj);
90         idx++;
91     }
92 }
93 
HasProperty(int properties,int propertyMask)94 bool HasProperty(int properties, int propertyMask)
95 {
96     if (properties < 0 || propertyMask < 0) {
97         HILOGE("properties or propertyMask is less than 0");
98         return false;
99     }
100     return (static_cast<unsigned int>(properties) & static_cast<unsigned int>(propertyMask)) != 0;
101 }
ConvertGattPropertiesToJs(napi_env env,int properties)102 napi_value ConvertGattPropertiesToJs(napi_env env, int properties)
103 {
104     napi_value object;
105     napi_create_object(env, &object);
106 
107     napi_value value;
108     napi_get_boolean(env, HasProperty(properties, GattCharacteristic::WRITE), &value);
109     napi_set_named_property(env, object, "write", value);
110 
111     napi_get_boolean(env, HasProperty(properties, GattCharacteristic::WRITE_WITHOUT_RESPONSE), &value);
112     napi_set_named_property(env, object, "writeNoResponse", value);
113 
114     napi_get_boolean(env, HasProperty(properties, GattCharacteristic::READ), &value);
115     napi_set_named_property(env, object, "read", value);
116 
117     napi_get_boolean(env, HasProperty(properties, GattCharacteristic::NOTIFY), &value);
118     napi_set_named_property(env, object, "notify", value);
119 
120     napi_get_boolean(env, HasProperty(properties, GattCharacteristic::INDICATE), &value);
121     napi_set_named_property(env, object, "indicate", value);
122     return object;
123 }
124 
ConvertBLECharacteristicToJS(napi_env env,napi_value result,GattCharacteristic & characteristic)125 void ConvertBLECharacteristicToJS(napi_env env, napi_value result, GattCharacteristic& characteristic)
126 {
127     napi_value characteristicUuid;
128     HILOGI("uuid: %{public}s", characteristic.GetUuid().ToString().c_str());
129     napi_create_string_utf8(env, characteristic.GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH, &characteristicUuid);
130     napi_set_named_property(env, result, "characteristicUuid", characteristicUuid);
131 
132     if (characteristic.GetService() != nullptr) {
133         napi_value serviceUuid;
134         napi_create_string_utf8(env, characteristic.GetService()->GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH,
135             &serviceUuid);
136         napi_set_named_property(env, result, "serviceUuid", serviceUuid);
137     }
138 
139     size_t valueSize = 0;
140     uint8_t* valueData = characteristic.GetValue(&valueSize).get();
141     {
142         napi_value value = nullptr;
143         uint8_t* bufferData = nullptr;
144         napi_create_arraybuffer(env, valueSize, (void**)&bufferData, &value);
145         if (valueSize > 0 && memcpy_s(bufferData, valueSize, valueData, valueSize) != EOK) {
146             HILOGE("memcpy_s failed");
147             return;
148         }
149         napi_set_named_property(env, result, "characteristicValue", value);
150     }
151 
152     napi_value propertiesValue = ConvertGattPropertiesToJs(env, characteristic.GetProperties());
153     napi_set_named_property(env, result, "properties", propertiesValue);
154 
155     napi_value descriptors;
156     napi_create_array(env, &descriptors);
157     ConvertBLEDescriptorVectorToJS(env, descriptors, characteristic.GetDescriptors());
158     napi_set_named_property(env, result, "descriptors", descriptors);
159 }
160 
ConvertBLEDescriptorVectorToJS(napi_env env,napi_value result,vector<GattDescriptor> & descriptors)161 void ConvertBLEDescriptorVectorToJS(napi_env env, napi_value result, vector<GattDescriptor>& descriptors)
162 {
163     HILOGI("size: %{public}zu", descriptors.size());
164     size_t idx = 0;
165 
166     if (descriptors.empty()) {
167         return;
168     }
169 
170     for (auto& descriptor : descriptors) {
171         napi_value obj = nullptr;
172         napi_create_object(env, &obj);
173         ConvertBLEDescriptorToJS(env, obj, descriptor);
174         napi_set_element(env, result, idx, obj);
175         idx++;
176     }
177 }
178 
ConvertBLEDescriptorToJS(napi_env env,napi_value result,GattDescriptor & descriptor)179 void ConvertBLEDescriptorToJS(napi_env env, napi_value result, GattDescriptor& descriptor)
180 {
181     HILOGI("uuid: %{public}s", descriptor.GetUuid().ToString().c_str());
182 
183     napi_value descriptorUuid;
184     napi_create_string_utf8(env, descriptor.GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH, &descriptorUuid);
185     napi_set_named_property(env, result, "descriptorUuid", descriptorUuid);
186 
187     if (descriptor.GetCharacteristic() != nullptr) {
188         napi_value characteristicUuid;
189         napi_create_string_utf8(env, descriptor.GetCharacteristic()->GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH,
190             &characteristicUuid);
191         napi_set_named_property(env, result, "characteristicUuid", characteristicUuid);
192 
193         if (descriptor.GetCharacteristic()->GetService() != nullptr) {
194             napi_value serviceUuid;
195             napi_create_string_utf8(env, descriptor.GetCharacteristic()->GetService()->GetUuid().ToString().c_str(),
196                 NAPI_AUTO_LENGTH, &serviceUuid);
197             napi_set_named_property(env, result, "serviceUuid", serviceUuid);
198         }
199     }
200 
201     napi_value value;
202     size_t valueSize;
203     uint8_t* valueData = descriptor.GetValue(&valueSize).get();
204     uint8_t* bufferData = nullptr;
205     napi_create_arraybuffer(env, valueSize, (void**)&bufferData, &value);
206     if (memcpy_s(bufferData, valueSize, valueData, valueSize) != EOK) {
207         HILOGE("memcpy_s error");
208     }
209     napi_set_named_property(env, result, "descriptorValue", value);
210 }
211 
ConvertCharacteristicReadReqToJS(napi_env env,napi_value result,const std::string & device,const GattCharacteristic & characteristic,int requestId)212 void ConvertCharacteristicReadReqToJS(napi_env env, napi_value result, const std::string &device,
213     const GattCharacteristic &characteristic, int requestId)
214 {
215     napi_value deviceId;
216     napi_create_string_utf8(env, device.c_str(), NAPI_AUTO_LENGTH, &deviceId);
217     napi_set_named_property(env, result, "deviceId", deviceId);
218 
219     napi_value transId;
220     napi_create_int32(env, requestId, &transId);
221     napi_set_named_property(env, result, "transId", transId);
222 
223     napi_value offset;
224     napi_create_int32(env, 0, &offset);
225     napi_set_named_property(env, result, "offset", offset);
226     HILOGI("offset is %{public}d", 0);
227 
228     napi_value characteristicUuid;
229     napi_create_string_utf8(env, characteristic.GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH, &characteristicUuid);
230     napi_set_named_property(env, result, "characteristicUuid", characteristicUuid);
231     HILOGI("characteristicUuid is %{public}s", characteristic.GetUuid().ToString().c_str());
232 
233     if (characteristic.GetService() != nullptr) {
234         napi_value serviceUuid;
235         napi_create_string_utf8(env, characteristic.GetService()->GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH,
236             &serviceUuid);
237         napi_set_named_property(env, result, "serviceUuid", serviceUuid);
238     }
239 }
240 
ConvertDescriptorReadReqToJS(napi_env env,napi_value result,const std::string & device,const GattDescriptor & descriptor,int requestId)241 void ConvertDescriptorReadReqToJS(napi_env env, napi_value result, const std::string &device,
242     const GattDescriptor& descriptor, int requestId)
243 {
244     napi_value deviceId;
245     napi_create_string_utf8(env, device.c_str(), NAPI_AUTO_LENGTH, &deviceId);
246     napi_set_named_property(env, result, "deviceId", deviceId);
247 
248     napi_value transId;
249     napi_create_int32(env, requestId, &transId);
250     napi_set_named_property(env, result, "transId", transId);
251 
252     napi_value offset;
253     napi_create_int32(env, 0, &offset);
254     napi_set_named_property(env, result, "offset", offset);
255     HILOGI("offset is %{public}d", 0);
256 
257     napi_value descriptorUuid;
258     napi_create_string_utf8(env, descriptor.GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH, &descriptorUuid);
259     napi_set_named_property(env, result, "descriptorUuid", descriptorUuid);
260     HILOGI("descriptorUuid is %{public}s", descriptor.GetUuid().ToString().c_str());
261 
262     if (descriptor.GetCharacteristic() != nullptr) {
263     napi_value characteristicUuid;
264     napi_create_string_utf8(env, descriptor.GetCharacteristic()->GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH,
265         &characteristicUuid);
266     napi_set_named_property(env, result, "characteristicUuid", characteristicUuid);
267 
268         if (descriptor.GetCharacteristic()->GetService() != nullptr) {
269             napi_value serviceUuid;
270             napi_create_string_utf8(env, descriptor.GetCharacteristic()->GetService()->GetUuid().ToString().c_str(),
271                 NAPI_AUTO_LENGTH, &serviceUuid);
272             napi_set_named_property(env, result, "serviceUuid", serviceUuid);
273         }
274     }
275 }
276 
ConvertCharacteristicWriteReqToJS(napi_env env,napi_value result,const std::string & device,const GattCharacteristic & characteristic,int requestId)277 void ConvertCharacteristicWriteReqToJS(napi_env env, napi_value result, const std::string &device,
278     const GattCharacteristic& characteristic, int requestId)
279 {
280     napi_value deviceId;
281     napi_create_string_utf8(env, device.c_str(), NAPI_AUTO_LENGTH, &deviceId);
282     napi_set_named_property(env, result, "deviceId", deviceId);
283 
284     napi_value transId;
285     napi_create_int32(env, requestId, &transId);
286     napi_set_named_property(env, result, "transId", transId);
287 
288     napi_value offset;
289     napi_create_int32(env, 0, &offset);
290     napi_set_named_property(env, result, "offset", offset);
291     HILOGI("offset is %{public}d", 0);
292 
293     napi_value isPrepared;
294     napi_get_boolean(env, false, &isPrepared);
295     napi_set_named_property(env, result, "isPrepared", isPrepared);
296 
297     napi_value needRsp;
298     napi_get_boolean(env, characteristic.GetWriteType() == GattCharacteristic::WriteType::DEFAULT, &needRsp);
299     napi_set_named_property(env, result, "needRsp", needRsp);
300 
301     napi_value value;
302     size_t valueSize;
303     uint8_t* valueData = characteristic.GetValue(&valueSize).get();
304     uint8_t* bufferData = nullptr;
305     napi_create_arraybuffer(env, valueSize, (void**)&bufferData, &value);
306     if (memcpy_s(bufferData, valueSize, valueData, valueSize) != EOK) {
307         HILOGE("memcpy_s error");
308     }
309     napi_set_named_property(env, result, "value", value);
310 
311     napi_value characteristicUuid;
312     napi_create_string_utf8(env, characteristic.GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH, &characteristicUuid);
313     napi_set_named_property(env, result, "characteristicUuid", characteristicUuid);
314     HILOGI("characteristicUuid is %{public}s", characteristic.GetUuid().ToString().c_str());
315 
316     if (characteristic.GetService() != nullptr) {
317         napi_value serviceUuid;
318         napi_create_string_utf8(env, characteristic.GetService()->GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH,
319             &serviceUuid);
320         napi_set_named_property(env, result, "serviceUuid", serviceUuid);
321     }
322 }
323 
ConvertDescriptorWriteReqToJS(napi_env env,napi_value result,const std::string & device,const GattDescriptor & descriptor,int requestId)324 void ConvertDescriptorWriteReqToJS(napi_env env, napi_value result, const std::string &device,
325     const GattDescriptor &descriptor, int requestId)
326 {
327     napi_value deviceId;
328     napi_create_string_utf8(env, device.c_str(), NAPI_AUTO_LENGTH, &deviceId);
329     napi_set_named_property(env, result, "deviceId", deviceId);
330 
331     napi_value transId;
332     napi_create_int32(env, requestId, &transId);
333     napi_set_named_property(env, result, "transId", transId);
334 
335     napi_value offset;
336     napi_create_int32(env, 0, &offset);
337     napi_set_named_property(env, result, "offset", offset);
338     HILOGI("offset is %{public}d", 0);
339 
340     napi_value isPrepared;
341     napi_get_boolean(env, false, &isPrepared);
342     napi_set_named_property(env, result, "isPrepared", isPrepared);
343 
344     napi_value needRsp;
345     napi_get_boolean(env, true, &needRsp);
346     napi_set_named_property(env, result, "needRsp", needRsp);
347 
348     napi_value value;
349     size_t valueSize;
350     uint8_t* valueData = descriptor.GetValue(&valueSize).get();
351     uint8_t* bufferData = nullptr;
352     napi_create_arraybuffer(env, valueSize, (void**)&bufferData, &value);
353     if (memcpy_s(bufferData, valueSize, valueData, valueSize) != EOK) {
354         HILOGE("memcpy_s error");
355     }
356     napi_set_named_property(env, result, "value", value);
357 
358     napi_value descriptorUuid;
359     napi_create_string_utf8(env, descriptor.GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH, &descriptorUuid);
360     napi_set_named_property(env, result, "descriptorUuid", descriptorUuid);
361     HILOGI("descriptorUuid is %{public}s", descriptor.GetUuid().ToString().c_str());
362 
363     if (descriptor.GetCharacteristic() != nullptr) {
364         napi_value characteristicUuid;
365         napi_create_string_utf8(env, descriptor.GetCharacteristic()->GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH,
366             &characteristicUuid);
367         napi_set_named_property(env, result, "characteristicUuid", characteristicUuid);
368 
369         if (descriptor.GetCharacteristic()->GetService() != nullptr) {
370             napi_value serviceUuid;
371             napi_create_string_utf8(env, descriptor.GetCharacteristic()->GetService()->GetUuid().ToString().c_str(),
372                 NAPI_AUTO_LENGTH, &serviceUuid);
373             napi_set_named_property(env, result, "serviceUuid", serviceUuid);
374         }
375     }
376 }
377 
SetGattClientDeviceId(const std::string & deviceId)378 void SetGattClientDeviceId(const std::string &deviceId)
379 {
380     deviceAddr = deviceId;
381 }
382 
GetGattClientDeviceId()383 std::string GetGattClientDeviceId()
384 {
385     return deviceAddr;
386 }
387 
ToNapiValue(napi_env env) const388 napi_value NapiNativeBleCharacteristic::ToNapiValue(napi_env env) const
389 {
390     napi_value object;
391     napi_create_object(env, &object);
392     ConvertBLECharacteristicToJS(env, object, const_cast<GattCharacteristic &>(character_));
393     return object;
394 }
395 
ToNapiValue(napi_env env) const396 napi_value NapiNativeBleDescriptor::ToNapiValue(napi_env env) const
397 {
398     napi_value object;
399     napi_create_object(env, &object);
400     ConvertBLEDescriptorToJS(env, object, const_cast<GattDescriptor &>(descriptor_));
401     return object;
402 }
403 
ToNapiValue(napi_env env) const404 napi_value NapiNativeGattServiceArray::ToNapiValue(napi_env env) const
405 {
406     napi_value object;
407     napi_create_array(env, &object);
408     ConvertGattServiceVectorToJS(env, object, const_cast<vector<GattService> &>(gattServices_));
409     return object;
410 }
411 
ToNapiValue(napi_env env) const412 napi_value NapiNativeAdvertisingStateInfo::ToNapiValue(napi_env env) const
413 {
414     napi_value object;
415     napi_create_object(env, &object);
416 
417     napi_value value;
418     napi_create_int32(env, advHandle_, &value);
419     napi_set_named_property(env, object, "advertisingId", value);
420 
421     napi_create_int32(env, advState_, &value);
422     napi_set_named_property(env, object, "state", value);
423     return object;
424 }
425 
ToNapiValue(napi_env env) const426 napi_value NapiNativeGattsCharacterReadRequest::ToNapiValue(napi_env env) const
427 {
428     napi_value result = nullptr;
429     napi_create_object(env, &result);
430 
431     ConvertCharacteristicReadReqToJS(env, result, deviceAddr_, character_, transId_);
432     return result;
433 }
434 
ToNapiValue(napi_env env) const435 napi_value NapiNativeGattsCharacterWriteRequest::ToNapiValue(napi_env env) const
436 {
437     napi_value result = nullptr;
438     napi_create_object(env, &result);
439 
440     ConvertCharacteristicWriteReqToJS(env, result, deviceAddr_, character_, transId_);
441     return result;
442 }
443 
ToNapiValue(napi_env env) const444 napi_value NapiNativeGattsDescriptorWriteRequest::ToNapiValue(napi_env env) const
445 {
446     napi_value result = nullptr;
447     napi_create_object(env, &result);
448 
449     ConvertDescriptorWriteReqToJS(env, result, deviceAddr_, descriptor_, transId_);
450     return result;
451 }
452 
ToNapiValue(napi_env env) const453 napi_value NapiNativeGattsDescriptorReadRequest::ToNapiValue(napi_env env) const
454 {
455     napi_value result = nullptr;
456     napi_create_object(env, &result);
457 
458     ConvertDescriptorReadReqToJS(env, result, deviceAddr_, descriptor_, transId_);
459     return result;
460 }
461 }  // namespace Bluetooth
462 }  // namespace OHOS
463