1# 传感器开发指导(C/C++) 2<!--Kit: Sensor Service Kit--> 3<!--Subsystem: Sensors--> 4<!--Owner: @dilligencer--> 5<!--Designer: @butterls--> 6<!--Tester: @murphy84--> 7<!--Adviser: @hu-zhiqiong--> 8 9## 场景介绍 10 11当设备需要获取传感器数据时,可以使用sensor模块,例如:通过订阅方向传感器数据感知用户设备当前的朝向,通过订阅计步传感器数据统计用户的步数等。 12 13详细的接口介绍请参考[Sensor接口](../../reference/apis-sensor-service-kit/_sensor.md)。 14 15## 函数说明 16 17| 名称 | 描述 | 18| ------------------------------------------------------------ | ------------------------------------------------------------ | 19| OH_Sensor_GetInfos(Sensor_Info **infos, uint32_t *count) | 获取设备上所有传感器的信息。 | 20| OH_Sensor_Subscribe(const Sensor_SubscriptionId *id, const Sensor_SubscriptionAttribute *attribute, const Sensor_Subscriber *subscriber) | 订阅传感器数据。系统将以指定的频率向用户上报传感器数据。<br/>订阅加速度传感器,需要申请ohos.permission.ACCELEROMETER权限;<br/>订阅陀螺仪传感器,需要申请ohos.permission.GYROSCOPE权限;<br/>订阅计步器相关传感器时,需要申请ohos.permission.ACTIVITY_MOTION权限;<br/>订阅与健康相关的传感器时,比如心率传感器需要申请ohos.permission.READ_HEALTH_DATA权限,否则订阅失败;<br/>订阅其余传感器不需要申请权限。 | 21| OH_Sensor_Unsubscribe(const Sensor_SubscriptionId *id, const Sensor_Subscriber *subscriber) | 取消订阅传感器数据。<br/>取消订阅加速度计传感器,需要申请ohos.permission.ACCELEROMETER权限; <br/>取消订阅陀螺仪传感器,需要申请ohos.permission.GYROSCOPE权限; <br/>取消订阅计步器相关传感器时,需要申请ohos.permission.ACTIVITY_MOTION权限;<br/>取消订阅与健康相关的传感器时,需要申请ohos.permission.READ_HEALTH_DATA权限,否则取消订阅失败。 <br/>取消订阅其余传感器不需要申请权限。 | 22| OH_Sensor_CreateInfos(uint32_t count) | 用给定的数字创建一个实例数组,请参考[Sensor_Info](../../reference/apis-sensor-service-kit/_sensor.md#sensor_info)。 | 23| OH_Sensor_DestroyInfos(Sensor_Info **sensors, uint32_t count) | 销毁实例数组并回收内存,请参考[Sensor_Info](../../reference/apis-sensor-service-kit/_sensor.md#sensor_info)。 | 24| OH_SensorInfo_GetName(Sensor_Info *sensor, char *sensorName, uint32_t *length) | 获取传感器名称。 | 25| OH_SensorInfo_GetVendorName(Sensor_Info* sensor, char *vendorName, uint32_t *length) | 获取传感器的厂商名称。 | 26| OH_SensorInfo_GetType(Sensor_Info* sensor, Sensor_Type *sensorType) | 获取传感器类型。 | 27| OH_SensorInfo_GetResolution(Sensor_Info* sensor, float *resolution) | 获取传感器分辨率。 | 28| OH_SensorInfo_GetMinSamplingInterval(Sensor_Info* sensor, int64_t *minSamplingInterval) | 获取传感器的最小数据上报间隔。 | 29| OH_SensorInfo_GetMaxSamplingInterval(Sensor_Info* sensor, int64_t *maxSamplingInterval) | 获取传感器的最大数据上报间隔时间。 | 30| OH_SensorEvent_GetType(Sensor_Event* sensorEvent, Sensor_Type *sensorType) | 获取传感器类型。 | 31| OH_SensorEvent_GetTimestamp(Sensor_Event* sensorEvent, int64_t *timestamp) | 获取传感器数据的时间戳。 | 32| OH_SensorEvent_GetAccuracy(Sensor_Event* sensorEvent, Sensor_Accuracy *accuracy) | 获取传感器数据的精度。 | 33| OH_SensorEvent_GetData(Sensor_Event* sensorEvent, float **data, uint32_t *length) | 获取传感器数据。<br/>数据的长度和内容依赖于监听的传感器类型,传感器上报的数据格式如下:<br/>1.SENSOR_TYPE_ACCELEROMETER:data[0]、data[1]、data[2]分别表示设备x、y、z轴的加速度分量,单位m/s²;<br/>2.SENSOR_TYPE_GYROSCOPE:data[0]、data[1]、data[2]分别表示设备x、y、z轴的旋转角速度,单位弧度/s;<br/>3.SENSOR_TYPE_AMBIENT_LIGHT:data[0]表示环境光强度,单位lux;从API Version 12开始,将返回两个额外的数据,其中data[1]表示色温,单位kelvin;data[2]表示红外亮度,单位cd/m²;<br/> 4.SENSOR_TYPE_MAGNETIC_FIELD:data[0]、data[1]、data[2]分别表示设备x、y、z轴的地磁分量,单位微特斯拉; <br/>5.SENSOR_TYPE_BAROMETER:data[0]表示气压值,单位hPa;<br/>6.SENSOR_TYPE_HALL:data[0]表示皮套吸合状态,0表示打开,大于0表示吸附;<br/>7.SENSOR_TYPE_PROXIMITY:data[0]表示接近状态,0表示接近,大于0表示远离;<br/>8.SENSOR_TYPE_ORIENTATION:data[0]、data[1]、data[2]分别表示设备绕z、x、y轴的角度,单位度;<br/>9.SENSOR_TYPE_GRAVITY:data[0]、data[1]、data[2]分别表示设备x、y、z轴的重力加速度分量,单位m/s²;<br/>10.SENSOR_TYPE_ROTATION_VECTOR:data[0]、data[1]、data[2]分别表示设备x、y、z轴的旋转角度,单位度,data[3]表示旋转向量元素;<br/>11.SENSOR_TYPE_PEDOMETER_DETECTION:data[0]表示计步检测状态,1表示检测到了步数变化;<br/>12.SENSOR_TYPE_PEDOMETER:data[0]表示步数;<br/>13.SENSOR_TYPE_HEART_RATE:data[0]表示心率数值。 | 34| OH_Sensor_CreateSubscriptionId(void) | 创建一个Sensor_SubscriptionId 实例。 | 35| OH_Sensor_DestroySubscriptionId(Sensor_SubscriptionId *id) | 销毁Sensor_SubscriptionId 实例并回收内存。 | 36| OH_SensorSubscriptionId_SetType(Sensor_SubscriptionId* id, const Sensor_Type sensorType) | 设置传感器类型。 | 37| OH_Sensor_CreateSubscriptionAttribute(void) | 创建Sensor_SubscriptionAttribute实例。 | 38| OH_Sensor_DestroySubscriptionAttribute(Sensor_SubscriptionAttribute *attribute) | 销毁Sensor_SubscriptionAttribute实例并回收内存。 | 39| OH_SensorSubscriptionAttribute_SetSamplingInterval(Sensor_SubscriptionAttribute* attribute, const int64_t samplingInterval) | 设置传感器数据上报间隔。 | 40| OH_Sensor_CreateSubscriber(void) | 创建一个Sensor_Subscriber实例。 | 41| OH_Sensor_DestroySubscriber(Sensor_Subscriber *subscriber) | 销毁Sensor_Subscriber实例并回收内存。 | 42| OH_SensorSubscriber_SetCallback(Sensor_Subscriber* subscriber, const Sensor_EventCallback callback) | 设置一个回调函数来上报传感器数据。 | 43 44 45## 开发步骤 46 47开发步骤以加速度传感器为例。 48 491. 新建一个Native C++工程。 50 51  52 532. 配置加速度传感器权限,具体配置方式请参考[声明权限](../../security/AccessToken/declare-permissions.md)。 54 55 ```json 56 "requestPermissions": [ 57 { 58 "name": "ohos.permission.ACCELEROMETER" 59 }, 60 ] 61 ``` 62 633. CMakeLists.txt文件中引入动态依赖库。 64 65 ```c 66 target_link_libraries(entry PUBLIC libace_napi.z.so) 67 target_link_libraries(entry PUBLIC libhilog_ndk.z.so) 68 target_link_libraries(entry PUBLIC libohsensor.so) 69 ``` 70 714. 在napi_init.cpp文件中编码,首先导入模块。 72 73 ```c 74 #include "sensors/oh_sensor.h" 75 #include "napi/native_api.h" 76 #include "hilog/log.h" 77 #include <thread> 78 ``` 79 805. 定义常量。 81 82 ```c 83 const int GLOBAL_RESMGR = 0xFF00; 84 const char *TAG = "[Sensor]"; 85 constexpr Sensor_Type SENSOR_ID { SENSOR_TYPE_ACCELEROMETER }; 86 constexpr uint32_t SENSOR_NAME_LENGTH_MAX = 64; 87 constexpr int64_t SENSOR_SAMPLE_PERIOD = 200000000; 88 constexpr int32_t SLEEP_TIME_MS = 1000; 89 constexpr int64_t INVALID_VALUE = -1; 90 constexpr float INVALID_RESOLUTION = -1.0F; 91 Sensor_Subscriber *g_user = nullptr; 92 ``` 93 946. 定义一个回调函数用来接收传感器数据。 95 96 ```c 97 void SensorDataCallbackImpl(Sensor_Event *event) { 98 if (event == nullptr) { 99 OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "event is null"); 100 return; 101 } 102 int64_t timestamp = INVALID_VALUE; 103 int32_t ret = OH_SensorEvent_GetTimestamp(event, ×tamp); // 获取传感器数据的时间戳。 104 if (ret != SENSOR_SUCCESS) { 105 return; 106 } 107 Sensor_Type sensorType; 108 ret = OH_SensorEvent_GetType(event, &sensorType); // 获取传感器类型。 109 if (ret != SENSOR_SUCCESS) { 110 return; 111 } 112 Sensor_Accuracy accuracy = SENSOR_ACCURACY_UNRELIABLE; 113 ret = OH_SensorEvent_GetAccuracy(event, &accuracy); // 获取传感器数据的精度。 114 if (ret != SENSOR_SUCCESS) { 115 return; 116 } 117 float *data = nullptr; 118 uint32_t length = 0; 119 ret = OH_SensorEvent_GetData(event, &data, &length); // 获取传感器数据。 120 if (ret != SENSOR_SUCCESS) { 121 return; 122 } 123 if (data == nullptr) { 124 return; 125 } 126 OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "sensorType:%{public}d, dataLen:%{public}d, accuracy:%{public}d", sensorType, length, accuracy); 127 for (uint32_t i = 0; i < length; ++i) { 128 OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "data[%{public}d]:%{public}f", i, data[i]); 129 } 130 } 131 ``` 132 1337. 获取设备上所有传感器的信息。 134 135 ```c 136 static napi_value GetSensorInfos(napi_env env, napi_callback_info info) 137 { 138 uint32_t count = 0; 139 int32_t ret = OH_Sensor_GetInfos(nullptr, &count); // 获取设备上所有传感器的个数。 140 if (ret != SENSOR_SUCCESS) { 141 return nullptr; 142 } 143 Sensor_Info **sensors = OH_Sensor_CreateInfos(count); // 用给定的数字创建一个实例数组。 144 if (sensors == nullptr) { 145 return nullptr; 146 } 147 ret = OH_Sensor_GetInfos(sensors, &count); // 获取设备上所有传感器的信息。 148 if (ret != SENSOR_SUCCESS) { 149 return nullptr; 150 } 151 for (uint32_t i = 0; i < count; ++i) { 152 char sensorName[SENSOR_NAME_LENGTH_MAX] = {}; 153 uint32_t length = SENSOR_NAME_LENGTH_MAX; 154 ret = OH_SensorInfo_GetName(sensors[i], sensorName, &length); // 获取传感器名称。 155 if (ret != SENSOR_SUCCESS) { 156 return nullptr; 157 } 158 char vendorName[SENSOR_NAME_LENGTH_MAX] = {}; 159 length = SENSOR_NAME_LENGTH_MAX; 160 ret = OH_SensorInfo_GetVendorName(sensors[i], vendorName, &length); // 获取传感器的厂商名称。 161 if (ret != SENSOR_SUCCESS) { 162 return nullptr; 163 } 164 Sensor_Type sensorType; 165 ret = OH_SensorInfo_GetType(sensors[i], &sensorType); // 获取传感器类型。 166 if (ret != SENSOR_SUCCESS) { 167 return nullptr; 168 } 169 float resolution = INVALID_RESOLUTION; 170 ret = OH_SensorInfo_GetResolution(sensors[i], &resolution); // 获取传感器分辨率。 171 if (ret != SENSOR_SUCCESS) { 172 return nullptr; 173 } 174 int64_t minSamplePeriod = INVALID_VALUE; 175 ret = OH_SensorInfo_GetMinSamplingInterval(sensors[i], &minSamplePeriod); // 获取传感器的最小数据上报间隔。 176 if (ret != SENSOR_SUCCESS) { 177 return nullptr; 178 } 179 int64_t maxSamplePeriod = INVALID_VALUE; 180 ret = OH_SensorInfo_GetMaxSamplingInterval(sensors[i], &maxSamplePeriod); // 获取传感器的最大数据上报间隔时间。 181 if (ret != SENSOR_SUCCESS) { 182 return nullptr; 183 } 184 } 185 OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "GetSensorInfos successful"); 186 ret = OH_Sensor_DestroyInfos(sensors, count); // 销毁实例数组并回收内存。 187 if (ret != SENSOR_SUCCESS) { 188 return nullptr; 189 } 190 napi_value result = nullptr; 191 napi_create_int32(env, ret, &result); 192 return result; 193 } 194 ``` 195 1968. 订阅和取消订阅传感器数据。 197 198 ```c 199 static napi_value Subscriber(napi_env env, napi_callback_info info) 200 { 201 g_user = OH_Sensor_CreateSubscriber(); // 创建一个Sensor_Subscriber实例。 202 int32_t ret = OH_SensorSubscriber_SetCallback(g_user, SensorDataCallbackImpl); // 设置一个回调函数来报告传感器数据。 203 if (ret != SENSOR_SUCCESS) { 204 return nullptr; 205 } 206 207 Sensor_SubscriptionId *id = OH_Sensor_CreateSubscriptionId(); // 创建一个Sensor_SubscriptionId实例。 208 ret = OH_SensorSubscriptionId_SetType(id, SENSOR_ID); // 设置传感器类型。 209 if (ret != SENSOR_SUCCESS) { 210 return nullptr; 211 } 212 213 Sensor_SubscriptionAttribute *attr = OH_Sensor_CreateSubscriptionAttribute(); // 创建Sensor_SubscriptionAttribute实例。 214 ret = OH_SensorSubscriptionAttribute_SetSamplingInterval(attr, SENSOR_SAMPLE_PERIOD); // 设置传感器数据报告间隔。 215 if (ret != SENSOR_SUCCESS) { 216 return nullptr; 217 } 218 219 ret = OH_Sensor_Subscribe(id, attr, g_user); // 订阅传感器数据。 220 if (ret != SENSOR_SUCCESS) { 221 return nullptr; 222 } 223 OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "Subscriber successful"); 224 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME_MS)); 225 ret = OH_Sensor_Unsubscribe(id, g_user); // 取消订阅传感器数据。 226 if (ret != SENSOR_SUCCESS) { 227 return nullptr; 228 } 229 if (id != nullptr) { 230 OH_Sensor_DestroySubscriptionId(id); // 销毁Sensor_SubscriptionId实例并回收内存。 231 } 232 if (attr != nullptr) { 233 OH_Sensor_DestroySubscriptionAttribute(attr); // 销毁Sensor_SubscriptionAttribute实例并回收内存。 234 } 235 if (g_user != nullptr) { 236 OH_Sensor_DestroySubscriber(g_user); // 销毁Sensor_Subscriber实例并回收内存。 237 g_user = nullptr; 238 } 239 napi_value result = nullptr; 240 napi_create_int32(env, ret, &result); 241 return result; 242 } 243 ``` 244 2459. 在Init函数中补充接口。 246 247 ```c 248 EXTERN_C_START 249 static napi_value Init(napi_env env, napi_value exports) 250 { 251 napi_property_descriptor desc[] = { 252 { "getSensorInfos", nullptr, GetSensorInfos, nullptr, nullptr, nullptr, napi_default, nullptr }, 253 { "subscriber", nullptr, Subscriber, nullptr, nullptr, nullptr, napi_default, nullptr } 254 }; 255 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 256 return exports; 257 } 258 EXTERN_C_END 259 ``` 260 26110. 在types/libentry路径下index.d.ts文件中引入Napi接口。 262 263 ```c 264 export const getSensorInfos: () => number; 265 export const subscriber: () => number; 266 ``` 267 26811. 删除Index.ets中的已废弃函数。 269 270 ```js 271 .onClick(() => { 272 hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3)); 273 }) 274 ``` 275