1 /*
2 * Copyright (c) 20212 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 "sensor_napi_utils.h"
17
18 #include <map>
19 #include <string>
20 #include <vector>
21
22 namespace OHOS {
23 namespace Sensors {
24 namespace {
25 constexpr int32_t STRING_LENGTH_MAX = 64;
26 }
IsSameValue(const napi_env & env,const napi_value & lhs,const napi_value & rhs)27 bool IsSameValue(const napi_env &env, const napi_value &lhs, const napi_value &rhs)
28 {
29 CALL_LOG_ENTER;
30 bool result = false;
31 CHKNRF(env, napi_strict_equals(env, lhs, rhs, &result), "napi_strict_equals");
32 return result;
33 }
34
IsMatchType(const napi_env & env,const napi_value & value,const napi_valuetype & type)35 bool IsMatchType(const napi_env &env, const napi_value &value, const napi_valuetype &type)
36 {
37 CALL_LOG_ENTER;
38 napi_valuetype paramType = napi_undefined;
39 CHKNRF(env, napi_typeof(env, value, ¶mType), "napi_typeof");
40 return paramType == type;
41 }
42
IsMatchArrayType(const napi_env & env,const napi_value & value)43 bool IsMatchArrayType(const napi_env &env, const napi_value &value)
44 {
45 CALL_LOG_ENTER;
46 bool result = false;
47 CHKNRF(env, napi_is_array(env, value, &result), "napi_is_array");
48 return result;
49 }
50
GetFloatArray(const napi_env & env,const napi_value & value,vector<float> & array)51 bool GetFloatArray(const napi_env &env, const napi_value &value, vector<float> &array)
52 {
53 CALL_LOG_ENTER;
54 uint32_t arrayLength = 0;
55 CHKNRF(env, napi_get_array_length(env, value, &arrayLength), "napi_get_array_length");
56 for (size_t i = 0; i < arrayLength; ++i) {
57 napi_value element = nullptr;
58 CHKNRF(env, napi_get_element(env, value, i, &element), "napi_get_element");
59 CHKNCF(env, IsMatchType(env, element, napi_number), "Wrong argument type. Number or function expected");
60 double value = 0;
61 CHKNCF(env, GetCppDouble(env, element, value), "Wrong argument type. get double fail");
62 array.push_back(static_cast<float>(value));
63 }
64 return true;
65 }
66
GetNamedProperty(const napi_env & env,const napi_value & object,string name)67 napi_value GetNamedProperty(const napi_env &env, const napi_value &object, string name)
68 {
69 CALL_LOG_ENTER;
70 bool status = false;
71 CHKNRP(env, napi_has_named_property(env, object, name.c_str(), &status), "napi_has_named_property");
72 if (!status) {
73 SEN_HILOGW("%{public}s not exists on the object", name.c_str());
74 return nullptr;
75 }
76 napi_value value = nullptr;
77 CHKNRP(env, napi_get_named_property(env, object, name.c_str(), &value),
78 "napi_get_named_property");
79 return value;
80 }
81
GetCppDouble(const napi_env & env,const napi_value & value,double & number)82 bool GetCppDouble(const napi_env &env, const napi_value &value, double &number)
83 {
84 CALL_LOG_ENTER;
85 CHKNRF(env, napi_get_value_double(env, value, &number), "napi_get_value_double");
86 return true;
87 }
88
GetCppFloat(const napi_env & env,const napi_value & value,float & number)89 bool GetCppFloat(const napi_env &env, const napi_value &value, float &number)
90 {
91 CALL_LOG_ENTER;
92 double result = 0;
93 CHKNCF(env, GetCppDouble(env, value, result), "Get cpp double fail");
94 number = static_cast<float>(result);
95 return true;
96 }
97
GetCppInt32(const napi_env & env,const napi_value & value,int32_t & number)98 bool GetCppInt32(const napi_env &env, const napi_value &value, int32_t &number)
99 {
100 CALL_LOG_ENTER;
101 CHKNRF(env, napi_get_value_int32(env, value, &number), "napi_get_value_int32");
102 return true;
103 }
104
GetCppInt64(const napi_env & env,const napi_value & value,int64_t & number)105 bool GetCppInt64(const napi_env &env, const napi_value &value, int64_t &number)
106 {
107 CALL_LOG_ENTER;
108 CHKNRF(env, napi_get_value_int64(env, value, &number), "napi_get_value_int64");
109 return true;
110 }
111
GetCppBool(const napi_env & env,const napi_value & value)112 bool GetCppBool(const napi_env &env, const napi_value &value)
113 {
114 CALL_LOG_ENTER;
115 bool number = false;
116 CHKNRF(env, napi_get_value_bool(env, value, &number), "napi_get_value_bool");
117 return number;
118 }
119
GetNapiInt32(const napi_env & env,int32_t number)120 napi_value GetNapiInt32(const napi_env &env, int32_t number)
121 {
122 napi_value value = nullptr;
123 CHKNRP(env, napi_create_int32(env, number, &value), "napi_create_int32");
124 return value;
125 }
126
GetStringValue(const napi_env & env,const napi_value & value,string & result)127 bool GetStringValue(const napi_env &env, const napi_value &value, string &result)
128 {
129 CALL_LOG_ENTER;
130 CHKNCF(env, IsMatchType(env, value, napi_string), "Wrong argument type. String or function expected");
131 char buf[STRING_LENGTH_MAX] = { 0 };
132 size_t copyLength = 0;
133 CHKNRF(env, napi_get_value_string_utf8(env, value, buf, STRING_LENGTH_MAX, ©Length),
134 "napi_get_value_string_utf8");
135 result = std::string(buf);
136 return true;
137 }
138
RegisterNapiCallback(const napi_env & env,const napi_value & value,napi_ref & callback)139 bool RegisterNapiCallback(const napi_env &env, const napi_value &value,
140 napi_ref &callback)
141 {
142 CHKNCF(env, IsMatchType(env, value, napi_function), "Wrong argument type, should be function");
143 CHKNRF(env, napi_create_reference(env, value, 1, &callback), "napi_create_reference");
144 return true;
145 }
146
CreateFailMessage(CallbackDataType type,int32_t code,string message,sptr<AsyncCallbackInfo> & asyncCallbackInfo)147 bool CreateFailMessage(CallbackDataType type, int32_t code, string message,
148 sptr<AsyncCallbackInfo> &asyncCallbackInfo)
149 {
150 CHKPF(asyncCallbackInfo);
151 asyncCallbackInfo->type = type;
152 asyncCallbackInfo->error.code = code;
153 asyncCallbackInfo->error.message = message;
154 return true;
155 }
156
157 std::map<int32_t, vector<string>> g_sensorAttributeList = {
158 { 0, { "x" } },
159 { SENSOR_TYPE_ID_ACCELEROMETER, { "x", "y", "z" } },
160 { SENSOR_TYPE_ID_GYROSCOPE, { "x", "y", "z" } },
161 { SENSOR_TYPE_ID_AMBIENT_LIGHT, { "intensity" } },
162 { SENSOR_TYPE_ID_MAGNETIC_FIELD, { "x", "y", "z" } },
163 { SENSOR_TYPE_ID_BAROMETER, { "pressure" } },
164 { SENSOR_TYPE_ID_HALL, { "status" } },
165 { SENSOR_TYPE_ID_PROXIMITY, { "distance" } },
166 { SENSOR_TYPE_ID_HUMIDITY, { "humidity" } },
167 { SENSOR_TYPE_ID_ORIENTATION, { "alpha", "beta", "gamma" } },
168 { SENSOR_TYPE_ID_GRAVITY, { "x", "y", "z" } },
169 { SENSOR_TYPE_ID_LINEAR_ACCELERATION, { "x", "y", "z" } },
170 { SENSOR_TYPE_ID_ROTATION_VECTOR, { "x", "y", "z", "w" } },
171 { SENSOR_TYPE_ID_AMBIENT_TEMPERATURE, { "temperature" } },
172 { SENSOR_TYPE_ID_MAGNETIC_FIELD_UNCALIBRATED, { "x", "y", "z", "biasX", "biasY", "biasZ" } },
173 { SENSOR_TYPE_ID_GYROSCOPE_UNCALIBRATED, { "x", "y", "z", "biasX", "biasY", "biasZ" } },
174 { SENSOR_TYPE_ID_SIGNIFICANT_MOTION, { "scalar" } },
175 { SENSOR_TYPE_ID_PEDOMETER_DETECTION, { "scalar" } },
176 { SENSOR_TYPE_ID_PEDOMETER, { "steps" } },
177 { SENSOR_TYPE_ID_HEART_RATE, { "heartRate" } },
178 { SENSOR_TYPE_ID_WEAR_DETECTION, { "value" } },
179 { SENSOR_TYPE_ID_ACCELEROMETER_UNCALIBRATED, { "x", "y", "z", "biasX", "biasY", "biasZ" } }
180 };
181
182 std::map<int32_t, ConvertDataFunc> g_convertfuncList = {
183 {FAIL, ConvertToFailData},
184 {ON_CALLBACK, ConvertToSensorData},
185 {ONCE_CALLBACK, ConvertToSensorData},
186 {GET_GEOMAGNETIC_FIELD, ConvertToGeomagneticData},
187 {GET_ALTITUDE, ConvertToNumber},
188 {GET_GEOMAGNITIC_DIP, ConvertToNumber},
189 {GET_ANGLE_MODIFY, ConvertToArray},
190 {CREATE_ROTATION_MATRIX, ConvertToArray},
191 {TRANSFORM_COORDINATE_SYSTEM, ConvertToArray},
192 {CREATE_QUATERNION, ConvertToArray},
193 {GET_DIRECTION, ConvertToArray},
194 {ROTATION_INCLINATION_MATRIX, ConvertToRotationMatrix},
195 {GET_SENSOR_LIST, ConvertToSensorInfos},
196 {GET_SINGLE_SENSOR, ConvertToSingleSensor},
197 {GET_BODY_STATE, ConvertToBodyData},
198 {SUBSCRIBE_CALLBACK, ConvertToSensorData},
199 {SUBSCRIBE_COMPASS, ConvertToCompass},
200 };
201
getJsonObject(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value & result)202 bool getJsonObject(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value &result)
203 {
204 CHKPF(asyncCallbackInfo);
205 CHKNRF(env, napi_create_object(env, &result), "napi_create_object");
206 napi_value value = nullptr;
207 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.x, &value), "napi_create_double");
208 CHKNRF(env, napi_set_named_property(env, result, "x", value), "napi_set_named_property");
209
210 value = nullptr;
211 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.y, &value), "napi_create_double");
212 CHKNRF(env, napi_set_named_property(env, result, "y", value), "napi_set_named_property");
213
214 value = nullptr;
215 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.z, &value), "napi_create_double");
216 CHKNRF(env, napi_set_named_property(env, result, "z", value), "napi_set_named_property");
217
218 value = nullptr;
219 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.geomagneticDip, &value),
220 "napi_create_double");
221 CHKNRF(env, napi_set_named_property(env, result, "geomagneticDip", value), "napi_set_named_property");
222
223 value = nullptr;
224 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.deflectionAngle, &value),
225 "napi_create_double");
226 CHKNRF(env, napi_set_named_property(env, result, "deflectionAngle", value), "napi_set_named_property");
227
228 value = nullptr;
229 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.levelIntensity, &value),
230 "napi_create_double");
231 CHKNRF(env, napi_set_named_property(env, result, "levelIntensity", value), "napi_set_named_property");
232
233 value = nullptr;
234 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.totalIntensity, &value),
235 "napi_create_double");
236 CHKNRF(env, napi_set_named_property(env, result, "totalIntensity", value), "napi_set_named_property");
237 return true;
238 }
239
ConvertToSensorInfo(const napi_env & env,SensorInfo sensorInfo,napi_value & result)240 bool ConvertToSensorInfo(const napi_env &env, SensorInfo sensorInfo, napi_value &result)
241 {
242 CALL_LOG_ENTER;
243 CHKNRF(env, napi_create_object(env, &result), "napi_create_object");
244 napi_value value = nullptr;
245 CHKNRF(env, napi_create_string_latin1(env, sensorInfo.sensorName, NAPI_AUTO_LENGTH, &value),
246 "napi_create_string_latin1");
247 CHKNRF(env, napi_set_named_property(env, result, "sensorName", value), "napi_set_named_property");
248
249 value = nullptr;
250 CHKNRF(env, napi_create_string_latin1(env, sensorInfo.vendorName, NAPI_AUTO_LENGTH, &value),
251 "napi_create_string_latin1");
252 CHKNRF(env, napi_set_named_property(env, result, "vendorName", value), "napi_set_named_property");
253
254 value = nullptr;
255 CHKNRF(env, napi_create_string_latin1(env, sensorInfo.firmwareVersion, NAPI_AUTO_LENGTH, &value),
256 "napi_create_string_latin1");
257 CHKNRF(env, napi_set_named_property(env, result, "firmwareVersion", value), "napi_set_named_property");
258
259 value = nullptr;
260 CHKNRF(env, napi_create_string_latin1(env, sensorInfo.hardwareVersion, NAPI_AUTO_LENGTH, &value),
261 "napi_create_string_latin1");
262 CHKNRF(env, napi_set_named_property(env, result, "hardwareVersion", value), "napi_set_named_property");
263
264 value = nullptr;
265 CHKNRF(env, napi_create_double(env, sensorInfo.sensorTypeId, &value), "napi_create_double");
266 CHKNRF(env, napi_set_named_property(env, result, "sensorTypeId", value), "napi_set_named_property");
267
268 value = nullptr;
269 CHKNRF(env, napi_create_double(env, sensorInfo.maxRange, &value), "napi_create_double");
270 CHKNRF(env, napi_set_named_property(env, result, "maxRange", value), "napi_set_named_property");
271
272 value = nullptr;
273 CHKNRF(env, napi_create_double(env, sensorInfo.precision, &value), "napi_create_double");
274 CHKNRF(env, napi_set_named_property(env, result, "precision", value), "napi_set_named_property");
275
276 value = nullptr;
277 CHKNRF(env, napi_create_double(env, sensorInfo.power, &value), "napi_create_double");
278 CHKNRF(env, napi_set_named_property(env, result, "power", value), "napi_set_named_property");
279 return true;
280 }
281
ConvertToSingleSensor(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])282 bool ConvertToSingleSensor(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
283 {
284 CALL_LOG_ENTER;
285 CHKPF(asyncCallbackInfo);
286 return ConvertToSensorInfo(env, asyncCallbackInfo->sensorInfos[0], result[1]);
287 }
288
ConvertToSensorInfos(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])289 bool ConvertToSensorInfos(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
290 {
291 CALL_LOG_ENTER;
292 CHKPF(asyncCallbackInfo);
293 CHKNRF(env, napi_create_array(env, &result[1]), "napi_create_array");
294 auto sensorInfos = asyncCallbackInfo->sensorInfos;
295 for (uint32_t i = 0; i < sensorInfos.size(); ++i) {
296 napi_value value = nullptr;
297 CHKNCF(env, ConvertToSensorInfo(env, sensorInfos[i], value), "Convert sensor info fail");
298 CHKNRF(env, napi_set_element(env, result[1], i, value), "napi_set_element");
299 }
300 return true;
301 }
302
ConvertToFailData(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])303 bool ConvertToFailData(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
304 {
305 CALL_LOG_ENTER;
306 CHKPF(asyncCallbackInfo);
307 result[0] = GreateBusinessError(env, asyncCallbackInfo->error.code, asyncCallbackInfo->error.message,
308 asyncCallbackInfo->error.name, asyncCallbackInfo->error.stack);
309 CHKPF(result[0]);
310 return true;
311 }
312
ConvertToSensorData(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])313 bool ConvertToSensorData(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
314 {
315 CHKPF(asyncCallbackInfo);
316 int32_t sensorTypeId = asyncCallbackInfo->data.sensorData.sensorTypeId;
317 CHKNCF(env, (g_sensorAttributeList.find(sensorTypeId) != g_sensorAttributeList.end()), "Invalid sensor type");
318 if (sensorTypeId == SENSOR_TYPE_ID_WEAR_DETECTION && asyncCallbackInfo->type == SUBSCRIBE_CALLBACK) {
319 return ConvertToBodyData(env, asyncCallbackInfo, result);
320 }
321
322 size_t size = g_sensorAttributeList[sensorTypeId].size();
323 uint32_t dataLenth = asyncCallbackInfo->data.sensorData.dataLength / sizeof(float);
324 CHKNCF(env, (size <= dataLenth), "Data length mismatch");
325
326 CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object");
327 napi_value message = nullptr;
328 auto sensorAttributes = g_sensorAttributeList[sensorTypeId];
329 for (uint32_t i = 0; i < size; ++i) {
330 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.sensorData.data[i], &message),
331 "napi_create_double");
332 CHKNRF(env, napi_set_named_property(env, result[1], sensorAttributes[i].c_str(), message),
333 "napi_set_named_property");
334 message = nullptr;
335 }
336
337 CHKNRF(env, napi_create_int64(env, asyncCallbackInfo->data.sensorData.timestamp, &message),
338 "napi_create_int64");
339 CHKNRF(env, napi_set_named_property(env, result[1], "timestamp", message), "napi_set_named_property");
340 return true;
341 }
342
ConvertToGeomagneticData(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])343 bool ConvertToGeomagneticData(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
344 {
345 CALL_LOG_ENTER;
346 return getJsonObject(env, asyncCallbackInfo, result[1]);
347 }
348
ConvertToBodyData(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])349 bool ConvertToBodyData(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
350 {
351 CALL_LOG_ENTER;
352 CHKPF(asyncCallbackInfo);
353 CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object");
354 napi_value status = nullptr;
355 CHKNRF(env, napi_get_boolean(env, asyncCallbackInfo->data.sensorData.data[0], &status),
356 "napi_get_boolean");
357 CHKNRF(env, napi_set_named_property(env, result[1], "value", status), "napi_set_named_property");
358 return true;
359 }
360
ConvertToCompass(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])361 bool ConvertToCompass(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
362 {
363 CALL_LOG_ENTER;
364 CHKPF(asyncCallbackInfo);
365 CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object");
366 napi_value message = nullptr;
367 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.sensorData.data[0], &message),
368 "napi_create_double");
369 CHKNRF(env, napi_set_named_property(env, result[1], "direction", message), "napi_set_named_property");
370 return true;
371 }
372
ConvertToNumber(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])373 bool ConvertToNumber(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
374 {
375 CALL_LOG_ENTER;
376 CHKPF(asyncCallbackInfo);
377 napi_status status =
378 napi_create_double(env, static_cast<double>(asyncCallbackInfo->data.reserveData.reserve[0]), &result[1]);
379 CHKNRF(env, status, "napi_create_double");
380 return true;
381 }
382
ConvertToArray(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])383 bool ConvertToArray(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
384 {
385 CALL_LOG_ENTER;
386 CHKPF(asyncCallbackInfo);
387 bool ret = CreateNapiArray(env, asyncCallbackInfo->data.reserveData.reserve,
388 asyncCallbackInfo->data.reserveData.length, result[1]);
389 CHKNCF(env, ret, "Create napi array fail");
390 return true;
391 }
392
ConvertToRotationMatrix(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])393 bool ConvertToRotationMatrix(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
394 {
395 CALL_LOG_ENTER;
396 CHKPF(asyncCallbackInfo);
397 napi_value rotation = nullptr;
398 bool ret = CreateNapiArray(env, asyncCallbackInfo->data.rationMatrixData.rotationMatrix,
399 THREE_DIMENSIONAL_MATRIX_LENGTH, rotation);
400 CHKNCF(env, ret, "Create napi array rotation fail");
401
402 napi_value inclination = nullptr;
403 ret = CreateNapiArray(env, asyncCallbackInfo->data.rationMatrixData.inclinationMatrix,
404 THREE_DIMENSIONAL_MATRIX_LENGTH, inclination);
405 CHKNCF(env, ret, "Create napi array inclination fail");
406
407 CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object");
408 CHKNRF(env, napi_set_named_property(env, result[1], "rotation", rotation),
409 "napi_set_named_property");
410 CHKNRF(env, napi_set_named_property(env, result[1], "inclination", inclination),
411 "napi_set_named_property");
412 return true;
413 }
414
GreateBusinessError(const napi_env & env,int32_t errCode,string errMessage,string errName,string errStack)415 napi_value GreateBusinessError(const napi_env &env, int32_t errCode, string errMessage,
416 string errName, string errStack)
417 {
418 CALL_LOG_ENTER;
419 napi_value result = nullptr;
420 CHKNRP(env, napi_create_object(env, &result), "napi_create_object");
421 napi_value value = nullptr;
422 CHKNRP(env, napi_create_int32(env, errCode, &value), "napi_create_int32");
423 CHKNRP(env, napi_set_named_property(env, result, "code", value), "napi_set_named_property");
424
425 value = nullptr;
426 CHKNRP(env, napi_create_string_utf8(env, errMessage.data(), NAPI_AUTO_LENGTH, &value),
427 "napi_create_string_utf8");
428 CHKNRP(env, napi_set_named_property(env, result, "message", value), "napi_set_named_property");
429
430 value = nullptr;
431 CHKNRP(env, napi_create_string_utf8(env, errName.data(), NAPI_AUTO_LENGTH, &value),
432 "napi_create_string_utf8");
433 CHKNRP(env, napi_set_named_property(env, result, "name", value), "napi_set_named_property");
434
435 value = nullptr;
436 CHKNRP(env, napi_create_string_utf8(env, errStack.data(), NAPI_AUTO_LENGTH, &value),
437 "napi_create_string_utf8");
438 CHKNRP(env, napi_set_named_property(env, result, "stack", value), "napi_set_named_property");
439 return result;
440 }
441
CreateNapiArray(const napi_env & env,float data[],int32_t dataLength,napi_value & result)442 bool CreateNapiArray(const napi_env &env, float data[], int32_t dataLength, napi_value &result)
443 {
444 CHKNRF(env, napi_create_array(env, &result), "napi_create_array");
445 for (int32_t i = 0; i < dataLength; ++i) {
446 napi_value message = nullptr;
447 CHKNRF(env, napi_create_double(env, data[i], &message), "napi_create_double");
448 CHKNRF(env, napi_set_element(env, result, i, message), "napi_set_element");
449 }
450 return true;
451 }
452
EmitAsyncCallbackWork(sptr<AsyncCallbackInfo> asyncCallbackInfo)453 void EmitAsyncCallbackWork(sptr<AsyncCallbackInfo> asyncCallbackInfo)
454 {
455 CALL_LOG_ENTER;
456 CHKPV(asyncCallbackInfo);
457 napi_value resourceName = nullptr;
458 CHKNRV(asyncCallbackInfo->env, napi_create_string_utf8(asyncCallbackInfo->env, "AsyncCallback",
459 NAPI_AUTO_LENGTH, &resourceName), "napi_create_string_utf8");
460 asyncCallbackInfo->IncStrongRef(nullptr);
461 napi_status status = napi_create_async_work(asyncCallbackInfo->env, nullptr, resourceName,
462 [](napi_env env, void* data) {},
463 [](napi_env env, napi_status status, void* data) {
464 CALL_LOG_ENTER;
465 sptr<AsyncCallbackInfo> asyncCallbackInfo(static_cast<AsyncCallbackInfo *>(data));
466 /**
467 * After the asynchronous task is created, the asyncCallbackInfo reference count is reduced
468 * to 0 destructions, so you need to add 1 to the asyncCallbackInfo reference count when the
469 * asynchronous task is created, and subtract 1 from the reference count after the naked
470 * pointer is converted to a pointer when the asynchronous task is executed, the reference
471 * count of the smart pointer is guaranteed to be 1.
472 */
473 asyncCallbackInfo->DecStrongRef(nullptr);
474 napi_value callback = nullptr;
475 napi_value callResult = nullptr;
476 napi_value result[2] = {0};
477 if (asyncCallbackInfo->type == SUBSCRIBE_FAIL) {
478 CHKNRV(env, napi_get_reference_value(env, asyncCallbackInfo->callback[1], &callback),
479 "napi_get_reference_value");
480 CHKNRV(env, napi_create_string_utf8(env, asyncCallbackInfo->error.message.c_str(),
481 NAPI_AUTO_LENGTH, &result[0]), "napi_create_string_utf8");
482 CHKNRV(env, napi_create_int32(env, asyncCallbackInfo->error.code, &result[1]), "napi_create_int32");
483 CHKNRV(env, napi_call_function(env, nullptr, callback, 2, result, &callResult),
484 "napi_call_function");
485 return;
486 }
487 CHKNRV(env, napi_get_reference_value(env, asyncCallbackInfo->callback[0], &callback),
488 "napi_get_reference_value");
489 CHKNCV(env, (g_convertfuncList.find(asyncCallbackInfo->type) != g_convertfuncList.end()),
490 "Callback type invalid in async work");
491 bool ret = g_convertfuncList[asyncCallbackInfo->type](env, asyncCallbackInfo, result);
492 CHKNCV(env, ret, "Create napi data fail in async work");
493 CHKNRV(env, napi_call_function(env, nullptr, callback, 2, result, &callResult),
494 "napi_call_function");
495 },
496 asyncCallbackInfo.GetRefPtr(), &asyncCallbackInfo->asyncWork);
497 if (status != napi_ok
498 || napi_queue_async_work(asyncCallbackInfo->env, asyncCallbackInfo->asyncWork) != napi_ok) {
499 SEN_HILOGE("Create async work fail");
500 asyncCallbackInfo->DecStrongRef(nullptr);
501 }
502 }
503
freeWork(uv_work_t * work)504 void freeWork(uv_work_t *work)
505 {
506 CALL_LOG_ENTER;
507 CHKPV(work);
508 delete work;
509 work = nullptr;
510 }
511
EmitUvEventLoop(sptr<AsyncCallbackInfo> asyncCallbackInfo)512 void EmitUvEventLoop(sptr<AsyncCallbackInfo> asyncCallbackInfo)
513 {
514 CHKPV(asyncCallbackInfo);
515 uv_loop_s *loop(nullptr);
516 CHKNRV(asyncCallbackInfo->env, napi_get_uv_event_loop(asyncCallbackInfo->env, &loop),
517 "napi_get_uv_event_loop");
518 CHKPV(loop);
519 uv_work_t *work = new(std::nothrow) uv_work_t;
520 CHKPV(work);
521 asyncCallbackInfo->work = work;
522 asyncCallbackInfo->IncStrongRef(nullptr);
523 work->data = asyncCallbackInfo.GetRefPtr();
524 int32_t ret = uv_queue_work(loop, work, [] (uv_work_t *work) { }, [] (uv_work_t *work, int status) {
525 CHKPV(work);
526 sptr<AsyncCallbackInfo> asyncCallbackInfo(static_cast<AsyncCallbackInfo *>(work->data));
527 /**
528 * After the asynchronous task is created, the asyncCallbackInfo reference count is reduced
529 * to 0 destructions, so you need to add 1 to the asyncCallbackInfo reference count when the
530 * asynchronous task is created, and subtract 1 from the reference count after the naked
531 * pointer is converted to a pointer when the asynchronous task is executed, the reference
532 * count of the smart pointer is guaranteed to be 1.
533 */
534 asyncCallbackInfo->DecStrongRef(nullptr);
535 napi_env env = asyncCallbackInfo->env;
536 napi_value callback = nullptr;
537 CHKNRV(env, napi_get_reference_value(env, asyncCallbackInfo->callback[0], &callback),
538 "napi_get_reference_value");
539 napi_value callResult = nullptr;
540 napi_value result[2] = {0};
541 CHKNCV(env, (g_convertfuncList.find(asyncCallbackInfo->type) != g_convertfuncList.end()),
542 "Asynccallback Type invalid in uv work");
543 g_convertfuncList[asyncCallbackInfo->type](env, asyncCallbackInfo, result);
544 CHKNRV(env, napi_call_function(env, nullptr, callback, 1, &result[1], &callResult), "napi_call_function");
545 asyncCallbackInfo->work = nullptr;
546 freeWork(work);
547 });
548 if (ret != 0) {
549 SEN_HILOGE("uv_queue_work fail");
550 asyncCallbackInfo->DecStrongRef(nullptr);
551 asyncCallbackInfo->work = nullptr;
552 freeWork(work);
553 }
554 }
555
EmitPromiseWork(sptr<AsyncCallbackInfo> asyncCallbackInfo)556 void EmitPromiseWork(sptr<AsyncCallbackInfo> asyncCallbackInfo)
557 {
558 CALL_LOG_ENTER;
559 CHKPV(asyncCallbackInfo);
560 napi_value resourceName = nullptr;
561 CHKNRV(asyncCallbackInfo->env, napi_create_string_latin1(asyncCallbackInfo->env, "Promise",
562 NAPI_AUTO_LENGTH, &resourceName), "napi_create_string_latin1");
563 asyncCallbackInfo->IncStrongRef(nullptr);
564 napi_status status = napi_create_async_work(asyncCallbackInfo->env, nullptr, resourceName,
565 [](napi_env env, void* data) {},
566 [](napi_env env, napi_status status, void* data) {
567 CALL_LOG_ENTER;
568 sptr<AsyncCallbackInfo> asyncCallbackInfo(static_cast<AsyncCallbackInfo *>(data));
569 /**
570 * After the asynchronous task is created, the asyncCallbackInfo reference count is reduced
571 * to 0 destructions, so you need to add 1 to the asyncCallbackInfo reference count when the
572 * asynchronous task is created, and subtract 1 from the reference count after the naked
573 * pointer is converted to a pointer when the asynchronous task is executed, the reference
574 * count of the smart pointer is guaranteed to be 1.
575 */
576 asyncCallbackInfo->DecStrongRef(nullptr);
577 napi_value result[2] = {0};
578 CHKNCV(env, (g_convertfuncList.find(asyncCallbackInfo->type) != g_convertfuncList.end()),
579 "Callback type invalid in promise");
580 bool ret = g_convertfuncList[asyncCallbackInfo->type](env, asyncCallbackInfo, result);
581 CHKNCV(env, ret, "Create napi data fail in promise");
582 if (asyncCallbackInfo->type == FAIL) {
583 CHKNRV(env, napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]),
584 "napi_reject_deferred");
585 } else {
586 CHKNRV(env, napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[1]),
587 "napi_resolve_deferred");
588 }
589 },
590 asyncCallbackInfo.GetRefPtr(), &asyncCallbackInfo->asyncWork);
591 if (status != napi_ok
592 || napi_queue_async_work(asyncCallbackInfo->env, asyncCallbackInfo->asyncWork) != napi_ok) {
593 SEN_HILOGE("Create async work fail");
594 asyncCallbackInfo->DecStrongRef(nullptr);
595 }
596 }
597 } // namespace Sensors
598 } // namespace OHOS