• 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,GattCharacteristic & characteristic,int requestId)212 void ConvertCharacteristicReadReqToJS(napi_env env, napi_value result, const std::string &device,
213     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,GattDescriptor & descriptor,int requestId)241 void ConvertDescriptorReadReqToJS(napi_env env, napi_value result, const std::string &device,
242     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,GattCharacteristic & characteristic,int requestId)277 void ConvertCharacteristicWriteReqToJS(napi_env env, napi_value result, const std::string &device,
278     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, true, &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     (void)memcpy_s(bufferData, valueSize, valueData, valueSize);
307     napi_set_named_property(env, result, "value", value);
308 
309     napi_value characteristicUuid;
310     napi_create_string_utf8(env, characteristic.GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH, &characteristicUuid);
311     napi_set_named_property(env, result, "characteristicUuid", characteristicUuid);
312     HILOGI("characteristicUuid is %{public}s", characteristic.GetUuid().ToString().c_str());
313 
314     if (characteristic.GetService() != nullptr) {
315         napi_value serviceUuid;
316         napi_create_string_utf8(env, characteristic.GetService()->GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH,
317             &serviceUuid);
318         napi_set_named_property(env, result, "serviceUuid", serviceUuid);
319     }
320 }
321 
ConvertDescriptorWriteReqToJS(napi_env env,napi_value result,const std::string & device,GattDescriptor & descriptor,int requestId)322 void ConvertDescriptorWriteReqToJS(napi_env env, napi_value result, const std::string &device,
323     GattDescriptor &descriptor, int requestId)
324 {
325     napi_value deviceId;
326     napi_create_string_utf8(env, device.c_str(), NAPI_AUTO_LENGTH, &deviceId);
327     napi_set_named_property(env, result, "deviceId", deviceId);
328 
329     napi_value transId;
330     napi_create_int32(env, requestId, &transId);
331     napi_set_named_property(env, result, "transId", transId);
332 
333     napi_value offset;
334     napi_create_int32(env, 0, &offset);
335     napi_set_named_property(env, result, "offset", offset);
336     HILOGI("offset is %{public}d", 0);
337 
338     napi_value isPrepared;
339     napi_get_boolean(env, false, &isPrepared);
340     napi_set_named_property(env, result, "isPrepared", isPrepared);
341 
342     napi_value needRsp;
343     napi_get_boolean(env, true, &needRsp);
344     napi_set_named_property(env, result, "needRsp", needRsp);
345 
346     napi_value value;
347     size_t valueSize;
348     uint8_t* valueData = descriptor.GetValue(&valueSize).get();
349     uint8_t* bufferData = nullptr;
350     napi_create_arraybuffer(env, valueSize, (void**)&bufferData, &value);
351     (void)memcpy_s(bufferData, valueSize, valueData, valueSize);
352     napi_set_named_property(env, result, "value", value);
353 
354     napi_value descriptorUuid;
355     napi_create_string_utf8(env, descriptor.GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH, &descriptorUuid);
356     napi_set_named_property(env, result, "descriptorUuid", descriptorUuid);
357     HILOGI("descriptorUuid is %{public}s", descriptor.GetUuid().ToString().c_str());
358 
359     if (descriptor.GetCharacteristic() != nullptr) {
360         napi_value characteristicUuid;
361         napi_create_string_utf8(env, descriptor.GetCharacteristic()->GetUuid().ToString().c_str(), NAPI_AUTO_LENGTH,
362             &characteristicUuid);
363         napi_set_named_property(env, result, "characteristicUuid", characteristicUuid);
364 
365         if (descriptor.GetCharacteristic()->GetService() != nullptr) {
366             napi_value serviceUuid;
367             napi_create_string_utf8(env, descriptor.GetCharacteristic()->GetService()->GetUuid().ToString().c_str(),
368                 NAPI_AUTO_LENGTH, &serviceUuid);
369             napi_set_named_property(env, result, "serviceUuid", serviceUuid);
370         }
371     }
372 }
373 
SetGattClientDeviceId(const std::string & deviceId)374 void SetGattClientDeviceId(const std::string &deviceId)
375 {
376     deviceAddr = deviceId;
377 }
378 
GetGattClientDeviceId()379 std::string GetGattClientDeviceId()
380 {
381     return deviceAddr;
382 }
383 
ToNapiValue(napi_env env) const384 napi_value NapiNativeBleCharacteristic::ToNapiValue(napi_env env) const
385 {
386     napi_value object;
387     napi_create_object(env, &object);
388     ConvertBLECharacteristicToJS(env, object, const_cast<GattCharacteristic &>(character_));
389     return object;
390 }
391 
ToNapiValue(napi_env env) const392 napi_value NapiNativeBleDescriptor::ToNapiValue(napi_env env) const
393 {
394     napi_value object;
395     napi_create_object(env, &object);
396     ConvertBLEDescriptorToJS(env, object, const_cast<GattDescriptor &>(descriptor_));
397     return object;
398 }
399 
ToNapiValue(napi_env env) const400 napi_value NapiNativeGattServiceArray::ToNapiValue(napi_env env) const
401 {
402     napi_value object;
403     napi_create_array(env, &object);
404     ConvertGattServiceVectorToJS(env, object, const_cast<vector<GattService> &>(gattServices_));
405     return object;
406 }
407 }  // namespace Bluetooth
408 }  // namespace OHOS
409