OpenHarmony sensor test tool 传感器 测试 工具
OpenHarmony 传感器的生态目前还不完善,体现在 hdf_unittest_sensor 功能缺失,只支持 als 读取数据。hdf_unittest_sensor enable 并未真正执行读取动作,只是读取了旧值。hdf_unittest_sensor 在设备没有传感器的情况下必失败,影响 xts 验证。hdi_unittest_sensor 同样功能缺失,甚至不支持数据验证。除 al
·
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 [options] <command> [sensor_id]
sensor_tool (help | -h | --help)
Note: Commands without sensor_id will apply to all sensors
Commands:
list List all sensors
enable [sensor_id] Enable specified sensor
disable [sensor_id] Disable specified sensor
read [sensor_id] Read sensor data once
monitor [sensor_id] Monitor sensor data continuously
Monitor Options:
-i, --interval <ms> Set sampling interval (default: 1000ms)
-c, --count <num> Set number of readings (default: infinite)
-t, --time <sec> Set monitoring duration in seconds (default: infinite)
你可以
使用 enable,read,disable 配合 i2cget,i2cset,
单独调试 hcs 中的 init,enable,disable 序列是否有问题,
or 掩码是否生效(用来排除 OH 代码问题)。
使用 monitor 检查传感器能否正常上报读数,
传感器读数是否会随环境变化而变化。
效果
效果如下
列出所有 sensor
C:\Users\chao>hdc shell sensor_tool list
Available sensors (5):
----------------------------------------
Sensor[0]: ID=6, Name=magnetometer
Sensor[1]: ID=12, Name=proximity
Sensor[2]: ID=5, Name=als
Sensor[3]: ID=2, Name=gyroscope
Sensor[4]: ID=1, Name=accelerometer
----------------------------------------
enable 所有 sensor
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
读取所有 sensor
C:\Users\chao>hdc shell sensor_tool read
Reading data:
----------------------------------------
Sensor[6] magnetometer data: -22.50 -45.15 86.85
Failed to read sensor 12 (proximity) data
Sensor[5] als data: 0.60
Sensor[2] gyroscope data: -6.38 3.19 6.38
Sensor[1] accelerometer data: 0.01 1.76 -10.01
----------------------------------------
自动 enable 并监控读数
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[6] 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[5] als data: 0.60
Trying to read data from sensor 2 (gyroscope):
Sensor[2] gyroscope data: -3.19 4.25 5.32
Trying to read data from sensor 1 (accelerometer):
Sensor[1] accelerometer data: 0.00 1.75 -9.98
----------------------------------------
Reading data (count: 2):
----------------------------------------
Trying to read data from sensor 6 (magnetometer):
Sensor[6] 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[5] als data: 0.60
Trying to read data from sensor 2 (gyroscope):
Sensor[2] gyroscope data: -5.32 2.13 3.19
Trying to read data from sensor 1 (accelerometer):
Sensor[1] accelerometer data: 0.02 1.73 -9.99
----------------------------------------
源码及编译
把下面文件放到 unittest 下面,
仿照 BUILD.gn 里的 hdf_unittest_sensor 改改
重新设置一个编译目标,比如 sensor_tool,然后单编即可
源码
#include <cmath>
#include <cstdio>
#include <unistd.h>
#include <signal.h>
#include <gtest/gtest.h>
#include <securec.h>
#include <string.h>
#include <getopt.h>
#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 [options] <command> [sensor_id]\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 [sensor_id] Enable specified sensor\n");
printf(" disable [sensor_id] Disable specified sensor\n");
printf(" read [sensor_id] Read sensor data once\n");
printf(" monitor [sensor_id] Monitor sensor data continuously\n");
printf("\nMonitor Options:\n");
printf(" -i, --interval <ms> Set sampling interval (default: 1000ms)\n");
printf(" -c, --count <num> Set number of readings (default: infinite)\n");
printf(" -t, --time <sec> 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[optind];
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[i].name != nullptr; i++) {
if (strcmp(cmd, cmdMap[i].name) == 0) {
args->cmd = cmdMap[i].type;
if (cmdMap[i].needId && optind + 1 < argc && argv[optind + 1][0] != '-') {
args->sensorId = atoi(argv[optind + 1]);
}
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 <= 0) {
printf("No sensors available\n");
return -1;
}
printf("Available sensors (%d):\n", g_sensorCount);
printf("----------------------------------------\n");
struct SensorInformation *info = g_sensorInfo;
for (int32_t i = 0; i < g_sensorCount; i++) {
printf("Sensor[%d]: ID=%d, Name=%s\n", i, info->sensorId, info->sensorName);
info++;
}
printf("----------------------------------------\n");
return 0;
}
// 通过传感器ID获取传感器名称
static const char* GetSensorName(int32_t sensorId)
{
if (g_sensorInfo == nullptr || g_sensorCount <= 0) {
return "Unknown";
}
for (int32_t i = 0; i < g_sensorCount; i++) {
if (g_sensorInfo[i].sensorId == sensorId) {
return g_sensorInfo[i].sensorName;
}
}
return "Unknown";
}
// 使能指定传感器
static int32_t EnableSensor(int32_t sensorId)
{
if (g_sensorDev == nullptr) {
printf("Sensor device not initialized\n");
return -1;
}
// 设置采样间隔
int32_t ret = g_sensorDev->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 <= 0) {
printf("No sensors available\n");
return -1;
}
struct SensorInformation *info = g_sensorInfo;
for (int32_t i = 0; i < g_sensorCount; i++) {
int32_t ret = EnableSensor(info->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 <= 0) {
printf("No sensors available\n");
return -1;
}
struct SensorInformation *info = g_sensorInfo;
for (int32_t i = 0; i < g_sensorCount; i++) {
int32_t ret = DisableSensor(info->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[i].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[i]);
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<float*>(events[i]->data);
printf("Sensor[%d] %s data: ", currentSensorId, GetSensorName(currentSensorId));
for (int32_t j = 0; j < events[i]->dataLen / sizeof(float); j++) {
printf("%.2f ", data[j]);
}
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 <= 0)) {
printf("No sensors available\n");
return -1;
}
// 使能传感器(如果指定了auto)
if (autoEnable) {
if (readAll) {
int32_t ret = EnableAllSensors();
if (ret != 0) {
return -1;
}
} else {
int32_t ret = EnableSensor(sensorId);
if (ret != 0) {
return -1;
}
}
}
// 分配事件数据空间
struct SensorEvents **events;
int32_t numSensors = readAll ? g_sensorCount : 1;
events = (struct SensorEvents**)OsalMemCalloc(sizeof(*events) * numSensors);
if (events == nullptr) {
printf("Failed to allocate sensor events array\n");
if (autoEnable) {
if (readAll) {
DisableAllSensors();
} else {
DisableSensor(sensorId);
}
}
return -1;
}
// 初始化所有事件数据空间
for (int32_t i = 0; i < numSensors; i++) {
events[i] = (struct SensorEvents*)OsalMemCalloc(sizeof(*events[i]));
if (events[i] == nullptr) {
printf("Failed to allocate sensor event %d\n", i);
goto cleanup;
}
events[i]->data = (uint8_t *)OsalMemCalloc(sizeof(float) * 3);
if (events[i]->data == nullptr) {
printf("Failed to allocate sensor data %d\n", i);
goto cleanup;
}
events[i]->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[i] != nullptr) {
if (events[i]->data != nullptr) {
OsalMemFree(events[i]->data);
}
OsalMemFree(events[i]);
}
}
OsalMemFree(events);
}
return 0;
}
更多推荐
所有评论(0)