1 /*
2 * Copyright (C) 2021-2022 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 #include "napi_bluetooth_gatt_server.h"
16 #include "bluetooth_gatt_service.h"
17 #include "bluetooth_host.h"
18 #include "bluetooth_log.h"
19 #include "napi_bluetooth_ble.h"
20 #include "napi_bluetooth_gatt_server.h"
21 #include "napi_bluetooth_utils.h"
22
23 namespace OHOS {
24 namespace Bluetooth {
25 using namespace std;
26
27 std::vector<std::string> NapiGattServer::deviceList;
28 thread_local napi_ref NapiGattServer::consRef_ = nullptr;
29
CreateGattServer(napi_env env,napi_callback_info info)30 napi_value NapiGattServer::CreateGattServer(napi_env env, napi_callback_info info)
31 {
32 HILOGI("CreateGattServer called");
33 napi_value result;
34 napi_value constructor = nullptr;
35 napi_get_reference_value(env, consRef_, &constructor);
36 napi_new_instance(env, constructor, 0, nullptr, &result);
37
38 HILOGI("CreateGattServer finished");
39 return result;
40 }
41
DefineGattServerJSClass(napi_env env)42 void NapiGattServer::DefineGattServerJSClass(napi_env env)
43 {
44 napi_property_descriptor gattserverDesc[] = {
45 DECLARE_NAPI_FUNCTION("startAdvertising", StartAdvertising),
46 DECLARE_NAPI_FUNCTION("stopAdvertising", StopAdvertising),
47 DECLARE_NAPI_FUNCTION("addService", AddService),
48 DECLARE_NAPI_FUNCTION("removeService", RemoveGattService),
49 DECLARE_NAPI_FUNCTION("close", Close),
50 DECLARE_NAPI_FUNCTION("notifyCharacteristicChanged", NotifyCharacteristicChanged),
51 DECLARE_NAPI_FUNCTION("sendResponse", SendResponse),
52 DECLARE_NAPI_FUNCTION("on", On),
53 DECLARE_NAPI_FUNCTION("off", Off),
54 };
55
56 napi_value constructor = nullptr;
57 napi_define_class(env, "GattServer", NAPI_AUTO_LENGTH, GattServerConstructor, nullptr,
58 sizeof(gattserverDesc) / sizeof(gattserverDesc[0]), gattserverDesc, &constructor);
59 napi_create_reference(env, constructor, 1, &consRef_);
60 }
61
GattServerConstructor(napi_env env,napi_callback_info info)62 napi_value NapiGattServer::GattServerConstructor(napi_env env, napi_callback_info info)
63 {
64 napi_value thisVar = nullptr;
65 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
66 NapiGattServer* gattServer = new NapiGattServer();
67
68 napi_wrap(
69 env, thisVar, gattServer,
70 [](napi_env env, void* data, void* hint) {
71 NapiGattServer* server = (NapiGattServer*)data;
72 delete server;
73 },
74 nullptr,
75 nullptr);
76
77 return thisVar;
78 }
79
On(napi_env env,napi_callback_info info)80 napi_value NapiGattServer::On(napi_env env, napi_callback_info info)
81 {
82 HILOGI("RegisterGattServerCallback called");
83 NapiGattServer *gattServer = nullptr;
84 size_t expectedArgsCount = ARGS_SIZE_TWO;
85 size_t argc = expectedArgsCount;
86 napi_value argv[ARGS_SIZE_TWO] = {0};
87 napi_value thisVar = nullptr;
88
89 napi_value ret = nullptr;
90 napi_get_undefined(env, &ret);
91
92 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
93 if (argc != expectedArgsCount) {
94 HILOGE("Requires 2 arguments.");
95 return ret;
96 }
97 string type;
98 ParseString(env, type, argv[PARAM0]);
99 std::shared_ptr<BluetoothCallbackInfo> callbackInfo ;
100
101 if (type.c_str() == STR_BT_GATT_SERVER_CALLBACK_CHARACTERISTIC_READ ||
102 type.c_str() == STR_BT_GATT_SERVER_CALLBACK_CHARACTERISTIC_WRITE) {
103 callbackInfo = std::make_shared<GattCharacteristicCallbackInfo>();
104 } else if (type.c_str() == STR_BT_GATT_SERVER_CALLBACK_DESCRIPTOR_WRITE ||
105 type.c_str() == STR_BT_GATT_SERVER_CALLBACK_DESCRIPTOR_READ){
106 callbackInfo = std::make_shared<GattDescriptorCallbackInfo>();
107 } else {
108 callbackInfo = std::make_shared<BluetoothCallbackInfo>();
109 }
110 callbackInfo->env_ = env;
111
112 napi_unwrap(env, thisVar, (void **)&gattServer);
113 napi_valuetype valueType = napi_undefined;
114 napi_typeof(env, argv[PARAM1], &valueType);
115 if (valueType != napi_function) {
116 HILOGE("Wrong argument type. Function expected.");
117 return ret;
118 }
119 napi_create_reference(env, argv[PARAM1], 1, &callbackInfo->callback_);
120 gattServer->GetCallback().SetCallbackInfo(type, callbackInfo);
121
122 HILOGI("%{public}s is registered", type.c_str());
123
124 return ret;
125 }
126
Off(napi_env env,napi_callback_info info)127 napi_value NapiGattServer::Off(napi_env env, napi_callback_info info)
128 {
129 HILOGI("DeregisterGattServerCallback called");
130 NapiGattServer *GattServer = nullptr;
131 size_t expectedArgsCount = ARGS_SIZE_ONE;
132 size_t argc = expectedArgsCount;
133 napi_value argv[ARGS_SIZE_ONE] = {0};
134 napi_value thisVar = nullptr;
135
136 napi_value ret = nullptr;
137 napi_get_undefined(env, &ret);
138
139 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
140 if (argc != expectedArgsCount) {
141 HILOGE("Requires 1 argument.");
142 return ret;
143 }
144 string type;
145 ParseString(env, type, argv[PARAM0]);
146
147 napi_unwrap(env, thisVar, (void **)&GattServer);
148 GattServer->GetCallback().SetCallbackInfo(type, nullptr);
149
150 return ret;
151 }
152
AddService(napi_env env,napi_callback_info info)153 napi_value NapiGattServer::AddService(napi_env env, napi_callback_info info)
154 {
155 HILOGI("AddService called");
156 NapiGattServer *gattServer = nullptr;
157 size_t expectedArgsCount = ARGS_SIZE_ONE;
158 size_t argc = expectedArgsCount;
159 napi_value argv[ARGS_SIZE_ONE] = {0};
160 napi_value thisVar = nullptr;
161 bool isOK = false;
162 napi_value ret = nullptr;
163 napi_get_boolean(env, isOK, &ret);
164
165 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
166 if (argc != expectedArgsCount) {
167 HILOGE("Requires 1 argument.");
168 return ret;
169 }
170 GattService* gattService = GetServiceFromJS(env, argv[PARAM0], nullptr, nullptr);
171
172 napi_unwrap(env, thisVar, (void**)&gattServer);
173 if (gattServer->GetServer()->AddService(*gattService) == GattStatus::GATT_SUCCESS) {
174 isOK = true;
175 }
176 delete gattService;
177
178 napi_get_boolean(env, isOK, &ret);
179 return ret;
180 }
181
Close(napi_env env,napi_callback_info info)182 napi_value NapiGattServer::Close(napi_env env, napi_callback_info info)
183 {
184 HILOGI("Close called");
185 NapiGattServer* gattServer = nullptr;
186 bool isOK = true;
187 napi_value thisVar = nullptr;
188
189 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
190 napi_unwrap(env, thisVar, (void**)&gattServer);
191
192 delete gattServer;
193
194 napi_value ret = nullptr;
195 napi_get_boolean(env, isOK, &ret);
196 return ret;
197 }
198
RemoveGattService(napi_env env,napi_callback_info info)199 napi_value NapiGattServer::RemoveGattService(napi_env env, napi_callback_info info)
200 {
201 HILOGI("RemoveGattService called");
202 NapiGattServer* gattServer = nullptr;
203 size_t expectedArgsCount = ARGS_SIZE_ONE;
204 size_t argc = expectedArgsCount;
205 napi_value argv[ARGS_SIZE_ONE] = {0};
206 napi_value thisVar = nullptr;
207 std::string uuid;
208 bool isOK = false;
209
210 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
211 NAPI_ASSERT(env, argc == expectedArgsCount, "Requires 1 arguments.");
212 ParseString(env, uuid, argv[PARAM0]);
213
214 napi_unwrap(env, thisVar, (void**)&gattServer);
215 UUID serviceUuid = UUID::FromString(uuid);
216
217 std::optional<std::reference_wrapper<GattService>> gattService =
218 gattServer->GetServer()->GetService(serviceUuid, true);
219 if (gattService != std::nullopt) {
220 if (gattServer->GetServer()->RemoveGattService(*gattService) == GattStatus::GATT_SUCCESS) {
221 isOK = true;
222 }
223 }
224 gattService = gattServer->GetServer()->GetService(serviceUuid, false);
225 if (gattService != std::nullopt) {
226 if (gattServer->GetServer()->RemoveGattService(*gattService) == GattStatus::GATT_SUCCESS) {
227 isOK = true;
228 }
229 }
230
231 napi_value ret = nullptr;
232 napi_get_boolean(env, isOK, &ret);
233 return ret;
234 }
235
SendResponse(napi_env env,napi_callback_info info)236 napi_value NapiGattServer::SendResponse(napi_env env, napi_callback_info info)
237 {
238 NapiGattServer* gattServer = nullptr;
239 size_t expectedArgsCount = ARGS_SIZE_ONE;
240 size_t argc = expectedArgsCount;
241 napi_value argv[ARGS_SIZE_ONE] = {0};
242 napi_value thisVar = nullptr;
243 bool isOK = false;
244
245 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
246 NAPI_ASSERT(env, argc == expectedArgsCount, "Requires 1 arguments.");
247
248 ServerResponse serverresponse = GetServerResponseFromJS(env, argv[PARAM0]);
249 napi_unwrap(env, thisVar, (void**)&gattServer);
250 BluetoothRemoteDevice remoteDevice =
251 BluetoothHost::GetDefaultHost().GetRemoteDevice(serverresponse.deviceId, 1);
252 if (gattServer->GetServer()->SendResponse(
253 remoteDevice, serverresponse.transId,
254 serverresponse.status,
255 serverresponse.offset,
256 serverresponse.value,
257 serverresponse.length) == GattStatus::GATT_SUCCESS) {
258 isOK = true;
259 }
260
261 napi_value ret = nullptr;
262 napi_get_boolean(env, isOK, &ret);
263 return ret;
264 }
265
NotifyCharacteristicChanged(napi_env env,napi_callback_info info)266 napi_value NapiGattServer::NotifyCharacteristicChanged(napi_env env, napi_callback_info info)
267 {
268 HILOGI("NotifyCharacteristicChanged called");
269 NapiGattServer* gattServer = nullptr;
270 size_t expectedArgsCount = ARGS_SIZE_TWO;
271 size_t argc = expectedArgsCount;
272 std::string deviceID;
273 napi_value argv[ARGS_SIZE_TWO] = {0, 0};
274 napi_value thisVar = nullptr;
275 bool isOK = false;
276 napi_value ret = nullptr;
277 napi_get_boolean(env, isOK, &ret);
278
279 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
280 if (argc != expectedArgsCount) {
281 HILOGE("Requires 2 argument.");
282 return ret;
283 }
284 napi_unwrap(env, thisVar, (void**)&gattServer);
285 ParseString(env, deviceID, argv[PARAM0]);
286 BluetoothRemoteDevice remoteDevice = BluetoothHost::GetDefaultHost().GetRemoteDevice(deviceID, 1);
287 GattCharacteristic* characteristic = GetCharacteristicFromJS(env, argv[PARAM1], gattServer->GetServer(), nullptr);
288
289 if (characteristic == nullptr) {
290 HILOGI("characteristic is nullptr");
291 return ret;
292 }
293 if (gattServer->GetServer()->NotifyCharacteristicChanged(
294 remoteDevice, *characteristic, true) == GattStatus::GATT_SUCCESS) {
295 isOK = true;
296 }
297
298 napi_get_boolean(env, isOK, &ret);
299 return ret;
300 }
301 } // namespace Bluetooth
302 } // namespace OHOS
303