• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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