1 /*
2 * Copyright (c) 2022 Chipsea Technologies (Shenzhen) Corp., 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 "medical_js.h"
16
17 #include <cstdio>
18 #include <cstdlib>
19 #include <cstring>
20 #include <map>
21 #include <pthread.h>
22 #include <string>
23 #include <thread>
24 #include <unistd.h>
25
26 #include "hilog/log.h"
27 #include "napi/native_api.h"
28 #include "napi/native_node_api.h"
29 #include "medical_native_impl.h"
30 #include "medical_napi_utils.h"
31
32 #include "refbase.h"
33 #include "securec.h"
34
35 using namespace OHOS::HiviewDFX;
36 static constexpr HiLogLabel LABEL = {LOG_CORE, 0xD002786, "AfeJsAPI"};
37
38 static std::map<int32_t, struct AsyncCallbackInfo*> g_onCallbackInfos;
39
DataCallbackImpl(SensorEvent * event)40 static void DataCallbackImpl(SensorEvent *event)
41 {
42 HiLog::Info(LABEL, "%{public}s in", __func__);
43 if (event == nullptr) {
44 HiLog::Error(LABEL, "%{public}s event is null!", __func__);
45 return;
46 }
47 int32_t sensorTypeId = event->sensorTypeId;
48 uint32_t *data = (uint32_t *)(event->data);
49 uint32_t maxDataLen = MAX_DATA_LEN * sizeof(uint32_t);
50 uint32_t dataLen = (event->dataLen > maxDataLen) ? maxDataLen : event->dataLen;
51 // check sensorType
52 if (g_onCallbackInfos.find(sensorTypeId) == g_onCallbackInfos.end()) {
53 HiLog::Debug(LABEL, "%{public}s no subscribe to the sensor data on", __func__);
54 return;
55 }
56 struct AsyncCallbackInfo *onCallbackInfo = g_onCallbackInfos[sensorTypeId];
57 onCallbackInfo->sensorTypeId = sensorTypeId;
58 onCallbackInfo->sensorDataLength = dataLen / sizeof(uint32_t);
59 if (memcpy_s(onCallbackInfo->sensorData, dataLen, data, dataLen) != EOK) {
60 HiLog::Error(LABEL, "%{public}s copy data failed", __func__);
61 return;
62 }
63
64 EmitUvEventLoop((struct AsyncCallbackInfo *)(onCallbackInfo));
65 HiLog::Info(LABEL, "%{public}s end", __func__);
66 }
67
68 static const MedicalSensorUser user = {
69 .callback = DataCallbackImpl
70 };
71
UnsubscribeSensor(int32_t sensorTypeId)72 static int32_t UnsubscribeSensor(int32_t sensorTypeId)
73 {
74 HiLog::Info(LABEL, "%{public}s in", __func__);
75 int32_t ret = DeactivateSensor(sensorTypeId, &user);
76 if (ret < 0) {
77 HiLog::Error(LABEL, "%{public}s DeactivateSensor failed", __func__);
78 return ret;
79 }
80 ret = UnsubscribeSensor(sensorTypeId, &user);
81 if (ret < 0) {
82 HiLog::Error(LABEL, "%{public}s UnsubscribeSensor failed", __func__);
83 return ret;
84 }
85 HiLog::Info(LABEL, "%{public}s left", __func__);
86 return 0;
87 }
88
SubscribeSensor(int32_t sensorTypeId,int64_t interval,const MedicalSensorUser * user)89 static int32_t SubscribeSensor(int32_t sensorTypeId, int64_t interval, const MedicalSensorUser *user)
90 {
91 HiLog::Info(LABEL, "%{public}s in, sensorTypeId: %{public}d", __func__, sensorTypeId);
92 int32_t ret = SubscribeSensor(sensorTypeId, user);
93 if (ret < 0) {
94 HiLog::Error(LABEL, "%{public}s subscribeSensor failed", __func__);
95 return ret;
96 }
97 ret = SetBatch(sensorTypeId, user, interval, 0);
98 if (ret < 0) {
99 HiLog::Error(LABEL, "%{public}s set batch failed", __func__);
100 return ret;
101 }
102 ret = ActivateSensor(sensorTypeId, user);
103 if (ret < 0) {
104 HiLog::Error(LABEL, "%{public}s activateSensor failed", __func__);
105 return ret;
106 }
107 return 0;
108 }
109
On(napi_env env,napi_callback_info info)110 static napi_value On(napi_env env, napi_callback_info info)
111 {
112 HiLog::Info(LABEL, "%{public}s in", __func__);
113 size_t requiredMaxArgc = 3;
114 size_t requiredMinArgc = 2;
115 size_t argc = 3;
116 napi_value args[3];
117 napi_value thisVar;
118 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, NULL));
119 NAPI_ASSERT(env, ((argc >= requiredMinArgc) && (argc <= requiredMaxArgc)), "requires 2 or 3 parameteres");
120
121 napi_valuetype eventId = napi_undefined;
122 napi_typeof(env, args[0], &eventId);
123 NAPI_ASSERT(env, eventId == napi_number, "type mismatch for parameter 1");
124 int32_t sensorTypeId = GetCppInt32(args[0], env);
125
126 napi_valuetype handler = napi_undefined;
127 napi_typeof(env, args[1], &handler);
128 NAPI_ASSERT(env, handler == napi_function, "type mismatch for parameter 2");
129
130 int64_t interval = 200000000;
131 if (argc == requiredMaxArgc) {
132 HiLog::Info(LABEL, "%{public}s argc = 3!", __func__);
133 napi_value value = NapiGetNamedProperty(args[2], "interval", env);
134 napi_valuetype intervalType = napi_undefined;
135 napi_typeof(env, value, &intervalType);
136 NAPI_ASSERT(env, intervalType == napi_number, "type mismatch for parameter 3");
137 interval = GetCppInt64(value, env);
138 }
139 AsyncCallbackInfo *asyncCallbackInfo = new AsyncCallbackInfo {
140 .env = env,
141 .asyncWork = nullptr,
142 .deferred = nullptr,
143 };
144 napi_create_reference(env, args[1], 1, &asyncCallbackInfo->callback[0]);
145 g_onCallbackInfos[sensorTypeId] = asyncCallbackInfo;
146 int32_t ret = SubscribeSensor(sensorTypeId, interval, &user);
147 if (ret < 0) {
148 HiLog::Error(LABEL, "%{public}s subscribeSensor failed", __func__);
149 EmitAsyncCallbackWork(asyncCallbackInfo);
150 g_onCallbackInfos.erase(sensorTypeId);
151 return nullptr;
152 }
153 HiLog::Info(LABEL, "%{public}s out", __func__);
154 return nullptr;
155 }
156
Off(napi_env env,napi_callback_info info)157 static napi_value Off(napi_env env, napi_callback_info info)
158 {
159 HiLog::Info(LABEL, "%{public}s in", __func__);
160 size_t argc = 2;
161 size_t requiredMaxArgc = 2;
162 size_t requiredMinArgc = 1;
163 napi_value args[2];
164 napi_value thisVar;
165 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, NULL));
166 NAPI_ASSERT(env, ((argc >= requiredMinArgc) && (argc <= requiredMaxArgc)), "requires 1 or 2 parameteres");
167
168 napi_valuetype eventId = napi_undefined;
169 napi_typeof(env, args[0], &eventId);
170 NAPI_ASSERT(env, eventId == napi_number, "type mismatch for parameter 1");
171 int32_t sensorTypeId = GetCppInt32(args[0], env);
172
173 AsyncCallbackInfo *asyncCallbackInfo = new AsyncCallbackInfo {
174 .env = env,
175 .asyncWork = nullptr,
176 .deferred = nullptr,
177 };
178
179 if (argc == requiredMaxArgc) {
180 napi_valuetype handler = napi_undefined;
181 napi_typeof(env, args[1], &handler);
182 NAPI_ASSERT(env, handler == napi_function, "type mismatch for parameter 2");
183 } else {
184 NAPI_ASSERT(env, g_onCallbackInfos.find(sensorTypeId) != g_onCallbackInfos.end(), "no callback registered");
185 napi_get_reference_value(env, g_onCallbackInfos[sensorTypeId]->callback[0], &args[1]);
186 }
187 napi_create_reference(env, args[1], 1, &asyncCallbackInfo->callback[0]);
188
189 int32_t ret = UnsubscribeSensor(sensorTypeId);
190 if (ret < 0) {
191 HiLog::Error(LABEL, "%{public}s UnsubscribeSensor failed", __func__);
192 } else {
193 HiLog::Error(LABEL, "%{public}s UnsubscribeSensor success", __func__);
194 if (g_onCallbackInfos.find(sensorTypeId) != g_onCallbackInfos.end()) {
195 napi_delete_reference(env, g_onCallbackInfos[sensorTypeId]->callback[0]);
196 delete g_onCallbackInfos[sensorTypeId];
197 g_onCallbackInfos[sensorTypeId] = nullptr;
198 g_onCallbackInfos.erase(sensorTypeId);
199 }
200 }
201 EmitAsyncCallbackWork(asyncCallbackInfo);
202 HiLog::Info(LABEL, "%{public}s left", __func__);
203 return nullptr;
204 }
205
SetOpt(napi_env env,napi_callback_info info)206 static napi_value SetOpt(napi_env env, napi_callback_info info)
207 {
208 HiLog::Info(LABEL, "%{public}s in", __func__);
209 size_t argc = 2;
210 napi_value args[2];
211 napi_value thisVar;
212 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, NULL));
213
214 if (argc < 1) {
215 HiLog::Error(LABEL, "%{public}s Invalid input.", __func__);
216 return nullptr;
217 }
218 if (!IsMatchType(args[0], napi_number, env)) {
219 HiLog::Error(LABEL, "%{public}s argument should be number type!", __func__);
220 return nullptr;
221 }
222 int32_t sensorTypeId = GetCppInt32(args[0], env);
223
224 if (!IsMatchType(args[1], napi_number, env)) {
225 HiLog::Error(LABEL, "%{public}s argument should be function type!", __func__);
226 return nullptr;
227 }
228 int32_t opt = GetCppInt32(args[1], env);
229
230 int32_t ret = SetOption(sensorTypeId, &user, opt);
231 if (ret < 0) {
232 HiLog::Error(LABEL, "%{public}s SetOption failed", __func__);
233 } else {
234 HiLog::Error(LABEL, "%{public}s SetOption success", __func__);
235 }
236 HiLog::Info(LABEL, "%{public}s left", __func__);
237 return nullptr;
238 }
239
EnumClassConstructor(napi_env env,napi_callback_info info)240 static napi_value EnumClassConstructor(napi_env env, napi_callback_info info)
241 {
242 size_t argc = 0;
243 napi_value args[1] = {0};
244 napi_value res = nullptr;
245 void *data = nullptr;
246 napi_status status = napi_get_cb_info(env, info, &argc, args, &res, &data);
247 if (status != napi_ok) {
248 return nullptr;
249 }
250 return res;
251 }
252
CreateEnumMdicalSensorType(napi_env env,napi_value exports)253 static napi_value CreateEnumMdicalSensorType(napi_env env, napi_value exports)
254 {
255 napi_property_descriptor desc[] = {
256 DECLARE_NAPI_STATIC_PROPERTY("TYPE_ID_PHOTOPLETHYSMOGRAPH", GetNapiInt32(TYPE_ID_PHOTOPLETHYSMOGRAPH, env)),
257 };
258 napi_value result = nullptr;
259 napi_define_class(env, "MedicalSensorType", NAPI_AUTO_LENGTH, EnumClassConstructor, nullptr,
260 sizeof(desc) / sizeof(*desc), desc, &result);
261 napi_set_named_property(env, exports, "MedicalSensorType", result);
262 return exports;
263 }
264
265 EXTERN_C_START
266
Init(napi_env env,napi_value exports)267 static napi_value Init(napi_env env, napi_value exports)
268 {
269 napi_property_descriptor desc[] = {
270 DECLARE_NAPI_FUNCTION("on", On),
271 DECLARE_NAPI_FUNCTION("setOpt", SetOpt),
272 DECLARE_NAPI_FUNCTION("off", Off)
273 };
274 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc));
275 CreateEnumMdicalSensorType(env, exports);
276 return exports;
277 }
278 EXTERN_C_END
279
280 static napi_module _module = {
281 .nm_version = 1,
282 .nm_flags = 0,
283 .nm_filename = NULL,
284 .nm_register_func = Init,
285 .nm_modname = "medical",
286 .nm_priv = ((void *)0),
287 .reserved = {0}
288 };
289
RegisterModule(void)290 extern "C" __attribute__((constructor)) void RegisterModule(void)
291 {
292 napi_module_register(&_module);
293 }
294