TuyaOS Sensor Hub组件介绍
Sensor Hub 是 TuyaOS 传感器管理组件,可以实现对传感器设备的硬件抽象,设备管理和数据处理。基于 sensor_hub 开发传感器应用时,开发者无需关注传感器的传输协议,只需要对传感器挂载硬件接口、工作方式、采集间隔等进行配置,然后在事件回调中读取传感器处理即可。
通过 Sensor Hub 管理传感器,可快速新增、切换新的传感器,而无需修改上层应用程序。
开发者可使用 tuyaos_sensor_hub_demo_quickstart 体验 Sensor Hub 组件,将多种传感器设备加入到智能设备中,实现更多设备智能化。
Sensor Hub 设计思想
分层设计
Sensor Hub 组件采用软硬件分层设计,分为 sensor hub 逻辑实现层、sensor driver 驱动层,可在驱动层添加新驱动实现新传感器快速接入。
Sensor Hub 层(tdl)
主要功能:
- 对应用提供统一的传感交互接口
- 对传感驱动提供统一的适配接口
- 给应用提供多种比较通用的采集策略
Sensor Driver 层(tdd)
主要功能:
- 传感器实例化
- 对应用提供挂载到 Sensor Hub 上的注册接口
传感数据元素类型抽象
传感上报的数据类型由 Sensor Driver 层配置,即由传感器实例决定。
- 元素型
传感器采集的某一类数据可以根据其物理含义抽象为一种元素 (element),复合型传感则包含多种元素,如温湿度传感器就包含了 2 种元素:温度、湿度。一组数据中包含了 几种元素、各元素名称 (ID)、各元素值的数据类型 均由 Sensor Driver 层配置。
元素值的数据类型可分为整型、浮点型。
- 透传型
传感数据存储的具体格式由 Sensor Driver 层配置,以二进制形式存储。
传感器采集策略
目前 Sensor Hub 支持以下采集策略配置:
数据读取的触发模式
软定时轮询
硬件定时轮询
IO中断
传感数据组缓存 fifo 深度
数据订阅模式
元素组(每次返回都是所有元素数据)
单元素(每次返回仅一种元素数据)
数据订阅规则设定
数据组数
过滤规则(最大值/最小值/步进值)
Sensor Hub 对上数据与接口
数据结构
1. 数据读取的触发模式
Code: Select all
/**
* @brief 采集触发模式
*/
typedef BYTE_T SR_TRIG_MODE_E;
#define SR_MODE_POLL_SOFT_TM 0 // 轮询(软件定时)
#define SR_MODE_POLL_HARD_TM 1 // 轮询(硬件定时)
#define SR_MODE_EXTI 2 // 外部中断(GPIO)
/**
* @brief 工作模式配置
*/
typedef struct {
SR_TRIG_MODE_E trig_mode; // 采集触发方式
UINT_T poll_intv_ms; // 轮询方式:采集间隔(ms)
TUYA_GPIO_NUM_E irq_pin; // 中断方式:中断引脚
TUYA_GPIO_IRQ_E irq_mode; // 中断方式:中断模式
} SR_WORK_MODE_T;
2. 元素型数据订阅规则
Code: Select all
/**
* @brief 元素型数据订阅类型
*/
typedef BYTE_T SR_ELE_SUB_TP_E;
#define SR_ELE_SUB_TP_GROUP 0 // 以组的形式上报应用订阅的所有元素的数据
#define SR_ELE_SUB_TP_SINGLE 1 // 一一上报应用订阅的每个元素的数据
/**
* @brief 过滤规则
*/
typedef union {
struct {
INT_T max; // 最大值
INT_T min; // 最小值
UINT_T step; // 步进值(非0:前后变化低于该值的会被过滤)
} i; // 整型
struct {
FLOAT_T max; // 最大值
FLOAT_T min; // 最小值
FLOAT_T step; // 步进值(非0:前后变化低于该值的会被过滤)
} f; // 浮点型
} SR_FILTETR_U;
/**
* @brief 元素型数据订阅规则
* @note val_num仅在订阅类型为SR_ELE_SUB_TP_SINGLE时有效,且其值不能超过fifo_size
*/
typedef struct {
UCHAR_T id; // 元素ID
UCHAR_T val_num; // 每次订阅的元素值个数
SR_FILTETR_U filter; // 过滤规则
} SR_ELE_SUB_RULE_T;
/**
* @brief 元素型数据订阅配置
* 拓展功能 (可选)
*/
typedef struct {
SR_ELE_SUB_TP_E tp; // 元素型数据订阅方式
UCHAR_T num; // 元素订阅数量,也是元素型数据订阅规则数量
SR_ELE_SUB_RULE_T *rule; // 元素型数据订阅规则
} SR_ELE_SUB_CFG_T;
3. 数据就绪通知回调
Code: Select all
/**
* @brief 元素型数据缓存结构
*/
typedef struct {
UCHAR_T id; // 元素ID
SR_VAL_TP_E val_tp; // 元素值类型
UCHAR_T val_num; // 元素值个数
SR_VAL_U *val; // 元素值(存储地址)
} SR_ELE_BUFF_T;
/**
* @brief 数据就绪通知回调
*/
typedef VOID_T (*SR_ELE_INFORM_CB)(CHAR_T* name, UCHAR_T buf_num, SR_ELE_BUFF_T *ele_data);
typedef VOID_T (*SR_RAW_INFORM_CB)(CHAR_T* name, UINT_T raw_num, SR_RAW_DATA_T *raw_data);
typedef union {
SR_ELE_INFORM_CB ele; // 用于元素型数据
SR_RAW_INFORM_CB raw; // 用于透传型数据
} SR_INFORM_CB_T;
4. 传感设备信息
Code: Select all
/**
* @brief 传感设备注册信息
*/
typedef struct {
SR_WORK_MODE_T mode; // 数据采集模式
SR_INFORM_CB_T inform_cb; // 数据就绪通知回调
UCHAR_T fifo_size; // 存放返回给app数据的缓存大小
SR_ELE_SUB_CFG_T *ele_sub; // 元素型数据订阅模型配置(不使用则写NULL)
} SR_DEV_CFG_T;
/**
* @brief 传感设备句柄
*/
typedef VOID_T* SENSOR_HANDLE_T;
应用接口
1. 创建传感器实例
Code: Select all
/**
* @brief 查找传感设备
* @param[in] dev_name: 传感设备名称
* @param[out] handle: 传感设备句柄
* @return 操作结果
*/
OPERATE_RET tdl_sensor_dev_find(CHAR_T *dev_name, SENSOR_HANDLE_T* handle);
2. 启动传感器
Code: Select all
/**
* @brief 启动传感设备
* @param[in] handle: 传感设备句柄
* @param[in] config: 设备配置参数
* @return 操作结果
*/
OPERATE_RET tdl_sensor_dev_open(SENSOR_HANDLE_T handle, SR_DEV_CFG_T* config);
3. 停止传感器
Code: Select all
/**
* @brief 启动传感设备
* @param[in] handle: 传感设备句柄
* @return 操作结果
*/
OPERATE_RET tdl_sensor_dev_close(SENSOR_HANDLE_T handle);
4. 配置传感器参数
Code: Select all
/**
* @brief 配置传感设备
* @param[in] handle: 传感设备句柄
* @param[in] cmd: 配置命令
* @param[in] param: 配置命令参数
* @return 操作结果
*/
OPERATE_RET tdl_sensor_dev_config(SENSOR_HANDLE_T handle, UCHAR_T cmd, VOID_T *param);
5. 读取传感器实时数据
Code: Select all
/**
* @brief 读取传感实时数据
* @param[in] handle: 设备句柄
* @param[in] ele_num: 元素个数,0表示透传型
* @param[inout] ele_data: 元素型数据,不使用时写NULL
* @param[out] raw_data: 透传型数据,不使用时写NULL
* @return 操作结果
*/
OPERATE_RET tdl_sensor_dev_read(IN SENSOR_HANDLE_T handle, IN UCHAR_T ele_num,
INOUT SR_ELE_DATA_T *ele_data, OUT SR_RAW_DATA_T *raw_data);
Sensor Hub 对下数据与接口
数据结构
元素数据类型配置
Code: Select all
/** * @brief 元素数据类型配置 */ typedef struct { UCHAR_T id; // 元素ID SR_VAL_TP_E val_tp; // 元素值类型 } SR_ELE_CFG_T;
驱动依赖资源信息
Code: Select all
/** * @brief 资源信息 */ typedef struct { UCHAR_T type; // 资源类型(I2C/SPI/...) UCHAR_T port; // 资源端口 VOID_T* handle; // 资源句柄(暂时没有用到) UCHAR_T info[SR_RSRC_INFO_LEN]; // 其他资源信息 } SR_RSRC_T;
驱动接口抽象
Code: Select all
/**
* @brief 驱动接口抽象
*/
typedef struct {
OPERATE_RET (*open)(SR_RSRC_T* dev);
OPERATE_RET (*close)(SR_RSRC_T* dev);
OPERATE_RET (*control)(SR_RSRC_T* dev, UCHAR_T cmd, VOID_T *param);
OPERATE_RET (*read_ele)(SR_RSRC_T* dev, SR_ELE_DATA_T *ele_data, UCHAR_T ele_num);
OPERATE_RET (*read_raw)(SR_RSRC_T* dev, SR_RAW_DATA_T *raw_data);
} SR_INTFS_T;
驱动注册接口
Code: Select all
/**
* @brief 注册传感设备
* @param[in] dev_name: 传感设备名称
* @param[in] intfs: 传感设备操作接口(内存由具体的传感器分配)
* @param[in] ele_num: 传感数据元素个数,0表示采用透传型(内存由具体的传感器分配)
* @param[in] ele_cfg: 每个元素的数据类型配置
* @param[in] resource: 传感设备依赖的资源信息
* @return 操作结果
*/
OPERATE_RET tdl_sensor_register(CHAR_T *dev_name, SR_INTFS_T *intfs, UCHAR_T ele_num, \
SR_ELE_CFG_T *ele_cfg, SR_RSRC_T *resource);
驱动开发流程
- 确定传感数据存储方式,如果选择元素型,则需确定有哪些
元素
及每个元素值的数据类型
; - 确定传感驱动的
外设
类型和需要配置的内容,比如 I2C、SPI ...; - 确定注册设备时需要做哪些处理,有哪些 资源信息 需要暂存至 SensorHub,实现
tdd_sensor_xxx_register
接口;(传感的通用初始化可以在注册时进行,或者使用控制命令进行,即由用户决定何时初始化) - 确定传感是否有启动测量和停止测量命令,实现
open
和close
接口; - 确定传感读数据的过程,实现
read_ele
或read_raw
接口; - 确定除读数据外是否需要增加其他的配置命令,实现
control
接口。
Sensor Hub使用流程
- 调用
tdd_sensor_xxx_register
注册 xxx 设备。 - 调用
tdl_sensor_dev_find
查找 xxx 设备,获得设备句柄(确认 xxx 设备是否注册成功)。 - 调用
tdl_sensor_dev_config
配置 xxx 设备(启动前的一些必要配置;启动后也可通过调用该接口控制设备)。 - 调用
tdl_sensor_dev_open
启动 xxx 设备(在需要启动时调用),同时需要编写数据通知回调函数。 - 调用
tdl_sensor_dev_read
读取 xxx 设备的实时数据(有需要时)。 - 调用
tdl_sensor_dev_close
停止 xxx 设备(在需要停止时调用)。