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