查看: 112|回复: 0

OpenHarmony sensor test tool 传感器 测试 工具

[复制链接]

1

主题

1

回帖

13

积分

新手上路

积分
13
发表于 2025-3-30 12:18:53 | 显示全部楼层 |阅读模式
OpenHarmony 传感器的生态目前还不完善,体现在
    hdf_unittest_sensor 功能缺失,只支持 als 读取数据。hdf_unittest_sensor enable 并未真正执行读取动作,只是读取了旧值。hdf_unittest_sensor 在设备没有传感器的情况下必失败,影响 xts 验证。hdi_unittest_sensor 同样功能缺失,甚至不支持数据验证。除 als 外,其他数据在 hdf_core 中的上报通路都没打通。实际测试中有发现 hcs 配置中,掩码不生效的问题。chipset raw 数据读取存在重入 bug。
鉴于很多都是一些低级错误,甚至基础不牢的问题。我开发了一个测试工具,用来检测传感器是否能正常上报数据。
用法如下:
  1. >hdc shell sensor_tool   
  2. Usage: sensor_tool [options]  [sensor_id]
  3.        sensor_tool (help | -h | --help)
  4. Note: Commands without sensor_id will apply to all sensors
  5. Commands:
  6.   list                    List all sensors
  7.   enable [sensor_id]      Enable specified sensor
  8.   disable [sensor_id]     Disable specified sensor
  9.   read [sensor_id]        Read sensor data once
  10.   monitor [sensor_id]     Monitor sensor data continuously
  11. Monitor Options:
  12.   -i, --interval     Set sampling interval (default: 1000ms)
  13.   -c, --count       Set number of readings (default: infinite)
  14.   -t, --time        Set monitoring duration in seconds (default: infinite)
复制代码
你可以
    使用 enable,read,disable 配合 i2cget,i2cset,单独调试 hcs 中的 init,enable,disable 序列是否有问题,或者是掩码是否生效(用来排除 OH 代码问题)。使用 monitor 检查传感器能否正常上报读数,传感器读数是否会随环境变化而变化。
效果如下
  1. C:\Users\chao>hdc shell sensor_tool list   
  2. Available sensors (5):
  3. ----------------------------------------
  4. Sensor[0]: ID=6, Name=magnetometer
  5. Sensor[1]: ID=12, Name=proximity
  6. Sensor[2]: ID=5, Name=als
  7. Sensor[3]: ID=2, Name=gyroscope
  8. Sensor[4]: ID=1, Name=accelerometer
  9. ----------------------------------------
  10. C:\Users\chao>hdc shell sensor_tool enable
  11. Sensor 6 (magnetometer) enabled successfully
  12. Sensor 12 (proximity) enabled successfully
  13. Sensor 5 (als) enabled successfully
  14. Sensor 2 (gyroscope) enabled successfully
  15. Sensor 1 (accelerometer) enabled successfully
  16. All sensors enabled successfully
  17. C:\Users\chao>hdc shell sensor_tool read  
  18. Reading data:
  19. ----------------------------------------
  20. Sensor[6] magnetometer data: -22.50 -45.15 86.85
  21. Failed to read sensor 12 (proximity) data
  22. Sensor[5] als data: 0.60
  23. Sensor[2] gyroscope data: -6.38 3.19 6.38
  24. Sensor[1] accelerometer data: 0.01 1.76 -10.01
  25. ----------------------------------------
  26. C:\Users\chao>hdc shell sensor_tool monitor
  27. Sensor 6 (magnetometer) enabled successfully
  28. Sensor 12 (proximity) enabled successfully
  29. Sensor 5 (als) enabled successfully
  30. Sensor 2 (gyroscope) enabled successfully
  31. Sensor 1 (accelerometer) enabled successfully
  32. All sensors enabled successfully
  33. Reading data (count: 1):
  34. ----------------------------------------
  35. Trying to read data from sensor 6 (magnetometer):
  36. Sensor[6] magnetometer data: -22.65 -45.60 89.25
  37. Trying to read data from sensor 12 (proximity):
  38. Failed to read sensor 12 (proximity) data, ret=-1
  39. Trying to read data from sensor 5 (als):
  40. Sensor[5] als data: 0.60
  41. Trying to read data from sensor 2 (gyroscope):
  42. Sensor[2] gyroscope data: -3.19 4.25 5.32
  43. Trying to read data from sensor 1 (accelerometer):
  44. Sensor[1] accelerometer data: 0.00 1.75 -9.98
  45. ----------------------------------------
  46. Reading data (count: 2):
  47. ----------------------------------------
  48. Trying to read data from sensor 6 (magnetometer):
  49. Sensor[6] magnetometer data: -22.05 -44.70 87.60
  50. Trying to read data from sensor 12 (proximity):
  51. Failed to read sensor 12 (proximity) data, ret=-1
  52. Trying to read data from sensor 5 (als):
  53. Sensor[5] als data: 0.60
  54. Trying to read data from sensor 2 (gyroscope):
  55. Sensor[2] gyroscope data: -5.32 2.13 3.19
  56. Trying to read data from sensor 1 (accelerometer):
  57. Sensor[1] accelerometer data: 0.02 1.73 -9.99
  58. ----------------------------------------
复制代码
编译说明

用法是,把下面文件放到 unittest 下面,改改仿照 BUILD.gn 里的 hdf_unittest_sensor,重新设置一个编译目标,比如 sensor_tool,然后单编。
  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include
  8. #include
  9. #include "hdf_base.h"
  10. #include "osal_mem.h"
  11. #include "osal_time.h"
  12. #include "sensor_if.h"
  13. #include "sensor_type.h"
  14. // 全局变量
  15. static const struct SensorInterface *g_sensorDev = nullptr;
  16. static struct SensorInformation *g_sensorInfo = nullptr;
  17. static int32_t g_sensorCount = 0;
  18. static uint32_t g_interval = 1000;  // 默认采样间隔1秒
  19. static int32_t g_count = -1;        // 默认持续读取
  20. static int32_t g_duration = -1;     // 默认持续运行
  21. static bool g_running = true;       // 运行状态标志
  22. // 命令类型枚举
  23. enum CommandType {
  24.     CMD_NONE = 0,
  25.     CMD_LIST,
  26.     CMD_ENABLE,
  27.     CMD_DISABLE,
  28.     CMD_READ,
  29.     CMD_MONITOR
  30. };
  31. // 命令参数结构
  32. struct CommandArgs {
  33.     enum CommandType cmd;
  34.     int32_t sensorId;
  35. };
  36. // 函数声明
  37. static void PrintUsage(void);
  38. static int32_t ParseCommandLine(int argc, char *argv[], struct CommandArgs *args);
  39. static int32_t InitSensorDev(void);
  40. static void DeinitSensorDev(void);
  41. static int32_t ListSensors(void);
  42. static int32_t EnableSensor(int32_t sensorId);
  43. static int32_t EnableAllSensors(void);
  44. static int32_t DisableSensor(int32_t sensorId);
  45. static int32_t DisableAllSensors(void);
  46. static int32_t ReadSensorData(int32_t sensorId, bool autoEnable, bool readAll);
  47. static const char* GetSensorName(int32_t sensorId);
  48. static int32_t ReadAndPrintSensorData(struct SensorEvents **events, int32_t numSensors,
  49.                                      int32_t sensorId, bool readAll, int32_t readCount = -1);
  50. // 信号处理函数
  51. static void SignalHandler(int signo)
  52. {
  53.     if (signo == SIGINT) {
  54.         printf("\nReceived Ctrl+C, stopping...\n");
  55.         g_running = false;
  56.     }
  57. }
  58. // 主函数
  59. int main(int argc, char *argv[])
  60. {
  61.     struct CommandArgs args = {CMD_NONE, 0};  // 修复结构体初始化
  62.     int32_t ret;
  63.     // 设置信号处理
  64.     signal(SIGINT, SignalHandler);
  65.     // 解析命令行参数
  66.     ret = ParseCommandLine(argc, argv, &args);
  67.     if (ret != 0) {
  68.         PrintUsage();
  69.         return -1;
  70.     }
  71.     // 初始化传感器设备
  72.     ret = InitSensorDev();
  73.     if (ret != 0) {
  74.         printf("Failed to init sensor device\n");
  75.         return -1;
  76.     }
  77.     // 执行命令
  78.     switch (args.cmd) {
  79.         case CMD_LIST:
  80.             ret = ListSensors();
  81.             break;
  82.         case CMD_ENABLE:
  83.             ret = (args.sensorId == -1) ? EnableAllSensors() : EnableSensor(args.sensorId);
  84.             break;
  85.         case CMD_DISABLE:
  86.             ret = (args.sensorId == -1) ? DisableAllSensors() : DisableSensor(args.sensorId);
  87.             break;
  88.         case CMD_READ:
  89.             ret = (args.sensorId == -1) ? ReadSensorData(0, false, true) : ReadSensorData(args.sensorId, false, false);
  90.             break;
  91.         case CMD_MONITOR:
  92.             ret = (args.sensorId == -1) ? ReadSensorData(0, true, true) : ReadSensorData(args.sensorId, true, false);
  93.             break;
  94.         default:
  95.             PrintUsage();
  96.             ret = -1;
  97.             break;
  98.     }
  99.     // 释放传感器设备
  100.     DeinitSensorDev();
  101.     return ret;
  102. }
  103. // 打印使用说明
  104. static void PrintUsage(void)
  105. {
  106.     printf("Usage: sensor_tool [options]  [sensor_id]\n");
  107.     printf("       sensor_tool (help | -h | --help)\n");
  108.     printf("\nNote: Commands without sensor_id will apply to all sensors\n");
  109.     printf("\nCommands:\n");
  110.     printf("  list                    List all sensors\n");
  111.     printf("  enable [sensor_id]      Enable specified sensor\n");
  112.     printf("  disable [sensor_id]     Disable specified sensor\n");
  113.     printf("  read [sensor_id]        Read sensor data once\n");
  114.     printf("  monitor [sensor_id]     Monitor sensor data continuously\n");
  115.     printf("\nMonitor Options:\n");
  116.     printf("  -i, --interval     Set sampling interval (default: 1000ms)\n");
  117.     printf("  -c, --count       Set number of readings (default: infinite)\n");
  118.     printf("  -t, --time        Set monitoring duration in seconds (default: infinite)\n");
  119. }
  120. // 解析命令行参数
  121. static int32_t ParseCommandLine(int argc, char *argv[], struct CommandArgs *args)
  122. {
  123.     int opt;
  124.     int option_index = 0;
  125.     struct option long_options[] = {
  126.         {"interval", required_argument, nullptr, 'i'},
  127.         {"count", required_argument, nullptr, 'c'},
  128.         {"time", required_argument, nullptr, 't'},
  129.         {"help", no_argument, nullptr, 'h'},
  130.         {nullptr, 0, nullptr, 0}
  131.     };
  132.     // 默认设置为-1表示所有传感器
  133.     args->sensorId = -1;
  134.     // 解析选项
  135.     while ((opt = getopt_long(argc, argv, "i:c:t:h", long_options, &option_index)) != -1) {
  136.         switch (opt) {
  137.             case 'i':
  138.                 g_interval = atoi(optarg);
  139.                 break;
  140.             case 'c':
  141.                 g_count = atoi(optarg);
  142.                 break;
  143.             case 't':
  144.                 g_duration = atoi(optarg);
  145.                 break;
  146.             case 'h':
  147.                 PrintUsage();
  148.                 exit(0);
  149.             default:
  150.                 return -1;
  151.         }
  152.     }
  153.     // 解析命令
  154.     if (optind >= argc) {
  155.         return -1;
  156.     }
  157.     const char *cmd = argv[optind];
  158.     struct {
  159.         const char *name;
  160.         enum CommandType type;
  161.         bool needId;
  162.     } cmdMap[] = {
  163.         {"list", CMD_LIST, false},
  164.         {"enable", CMD_ENABLE, true},
  165.         {"disable", CMD_DISABLE, true},
  166.         {"read", CMD_READ, true},
  167.         {"monitor", CMD_MONITOR, true},
  168.         {nullptr, CMD_NONE, false}
  169.     };
  170.     for (int i = 0; cmdMap[i].name != nullptr; i++) {
  171.         if (strcmp(cmd, cmdMap[i].name) == 0) {
  172.             args->cmd = cmdMap[i].type;
  173.             if (cmdMap[i].needId && optind + 1 < argc && argv[optind + 1][0] != '-') {
  174.                 args->sensorId = atoi(argv[optind + 1]);
  175.             }
  176.             return 0;
  177.         }
  178.     }
  179.     return -1;
  180. }
  181. // 初始化传感器设备
  182. static int32_t InitSensorDev(void)
  183. {
  184.     g_sensorDev = NewSensorInterfaceInstance();
  185.     if (g_sensorDev == nullptr) {
  186.         printf("Failed to get sensor interface instance\n");
  187.         return -1;
  188.     }
  189.     int32_t ret = g_sensorDev->GetAllSensors(&g_sensorInfo, &g_sensorCount);
  190.     if (ret != 0) {
  191.         printf("Failed to get sensor information\n");
  192.         FreeSensorInterfaceInstance();
  193.         g_sensorDev = nullptr;
  194.         return -1;
  195.     }
  196.     return 0;
  197. }
  198. // 释放传感器设备
  199. static void DeinitSensorDev(void)
  200. {
  201.     if (g_sensorDev != nullptr) {
  202.         FreeSensorInterfaceInstance();
  203.         g_sensorDev = nullptr;
  204.     }
  205. }
  206. // 列出所有传感器
  207. static int32_t ListSensors(void)
  208. {
  209.     if (g_sensorInfo == nullptr || g_sensorCount sensorId, info->sensorName);
  210.         info++;
  211.     }
  212.     printf("----------------------------------------\n");
  213.     return 0;
  214. }
  215. // 通过传感器ID获取传感器名称
  216. static const char* GetSensorName(int32_t sensorId)
  217. {
  218.     if (g_sensorInfo == nullptr || g_sensorCount SetBatch(sensorId, g_interval * 1000000, 0);
  219.     if (ret != 0) {
  220.         printf("Failed to set batch for sensor %d\n", sensorId);
  221.         return -1;
  222.     }
  223.     // 使能传感器
  224.     ret = g_sensorDev->Enable(sensorId);
  225.     if (ret != 0) {
  226.         printf("Failed to enable sensor %d\n", sensorId);
  227.         return -1;
  228.     }
  229.     printf("Sensor %d (%s) enabled successfully\n", sensorId, GetSensorName(sensorId));
  230.     return 0;
  231. }
  232. // 使能所有传感器
  233. static int32_t EnableAllSensors(void)
  234. {
  235.     if (g_sensorDev == nullptr || g_sensorInfo == nullptr || g_sensorCount sensorId);
  236.         if (ret != 0) {
  237.             printf("Failed to enable sensor %d\n", info->sensorId);
  238.             return -1;
  239.         }
  240.         info++;
  241.     }
  242.     printf("All sensors enabled successfully\n");
  243.     return 0;
  244. }
  245. // 禁用指定传感器
  246. static int32_t DisableSensor(int32_t sensorId)
  247. {
  248.     if (g_sensorDev == nullptr) {
  249.         printf("Sensor device not initialized\n");
  250.         return -1;
  251.     }
  252.     int32_t ret = g_sensorDev->Disable(sensorId);
  253.     if (ret != 0) {
  254.         printf("Failed to disable sensor %d\n", sensorId);
  255.         return -1;
  256.     }
  257.     printf("Sensor %d (%s) disabled successfully\n", sensorId, GetSensorName(sensorId));
  258.     return 0;
  259. }
  260. // 禁用所有传感器
  261. static int32_t DisableAllSensors(void)
  262. {
  263.     if (g_sensorDev == nullptr || g_sensorInfo == nullptr || g_sensorCount sensorId);
  264.         if (ret != 0) {
  265.             printf("Failed to disable sensor %d\n", info->sensorId);
  266.             return -1;
  267.         }
  268.         info++;
  269.     }
  270.     printf("All sensors disabled successfully\n");
  271.     return 0;
  272. }
  273. // 读取并打印传感器数据
  274. static int32_t ReadAndPrintSensorData(struct SensorEvents **events, int32_t numSensors,
  275.                                     int32_t sensorId, bool readAll, int32_t readCount)
  276. {
  277.     if (readCount >= 0) {
  278.         printf("\nReading data (count: %d):\n", readCount + 1);
  279.     } else {
  280.         printf("\nReading data:\n");
  281.     }
  282.     if (readAll) {
  283.         printf("----------------------------------------\n");
  284.     }
  285.     for (int32_t i = 0; i < numSensors; i++) {
  286.         int32_t currentSensorId = readAll ? g_sensorInfo[i].sensorId : sensorId;
  287.         if (readCount >= 0) {
  288.             printf("\nTrying to read data from sensor %d (%s):\n", currentSensorId, GetSensorName(currentSensorId));
  289.         }
  290.         int32_t ret = g_sensorDev->ReadData(currentSensorId, events[i]);
  291.         if (ret != 0) {
  292.             printf("Failed to read sensor %d (%s) data%s\n",
  293.                    currentSensorId, GetSensorName(currentSensorId),
  294.                    readCount >= 0 ? (", ret=" + std::to_string(ret)).c_str() : "");
  295.             if (readCount >= 0) {
  296.                 fflush(stdout);
  297.             }
  298.             continue;
  299.         }
  300.         // 打印数据
  301.         float *data = reinterpret_cast(events[i]->data);
  302.         printf("Sensor[%d] %s data: ", currentSensorId, GetSensorName(currentSensorId));
  303.         for (int32_t j = 0; j < events[i]->dataLen / sizeof(float); j++) {
  304.             printf("%.2f ", data[j]);
  305.         }
  306.         printf("\n");
  307.     }
  308.     if (readAll) {
  309.         printf("----------------------------------------\n");
  310.     }
  311.     if (readCount >= 0) {
  312.         fflush(stdout);
  313.     }
  314.     return 0;
  315. }
  316. // 读取传感器数据
  317. static int32_t ReadSensorData(int32_t sensorId, bool autoEnable, bool readAll)
  318. {
  319.     if (g_sensorDev == nullptr) {
  320.         printf("Sensor device not initialized\n");
  321.         return -1;
  322.     }
  323.     // 如果是读取所有传感器,需要额外的检查
  324.     if (readAll && (g_sensorInfo == nullptr || g_sensorCount data = (uint8_t *)OsalMemCalloc(sizeof(float) * 3);
  325.         if (events[i]->data == nullptr) {
  326.             printf("Failed to allocate sensor data %d\n", i);
  327.             goto cleanup;
  328.         }
  329.         events[i]->dataLen = sizeof(float) * 3;
  330.     }
  331.     // 如果是自动读取模式,使用循环读取
  332.     if (autoEnable) {
  333.         // 计算读取次数
  334.         int32_t readCount = 0;
  335.         int32_t maxCount = (g_count > 0) ? g_count : INT32_MAX;
  336.         int32_t maxTime = (g_duration > 0) ? g_duration : INT32_MAX;
  337.         OsalTimespec startTime = {0};
  338.         OsalGetTime(&startTime);
  339.         // 循环读取数据
  340.         while (readCount < maxCount && g_running) {
  341.             // 检查是否超时
  342.             OsalTimespec currentTime = {0};
  343.             if (OsalGetTime(¤tTime) == HDF_SUCCESS) {
  344.                 uint64_t elapsedTime = (currentTime.sec - startTime.sec) * 1000 +
  345.                                      (currentTime.usec - startTime.usec) / 1000;
  346.                 if (elapsedTime >= maxTime * 1000) {
  347.                     break;
  348.                 }
  349.             }
  350.             ReadAndPrintSensorData(events, numSensors, sensorId, readAll, readCount);
  351.             readCount++;
  352.             OsalMSleep(g_interval);
  353.         }
  354.     } else {
  355.         // 一次性读取数据
  356.         ReadAndPrintSensorData(events, numSensors, sensorId, readAll);
  357.     }
  358.     // 禁用传感器(如果指定了auto)
  359.     if (autoEnable) {
  360.         if (readAll) {
  361.             DisableAllSensors();
  362.         } else {
  363.             DisableSensor(sensorId);
  364.         }
  365.     }
  366. cleanup:
  367.     // 释放资源
  368.     if (events != nullptr) {
  369.         for (int32_t i = 0; i < numSensors; i++) {
  370.             if (events[i] != nullptr) {
  371.                 if (events[i]->data != nullptr) {
  372.                     OsalMemFree(events[i]->data);
  373.                 }
  374.                 OsalMemFree(events[i]);
  375.             }
  376.         }
  377.         OsalMemFree(events);
  378.     }
  379.     return 0;
  380. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表