传感器开发指导(C/C++)
==============

#### 场景介绍

当设备需要获取传感器数据时，可以使用sensor模块，例如：通过订阅方向传感器数据感知用户设备当前的朝向，通过订阅计步传感器数据统计用户的步数等。

详细的接口介绍请参考[Sensor](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-sensor)。

#### 函数说明

| 名称 | 描述 |
| :-- | :-- |
| OH\_Sensor\_GetInfos(Sensor\_Info \*\*infos, uint32\_t \*count) | 获取设备上所有传感器的信息。 |
| OH\_Sensor\_Subscribe(const Sensor\_SubscriptionId \*id, const Sensor\_SubscriptionAttribute \*attribute, const Sensor\_Subscriber \*subscriber) | 
订阅传感器数据。系统将以指定的频率向用户上报传感器数据。

订阅加速度传感器，需要申请ohos.permission.ACCELEROMETER权限；

订阅陀螺仪传感器，需要申请ohos.permission.GYROSCOPE权限；

订阅计步器相关传感器时，需要申请ohos.permission.ACTIVITY\_MOTION权限；

订阅与健康相关的传感器时，比如心率传感器需要申请ohos.permission.READ\_HEALTH\_DATA权限，否则订阅失败;

订阅其余传感器不需要申请权限。

 |
| OH\_Sensor\_Unsubscribe(const Sensor\_SubscriptionId \*id, const Sensor\_Subscriber \*subscriber) | 

取消订阅传感器数据。

取消订阅加速度传感器，需要申请ohos.permission.ACCELEROMETER权限；

取消订阅陀螺仪传感器，需要申请ohos.permission.GYROSCOPE权限；

取消订阅计步器相关传感器时，需要申请ohos.permission.ACTIVITY\_MOTION权限；

取消订阅与健康相关的传感器时，需要申请ohos.permission.READ\_HEALTH\_DATA权限，否则取消订阅失败。

取消订阅其余传感器不需要申请权限。

 |
| OH\_Sensor\_CreateInfos(uint32\_t count) | 用给定的数字创建一个实例数组，请参考[Sensor\_Info](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-sensor-sensor-info)。 |
| OH\_Sensor\_DestroyInfos(Sensor\_Info \*\*sensors, uint32\_t count) | 销毁实例数组并回收内存，请参考[Sensor\_Info](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-sensor-sensor-info)。 |
| OH\_SensorInfo\_GetName(Sensor\_Info \*sensor, char \*sensorName, uint32\_t \*length) | 获取传感器名称。 |
| OH\_SensorInfo\_GetVendorName(Sensor\_Info\* sensor, char \*vendorName, uint32\_t \*length) | 获取传感器的厂商名称。 |
| OH\_SensorInfo\_GetType(Sensor\_Info\* sensor, Sensor\_Type \*sensorType) | 获取传感器类型。 |
| OH\_SensorInfo\_GetResolution(Sensor\_Info\* sensor, float \*resolution) | 获取传感器分辨率。 |
| OH\_SensorInfo\_GetMinSamplingInterval(Sensor\_Info\* sensor, int64\_t \*minSamplingInterval) | 获取传感器的最小数据上报间隔。 |
| OH\_SensorInfo\_GetMaxSamplingInterval(Sensor\_Info\* sensor, int64\_t \*maxSamplingInterval) | 获取传感器的最大数据上报间隔时间。 |
| OH\_SensorEvent\_GetType(Sensor\_Event\* sensorEvent, Sensor\_Type \*sensorType) | 获取传感器类型。 |
| OH\_SensorEvent\_GetTimestamp(Sensor\_Event\* sensorEvent, int64\_t \*timestamp) | 获取传感器数据的时间戳。 |
| OH\_SensorEvent\_GetAccuracy(Sensor\_Event\* sensorEvent, Sensor\_Accuracy \*accuracy) | 获取传感器数据的精度。 |
| OH\_SensorEvent\_GetData(Sensor\_Event\* sensorEvent, float \*\*data, uint32\_t \*length) | 

获取传感器数据。

数据的长度和内容依赖于监听的传感器类型，传感器上报的数据格式如下：

1.SENSOR\_TYPE\_ACCELEROMETER:data\[0\]、data\[1\]、data\[2\]分别表示设备x、y、z轴的加速度分量，单位m/s²；

2.SENSOR\_TYPE\_GYROSCOPE:data\[0\]、data\[1\]、data\[2\]分别表示设备x、y、z轴的旋转角速度，单位弧度/s；

3.SENSOR\_TYPE\_AMBIENT\_LIGHT:data\[0\]表示环境光强度，单位lux；从API Version 12开始，将返回两个额外的数据，其中data\[1\]表示色温，单位kelvin；data\[2\]表示红外亮度，单位cd/m²；

4.SENSOR\_TYPE\_MAGNETIC\_FIELD:data\[0\]、data\[1\]、data\[2\]分别表示设备x、y、z轴的地磁分量，单位微特斯拉；

5.SENSOR\_TYPE\_BAROMETER:data\[0\]表示气压值，单位hPa；

6.SENSOR\_TYPE\_HALL:data\[0\]表示皮套吸合状态，0表示打开，大于0表示吸附；

7.SENSOR\_TYPE\_PROXIMITY:data\[0\]表示接近状态，0表示接近，大于0表示远离；

8.SENSOR\_TYPE\_ORIENTATION:data\[0\]、data\[1\]、data\[2\]分别表示设备绕z、x、y轴的角度，单位度；

9.SENSOR\_TYPE\_GRAVITY:data\[0\]、data\[1\]、data\[2\]分别表示设备x、y、z轴的重力加速度分量，单位m/s²；

10.SENSOR\_TYPE\_ROTATION\_VECTOR:data\[0\]、data\[1\]、data\[2\]分别表示设备x、y、z轴的旋转角度，单位度，data\[3\]表示旋转向量元素；

11.SENSOR\_TYPE\_PEDOMETER\_DETECTION:data\[0\]表示计步检测状态，1表示检测到了步数变化；

12.SENSOR\_TYPE\_PEDOMETER:data\[0\]表示步数；

13.SENSOR\_TYPE\_HEART\_RATE:data\[0\]表示心率数值。

 |
| OH\_Sensor\_CreateSubscriptionId(void) | 创建一个Sensor\_SubscriptionId 实例。 |
| OH\_Sensor\_DestroySubscriptionId(Sensor\_SubscriptionId \*id) | 销毁Sensor\_SubscriptionId 实例并回收内存。 |
| OH\_SensorSubscriptionId\_SetType(Sensor\_SubscriptionId\* id, const Sensor\_Type sensorType) | 设置传感器类型。 |
| OH\_Sensor\_CreateSubscriptionAttribute(void) | 创建Sensor\_SubscriptionAttribute实例。 |
| OH\_Sensor\_DestroySubscriptionAttribute(Sensor\_SubscriptionAttribute \*attribute) | 销毁Sensor\_SubscriptionAttribute实例并回收内存。 |
| OH\_SensorSubscriptionAttribute\_SetSamplingInterval(Sensor\_SubscriptionAttribute\* attribute, const int64\_t samplingInterval) | 设置传感器数据上报间隔。 |
| OH\_Sensor\_CreateSubscriber(void) | 创建一个Sensor\_Subscriber实例。 |
| OH\_Sensor\_DestroySubscriber(Sensor\_Subscriber \*subscriber) | 销毁Sensor\_Subscriber实例并回收内存。 |
| OH\_SensorSubscriber\_SetCallback(Sensor\_Subscriber\* subscriber, const Sensor\_EventCallback callback) | 设置一个回调函数来上报传感器数据。 |

#### 开发步骤

开发步骤以加速度传感器为例。

1.  新建一个Native C++工程。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/14/v3/2g9N5tOXSsCfINNd0M9UvA/zh-cn_image_0000002594668730.png?HW-CC-KV=V1&HW-CC-Date=20260612T073449Z&HW-CC-Expire=86400&HW-CC-Sign=8C3419E4B4C3A35474542A65082E6CDDB5886C5BAFF1E8AF250B95842284AB87)
    
2.  配置加速度传感器权限，具体配置方式请参考[声明权限](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/declare-permissions)。
    
    "requestPermissions": \[
      {
        "name": "ohos.permission.ACCELEROMETER"
      }
    \]
    
3.  CMakeLists.txt文件中引入动态依赖库。
    
    target\_link\_libraries(entry PUBLIC libace\_napi.z.so)
    target\_link\_libraries(entry PUBLIC libhilog\_ndk.z.so)
    target\_link\_libraries(entry PUBLIC libohsensor.so)
    
4.  在oh\_sensor\_capi.cpp文件中编码，首先导入模块。
    
    #include "sensors/oh\_sensor.h"
    #include "napi/native\_api.h"
    #include "hilog/log.h"
    #include <thread>
    
5.  定义常量。
    
    const int SENSOR\_LOG\_DOMAIN = 0xD002700;
    const char \*TAG = "\[Sensor\]";
    constexpr Sensor\_Type SENSOR\_ID { SENSOR\_TYPE\_ACCELEROMETER };
    constexpr uint32\_t SENSOR\_NAME\_LENGTH\_MAX = 64;
    constexpr int64\_t SENSOR\_SAMPLE\_PERIOD = 200000000;
    constexpr int32\_t SLEEP\_TIME\_MS = 1000;
    constexpr int64\_t INVALID\_VALUE = -1;
    constexpr float INVALID\_RESOLUTION = -1.0F;
    Sensor\_Subscriber \*g\_user = nullptr;
    
6.  定义一个回调函数用来接收传感器数据。
    
    // 定义回调函数
    void SensorDataCallbackImpl(Sensor\_Event \*event)
    {
        if (event == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "event is null");
            return;
        }
        int64\_t timestamp = INVALID\_VALUE;
        // 获取传感器数据的时间戳。
        int32\_t ret = OH\_SensorEvent\_GetTimestamp(event, &timestamp);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "get timestamp failed");
            return;
        }
        Sensor\_Type sensorType;
        // 获取传感器类型。
        ret = OH\_SensorEvent\_GetType(event, &sensorType);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "get sensor type failed");
            return;
        }
        Sensor\_Accuracy accuracy = SENSOR\_ACCURACY\_UNRELIABLE;
        // 获取传感器数据的精度。
        ret = OH\_SensorEvent\_GetAccuracy(event, &accuracy);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "get sensor accuracy failed");
            return;
        }
        float \*data = nullptr;
        uint32\_t length = 0;
        // 获取传感器数据。
        ret = OH\_SensorEvent\_GetData(event, &data, &length);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "get sensor data failed");
            return;
        }
        if (data == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "sensor data is null");
            return;
        }
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, SENSOR\_LOG\_DOMAIN, TAG,
            "sensorType:%{public}d, dataLen:%{public}d, accuracy:%{public}d", sensorType, length, accuracy);
        for (uint32\_t i = 0; i < length; ++i) {
            OH\_LOG\_Print(LOG\_APP, LOG\_INFO, SENSOR\_LOG\_DOMAIN, TAG, "data\[%{public}d\]:%{public}f", i, data\[i\]);
        }
    }
    
7.  获取设备上所有传感器的信息。
    
    static int32\_t GetSensorInfo(Sensor\_Info \*sensorInfoTemp)
    {
        char sensorName\[SENSOR\_NAME\_LENGTH\_MAX\] = {};
        uint32\_t length = SENSOR\_NAME\_LENGTH\_MAX;
        // 获取传感器名称。
        int32\_t ret = OH\_SensorInfo\_GetName(sensorInfoTemp, sensorName, &length);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "get sensor name failed");
            return ret;
        }
        char vendorName\[SENSOR\_NAME\_LENGTH\_MAX\] = {};
        length = SENSOR\_NAME\_LENGTH\_MAX;
        // 获取传感器的厂商名称。
        ret = OH\_SensorInfo\_GetVendorName(sensorInfoTemp, vendorName, &length);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "get sensor vendor name failed");
            return ret;
        }
        Sensor\_Type sensorType;
        // 获取传感器类型。
        ret = OH\_SensorInfo\_GetType(sensorInfoTemp, &sensorType);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "get sensor type failed");
            return ret;
        }
        float resolution = INVALID\_RESOLUTION;
        // 获取传感器分辨率。
        ret = OH\_SensorInfo\_GetResolution(sensorInfoTemp, &resolution);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "get sensor resolution failed");
            return ret;
        }
        int64\_t minSamplePeriod = INVALID\_VALUE;
        // 获取传感器的最小数据上报间隔。
        ret = OH\_SensorInfo\_GetMinSamplingInterval(sensorInfoTemp, &minSamplePeriod);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "get sensor min sampling interval failed");
            return ret;
        }
        int64\_t maxSamplePeriod = INVALID\_VALUE;
        // 获取传感器的最大数据上报间隔时间。
        ret = OH\_SensorInfo\_GetMaxSamplingInterval(sensorInfoTemp, &maxSamplePeriod);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "get sensor max sampling interval failed");
        }
        return ret;
    }
    
    static napi\_value GetSensorInfos(napi\_env env, napi\_callback\_info info)
    {
        uint32\_t count = 0;
        // 获取设备上所有传感器的个数。
        int32\_t ret = OH\_Sensor\_GetInfos(nullptr, &count);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "get sensor count failed");
            return nullptr;
        }
        // 用给定的数字创建一个实例数组。
        Sensor\_Info \*\*sensors = OH\_Sensor\_CreateInfos(count);
        if (sensors == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "create sensorInfo array failed");
            return nullptr;
        }
        // 获取设备上所有传感器的信息。
        ret = OH\_Sensor\_GetInfos(sensors, &count);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "get all sensor info failed");
            return nullptr;
        }
        for (uint32\_t i = 0; i < count; ++i) {
            Sensor\_Info \*sensorInfoTemp = sensors\[i\];
            ret = GetSensorInfo(sensorInfoTemp);
            if (ret != SENSOR\_SUCCESS) {
                OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "get sensor info failed");
                return nullptr;
            }
        }
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, SENSOR\_LOG\_DOMAIN, TAG, "GetSensorInfos successful");
        // 销毁实例数组并回收内存。
        ret = OH\_Sensor\_DestroyInfos(sensors, count);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "destroy sensor info failed");
            return nullptr;
        }
        return nullptr;
    }
    
8.  订阅和取消订阅传感器数据。
    
    static napi\_value Subscriber(napi\_env env, napi\_callback\_info info)
    {
        // 创建Sensor\_Subscriber实例。
        g\_user = OH\_Sensor\_CreateSubscriber();
        // 设置回调函数来报告传感器数据。
        int32\_t ret = OH\_SensorSubscriber\_SetCallback(g\_user, SensorDataCallbackImpl);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "OH\_SensorSubscriber\_SetCallback failed");
            return nullptr;
        }
        // 创建Sensor\_SubscriptionId实例。
        Sensor\_SubscriptionId \*id = OH\_Sensor\_CreateSubscriptionId();
        // 设置传感器类型,示例中设置的是SENSOR\_TYPE\_ACCELEROMETER类型，需开通ohos.permission.ACCELEROMETER权限
        // 参考传感器开发指导中 开发步骤第2点配置加速度传感器权限。
        ret = OH\_SensorSubscriptionId\_SetType(id, SENSOR\_ID);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "OH\_SensorSubscriptionId\_SetType failed");
            return nullptr;
        }
        // 创建Sensor\_SubscriptionAttribute实例。
        Sensor\_SubscriptionAttribute \*attr = OH\_Sensor\_CreateSubscriptionAttribute();
        // 设置传感器数据报告间隔。
        ret = OH\_SensorSubscriptionAttribute\_SetSamplingInterval(attr, SENSOR\_SAMPLE\_PERIOD);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG,
                "OH\_SensorSubscriptionAttribute\_SetSamplingInterval failed");
            return nullptr;
        }
        // 订阅传感器数据。
        ret = OH\_Sensor\_Subscribe(id, attr, g\_user);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "OH\_Sensor\_Subscribe failed");
            return nullptr;
        }
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, SENSOR\_LOG\_DOMAIN, TAG, "OH\_Sensor\_Subscribe successful");
        std::this\_thread::sleep\_for(std::chrono::milliseconds(SLEEP\_TIME\_MS));
        // 取消订阅传感器数据。
        ret = OH\_Sensor\_Unsubscribe(id, g\_user);
        if (ret != SENSOR\_SUCCESS) {
            OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, SENSOR\_LOG\_DOMAIN, TAG, "OH\_Sensor\_Unsubscribe failed");
            return nullptr;
        }
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, SENSOR\_LOG\_DOMAIN, TAG, "OH\_Sensor\_Unsubscribe successful");
        if (id != nullptr) {
            // 销毁Sensor\_SubscriptionId实例。
            OH\_Sensor\_DestroySubscriptionId(id);
        }
        if (attr != nullptr) {
            // 销毁Sensor\_SubscriptionAttribute实例。
            OH\_Sensor\_DestroySubscriptionAttribute(attr);
        }
        if (g\_user != nullptr) {
            // 销毁Sensor\_Subscriber实例并回收内存。
            OH\_Sensor\_DestroySubscriber(g\_user);
            g\_user = nullptr;
        }
        return nullptr;
    }
    
9.  在Init函数中补充接口。
    
    EXTERN\_C\_START
    static napi\_value Init(napi\_env env, napi\_value exports)
    {
        napi\_property\_descriptor desc\[\] = {
            {"getSensorInfos", nullptr, GetSensorInfos, nullptr, nullptr, nullptr, napi\_default, nullptr},
            {"subscriber", nullptr, Subscriber, nullptr, nullptr, nullptr, napi\_default, nullptr}
        };
        napi\_define\_properties(env, exports, sizeof(desc) / sizeof(desc\[0\]), desc);
        return exports;
    }
    EXTERN\_C\_END
    
10.  在types/libentry路径下index.d.ts文件中引入Napi接口。
     
     export const getSensorInfos: () => object;
     export const subscriber: () => object;
     
11.  编写程序入口调用代码。
     
     import { BusinessError } from '@kit.BasicServicesKit';
     import { hilog } from '@kit.PerformanceAnalysisKit';
     import sensorCapi from 'libentry.so';
     
     const DOMAIN = 0xD002700;
     // ...
               try {
                 sensorCapi.getSensorInfos();
                 // ...
               } catch (error) {
                 let e: BusinessError = error as BusinessError;
                 hilog.error(DOMAIN, 'testTag', \`Failed to invoke getSensorInfos. Code: ${e.code}, message: ${e.message}\`);
               }
               // ...
               try {
                 sensorCapi.subscriber();
                 // ...
               } catch (error) {
                 let e: BusinessError = error as BusinessError;
                 hilog.error(DOMAIN, 'testTag', \`Failed to invoke subscriber. Code: ${e.code}, message: ${e.message}\`);
               }