• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &paramType), "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, &copyLength),
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