chenyumai 发表于 2025-3-30 12:18:53

OpenHarmony sensor test tool 传感器 测试 工具

OpenHarmony 传感器的生态目前还不完善,体现在
hdf_unittest_sensor 功能缺失,只支持 als 读取数据。hdf_unittest_sensor enable 并未真正执行读取动作,只是读取了旧值。hdf_unittest_sensor 在设备没有传感器的情况下必失败,影响 xts 验证。hdi_unittest_sensor 同样功能缺失,甚至不支持数据验证。除 als 外,其他数据在 hdf_core 中的上报通路都没打通。实际测试中有发现 hcs 配置中,掩码不生效的问题。chipset raw 数据读取存在重入 bug。
鉴于很多都是一些低级错误,甚至基础不牢的问题。我开发了一个测试工具,用来检测传感器是否能正常上报数据。
用法如下:
>hdc shell sensor_tool   
Usage: sensor_tool
       sensor_tool (help | -h | --help)

Note: Commands without sensor_id will apply to all sensors

Commands:
list                  List all sensors
enable       Enable specified sensor
disable    Disable specified sensor
read       Read sensor data once
monitor    Monitor sensor data continuously

Monitor Options:
-i, --interval   Set sampling interval (default: 1000ms)
-c, --count       Set number of readings (default: infinite)
-t, --time      Set monitoring duration in seconds (default: infinite)你可以
使用 enable,read,disable 配合 i2cget,i2cset,单独调试 hcs 中的 init,enable,disable 序列是否有问题,或者是掩码是否生效(用来排除 OH 代码问题)。使用 monitor 检查传感器能否正常上报读数,传感器读数是否会随环境变化而变化。
效果如下
C:\Users\chao>hdc shell sensor_tool list   
Available sensors (5):
----------------------------------------
Sensor: ID=6, Name=magnetometer
Sensor: ID=12, Name=proximity
Sensor: ID=5, Name=als
Sensor: ID=2, Name=gyroscope
Sensor: ID=1, Name=accelerometer
----------------------------------------

C:\Users\chao>hdc shell sensor_tool enable
Sensor 6 (magnetometer) enabled successfully
Sensor 12 (proximity) enabled successfully
Sensor 5 (als) enabled successfully
Sensor 2 (gyroscope) enabled successfully
Sensor 1 (accelerometer) enabled successfully
All sensors enabled successfully

C:\Users\chao>hdc shell sensor_tool read

Reading data:
----------------------------------------
Sensor magnetometer data: -22.50 -45.15 86.85
Failed to read sensor 12 (proximity) data
Sensor als data: 0.60
Sensor gyroscope data: -6.38 3.19 6.38
Sensor accelerometer data: 0.01 1.76 -10.01
----------------------------------------

C:\Users\chao>hdc shell sensor_tool monitor
Sensor 6 (magnetometer) enabled successfully
Sensor 12 (proximity) enabled successfully
Sensor 5 (als) enabled successfully
Sensor 2 (gyroscope) enabled successfully
Sensor 1 (accelerometer) enabled successfully
All sensors enabled successfully

Reading data (count: 1):
----------------------------------------

Trying to read data from sensor 6 (magnetometer):
Sensor magnetometer data: -22.65 -45.60 89.25

Trying to read data from sensor 12 (proximity):
Failed to read sensor 12 (proximity) data, ret=-1

Trying to read data from sensor 5 (als):
Sensor als data: 0.60

Trying to read data from sensor 2 (gyroscope):
Sensor gyroscope data: -3.19 4.25 5.32

Trying to read data from sensor 1 (accelerometer):
Sensor accelerometer data: 0.00 1.75 -9.98
----------------------------------------

Reading data (count: 2):
----------------------------------------

Trying to read data from sensor 6 (magnetometer):
Sensor magnetometer data: -22.05 -44.70 87.60

Trying to read data from sensor 12 (proximity):
Failed to read sensor 12 (proximity) data, ret=-1

Trying to read data from sensor 5 (als):
Sensor als data: 0.60

Trying to read data from sensor 2 (gyroscope):
Sensor gyroscope data: -5.32 2.13 3.19

Trying to read data from sensor 1 (accelerometer):
Sensor accelerometer data: 0.02 1.73 -9.99
----------------------------------------编译说明

用法是,把下面文件放到 unittest 下面,改改仿照 BUILD.gn 里的 hdf_unittest_sensor,重新设置一个编译目标,比如 sensor_tool,然后单编。
#include
#include
#include
#include
#include
#include
#include
#include
#include "hdf_base.h"
#include "osal_mem.h"
#include "osal_time.h"
#include "sensor_if.h"
#include "sensor_type.h"

// 全局变量
static const struct SensorInterface *g_sensorDev = nullptr;
static struct SensorInformation *g_sensorInfo = nullptr;
static int32_t g_sensorCount = 0;
static uint32_t g_interval = 1000;// 默认采样间隔1秒
static int32_t g_count = -1;      // 默认持续读取
static int32_t g_duration = -1;   // 默认持续运行
static bool g_running = true;       // 运行状态标志

// 命令类型枚举
enum CommandType {
    CMD_NONE = 0,
    CMD_LIST,
    CMD_ENABLE,
    CMD_DISABLE,
    CMD_READ,
    CMD_MONITOR
};

// 命令参数结构
struct CommandArgs {
    enum CommandType cmd;
    int32_t sensorId;
};

// 函数声明
static void PrintUsage(void);
static int32_t ParseCommandLine(int argc, char *argv[], struct CommandArgs *args);
static int32_t InitSensorDev(void);
static void DeinitSensorDev(void);
static int32_t ListSensors(void);
static int32_t EnableSensor(int32_t sensorId);
static int32_t EnableAllSensors(void);
static int32_t DisableSensor(int32_t sensorId);
static int32_t DisableAllSensors(void);
static int32_t ReadSensorData(int32_t sensorId, bool autoEnable, bool readAll);
static const char* GetSensorName(int32_t sensorId);
static int32_t ReadAndPrintSensorData(struct SensorEvents **events, int32_t numSensors,
                                     int32_t sensorId, bool readAll, int32_t readCount = -1);

// 信号处理函数
static void SignalHandler(int signo)
{
    if (signo == SIGINT) {
      printf("\nReceived Ctrl+C, stopping...\n");
      g_running = false;
    }
}

// 主函数
int main(int argc, char *argv[])
{
    struct CommandArgs args = {CMD_NONE, 0};// 修复结构体初始化
    int32_t ret;

    // 设置信号处理
    signal(SIGINT, SignalHandler);

    // 解析命令行参数
    ret = ParseCommandLine(argc, argv, &args);
    if (ret != 0) {
      PrintUsage();
      return -1;
    }

    // 初始化传感器设备
    ret = InitSensorDev();
    if (ret != 0) {
      printf("Failed to init sensor device\n");
      return -1;
    }

    // 执行命令
    switch (args.cmd) {
      case CMD_LIST:
            ret = ListSensors();
            break;
      case CMD_ENABLE:
            ret = (args.sensorId == -1) ? EnableAllSensors() : EnableSensor(args.sensorId);
            break;
      case CMD_DISABLE:
            ret = (args.sensorId == -1) ? DisableAllSensors() : DisableSensor(args.sensorId);
            break;
      case CMD_READ:
            ret = (args.sensorId == -1) ? ReadSensorData(0, false, true) : ReadSensorData(args.sensorId, false, false);
            break;
      case CMD_MONITOR:
            ret = (args.sensorId == -1) ? ReadSensorData(0, true, true) : ReadSensorData(args.sensorId, true, false);
            break;
      default:
            PrintUsage();
            ret = -1;
            break;
    }

    // 释放传感器设备
    DeinitSensorDev();
    return ret;
}

// 打印使用说明
static void PrintUsage(void)
{
    printf("Usage: sensor_tool \n");
    printf("       sensor_tool (help | -h | --help)\n");
    printf("\nNote: Commands without sensor_id will apply to all sensors\n");
    printf("\nCommands:\n");
    printf("list                  List all sensors\n");
    printf("enable       Enable specified sensor\n");
    printf("disable    Disable specified sensor\n");
    printf("read       Read sensor data once\n");
    printf("monitor    Monitor sensor data continuously\n");
    printf("\nMonitor Options:\n");
    printf("-i, --interval   Set sampling interval (default: 1000ms)\n");
    printf("-c, --count       Set number of readings (default: infinite)\n");
    printf("-t, --time      Set monitoring duration in seconds (default: infinite)\n");
}

// 解析命令行参数
static int32_t ParseCommandLine(int argc, char *argv[], struct CommandArgs *args)
{
    int opt;
    int option_index = 0;
    struct option long_options[] = {
      {"interval", required_argument, nullptr, 'i'},
      {"count", required_argument, nullptr, 'c'},
      {"time", required_argument, nullptr, 't'},
      {"help", no_argument, nullptr, 'h'},
      {nullptr, 0, nullptr, 0}
    };

    // 默认设置为-1表示所有传感器
    args->sensorId = -1;

    // 解析选项
    while ((opt = getopt_long(argc, argv, "i:c:t:h", long_options, &option_index)) != -1) {
      switch (opt) {
            case 'i':
                g_interval = atoi(optarg);
                break;
            case 'c':
                g_count = atoi(optarg);
                break;
            case 't':
                g_duration = atoi(optarg);
                break;
            case 'h':
                PrintUsage();
                exit(0);
            default:
                return -1;
      }
    }

    // 解析命令
    if (optind >= argc) {
      return -1;
    }

    const char *cmd = argv;
    struct {
      const char *name;
      enum CommandType type;
      bool needId;
    } cmdMap[] = {
      {"list", CMD_LIST, false},
      {"enable", CMD_ENABLE, true},
      {"disable", CMD_DISABLE, true},
      {"read", CMD_READ, true},
      {"monitor", CMD_MONITOR, true},
      {nullptr, CMD_NONE, false}
    };

    for (int i = 0; cmdMap.name != nullptr; i++) {
      if (strcmp(cmd, cmdMap.name) == 0) {
            args->cmd = cmdMap.type;
            if (cmdMap.needId && optind + 1 < argc && argv != '-') {
                args->sensorId = atoi(argv);
            }
            return 0;
      }
    }

    return -1;
}

// 初始化传感器设备
static int32_t InitSensorDev(void)
{
    g_sensorDev = NewSensorInterfaceInstance();
    if (g_sensorDev == nullptr) {
      printf("Failed to get sensor interface instance\n");
      return -1;
    }

    int32_t ret = g_sensorDev->GetAllSensors(&g_sensorInfo, &g_sensorCount);
    if (ret != 0) {
      printf("Failed to get sensor information\n");
      FreeSensorInterfaceInstance();
      g_sensorDev = nullptr;
      return -1;
    }

    return 0;
}

// 释放传感器设备
static void DeinitSensorDev(void)
{
    if (g_sensorDev != nullptr) {
      FreeSensorInterfaceInstance();
      g_sensorDev = nullptr;
    }
}

// 列出所有传感器
static int32_t ListSensors(void)
{
    if (g_sensorInfo == nullptr || g_sensorCount sensorId, info->sensorName);
      info++;
    }
    printf("----------------------------------------\n");

    return 0;
}

// 通过传感器ID获取传感器名称
static const char* GetSensorName(int32_t sensorId)
{
    if (g_sensorInfo == nullptr || g_sensorCount SetBatch(sensorId, g_interval * 1000000, 0);
    if (ret != 0) {
      printf("Failed to set batch for sensor %d\n", sensorId);
      return -1;
    }

    // 使能传感器
    ret = g_sensorDev->Enable(sensorId);
    if (ret != 0) {
      printf("Failed to enable sensor %d\n", sensorId);
      return -1;
    }

    printf("Sensor %d (%s) enabled successfully\n", sensorId, GetSensorName(sensorId));
    return 0;
}

// 使能所有传感器
static int32_t EnableAllSensors(void)
{
    if (g_sensorDev == nullptr || g_sensorInfo == nullptr || g_sensorCount sensorId);
      if (ret != 0) {
            printf("Failed to enable sensor %d\n", info->sensorId);
            return -1;
      }
      info++;
    }

    printf("All sensors enabled successfully\n");
    return 0;
}

// 禁用指定传感器
static int32_t DisableSensor(int32_t sensorId)
{
    if (g_sensorDev == nullptr) {
      printf("Sensor device not initialized\n");
      return -1;
    }

    int32_t ret = g_sensorDev->Disable(sensorId);
    if (ret != 0) {
      printf("Failed to disable sensor %d\n", sensorId);
      return -1;
    }

    printf("Sensor %d (%s) disabled successfully\n", sensorId, GetSensorName(sensorId));
    return 0;
}

// 禁用所有传感器
static int32_t DisableAllSensors(void)
{
    if (g_sensorDev == nullptr || g_sensorInfo == nullptr || g_sensorCount sensorId);
      if (ret != 0) {
            printf("Failed to disable sensor %d\n", info->sensorId);
            return -1;
      }
      info++;
    }

    printf("All sensors disabled successfully\n");
    return 0;
}

// 读取并打印传感器数据
static int32_t ReadAndPrintSensorData(struct SensorEvents **events, int32_t numSensors,
                                    int32_t sensorId, bool readAll, int32_t readCount)
{
    if (readCount >= 0) {
      printf("\nReading data (count: %d):\n", readCount + 1);
    } else {
      printf("\nReading data:\n");
    }

    if (readAll) {
      printf("----------------------------------------\n");
    }

    for (int32_t i = 0; i < numSensors; i++) {
      int32_t currentSensorId = readAll ? g_sensorInfo.sensorId : sensorId;
      if (readCount >= 0) {
            printf("\nTrying to read data from sensor %d (%s):\n", currentSensorId, GetSensorName(currentSensorId));
      }

      int32_t ret = g_sensorDev->ReadData(currentSensorId, events);
      if (ret != 0) {
            printf("Failed to read sensor %d (%s) data%s\n",
                   currentSensorId, GetSensorName(currentSensorId),
                   readCount >= 0 ? (", ret=" + std::to_string(ret)).c_str() : "");
            if (readCount >= 0) {
                fflush(stdout);
            }
            continue;
      }

      // 打印数据
      float *data = reinterpret_cast(events->data);
      printf("Sensor[%d] %s data: ", currentSensorId, GetSensorName(currentSensorId));
      for (int32_t j = 0; j < events->dataLen / sizeof(float); j++) {
            printf("%.2f ", data);
      }
      printf("\n");
    }

    if (readAll) {
      printf("----------------------------------------\n");
    }
    if (readCount >= 0) {
      fflush(stdout);
    }

    return 0;
}

// 读取传感器数据
static int32_t ReadSensorData(int32_t sensorId, bool autoEnable, bool readAll)
{
    if (g_sensorDev == nullptr) {
      printf("Sensor device not initialized\n");
      return -1;
    }

    // 如果是读取所有传感器,需要额外的检查
    if (readAll && (g_sensorInfo == nullptr || g_sensorCount data = (uint8_t *)OsalMemCalloc(sizeof(float) * 3);
      if (events->data == nullptr) {
            printf("Failed to allocate sensor data %d\n", i);
            goto cleanup;
      }
      events->dataLen = sizeof(float) * 3;
    }

    // 如果是自动读取模式,使用循环读取
    if (autoEnable) {
      // 计算读取次数
      int32_t readCount = 0;
      int32_t maxCount = (g_count > 0) ? g_count : INT32_MAX;
      int32_t maxTime = (g_duration > 0) ? g_duration : INT32_MAX;
      OsalTimespec startTime = {0};
      OsalGetTime(&startTime);

      // 循环读取数据
      while (readCount < maxCount && g_running) {
            // 检查是否超时
            OsalTimespec currentTime = {0};
            if (OsalGetTime(¤tTime) == HDF_SUCCESS) {
                uint64_t elapsedTime = (currentTime.sec - startTime.sec) * 1000 +
                                     (currentTime.usec - startTime.usec) / 1000;
                if (elapsedTime >= maxTime * 1000) {
                  break;
                }
            }

            ReadAndPrintSensorData(events, numSensors, sensorId, readAll, readCount);
            readCount++;
            OsalMSleep(g_interval);
      }
    } else {
      // 一次性读取数据
      ReadAndPrintSensorData(events, numSensors, sensorId, readAll);
    }

    // 禁用传感器(如果指定了auto)
    if (autoEnable) {
      if (readAll) {
            DisableAllSensors();
      } else {
            DisableSensor(sensorId);
      }
    }

cleanup:
    // 释放资源
    if (events != nullptr) {
      for (int32_t i = 0; i < numSensors; i++) {
            if (events != nullptr) {
                if (events->data != nullptr) {
                  OsalMemFree(events->data);
                }
                OsalMemFree(events);
            }
      }
      OsalMemFree(events);
    }

    return 0;
}
页: [1]
查看完整版本: OpenHarmony sensor test tool 传感器 测试 工具