设备数据点

更新时间:2023-09-06 10:40:14

数据点,也叫 DP(Data Point 的缩写),有时也叫功能点,是描述一个设备所具有的功能。涂鸦 IoT 开发平台将设备的功能都抽象成功能点,支持数值型、布尔型、枚举型、字符串型、故障型以及 RAW 透传数据。

本文档将介绍基于功能点如何实现设备控制和数据上报功能。

实现方法

  • 通过 tuya_gw_user_dp_reg 接口订阅接收设备 DP,在回调中解析 DP 数据后执行对应的行为。
  • 设备的功能状态发生变化时,调用 DP 上报接口把 DP 数据同步到云端。

实现示例

#include "tuya_gw_dp_mgr.h"

VOID __dp_cmd_obj(IN CONST TY_RECV_OBJ_DP_S *dp)
{
    UINT_T i = 0;
    
    PR_DEBUG("recv soc obj dp, cmd_tp: %d, dtt_tp: %d, dp_cnt: %u", dp->cmd_tp, dp->dtt_tp, dp->dps_cnt);

    for (i = 0; i < dp->dps_cnt; i++) {
        CONST TY_OBJ_DP_S *p_dp_obj = dp->dps + i;
        PR_DEBUG("idx: %d, dpid: %d, type: %d, ts: %u", index, p_dp_obj->dpid, p_dp_obj->type, p_dp_obj->time_stamp);
        switch (p_dp_obj->type) {
            case PROP_BOOL:     { PR_DEBUG("bool value: %d", p_dp_obj->value.dp_bool); break;}
            case PROP_VALUE:    { PR_DEBUG("int value: %d", p_dp_obj->value.dp_value); break;}
            case PROP_STR:      { PR_DEBUG("str value: %s", p_dp_obj->value.dp_str); break;}
            case PROP_ENUM:     { PR_DEBUG("enum value: %u", p_dp_obj->value.dp_enum); break;}
            case PROP_BITMAP:   { PR_DEBUG("bits value: 0x%X", p_dp_obj->value.dp_bitmap); break;}
            default:            { PR_DEBUG("idx: %d dpid: %d type: %d ts: %u is invalid", index, p_dp_obj->dpid, p_dp_obj->type, p_dp_obj->time_stamp); break;}
        }
    }
    // TODO:解析 DP 数据,执行对应的行为

    // 接收到什么数据就上报什么数据作为应答
    OPERATE_RET op_ret = dev_report_dp_json_async(NULL, dp->dps, dp->dps_cnt);
    if (OPRT_OK != op_ret) {
        PR_DEBUG("dev_report_dp_json_async err: %d", op_ret);
    }
}

VOID __dp_cmd_raw(IN CONST TY_RECV_RAW_DP_S *dp)
{
    PR_DEBUG("recv soc raw dp, cmd_tp: %d, dtt_tp: %d, dpid: %d, len: %u", dp->cmd_tp, dp->dtt_tp, dp->dpid, dp->len);

    // 解析 RAW 数据,执行对应的行为
}

/**
 * @brief 查询 DP
 *
 * @param[in] dp_qry 查询的 DP 列表,参考 TY_DP_QUERY_S
 */
VOID __dp_cmd_query(IN CONST TY_DP_QUERY_S *dp_qry)
{
    UINT_T i = 0;

    PR_DEBUG("recv soc dp query");

    if (dp_qry->cnt == 0) {
        PR_WARN("query cnt is 0");
        return;
    } else {
        PR_DEBUG("query cnt: %d", dp_qry->cnt);
        for (i = 0; i < dp_qry->cnt; i++) {
            PR_DEBUG("dpid: %d", dp_qry->dpid[index]);
            // TODO:读取设备功能当前状态并上报
        }
    }
}

/**
 * @brief 订阅设备 DP 接收示例
 */
VOID demo_gw_dp(VOID)
{
    TY_GW_DP_CBS_S dp_cbs = {
        .obj   = __dp_cmd_obj,
        .raw   = __dp_cmd_raw,
        .query = __dp_cmd_query
    };

    tuya_gw_user_dp_reg(&dp_cbs);
    
    return;
}

/**
 * @brief obj dp 上报示例
 */
VOID demo_report_dp(VOID)
{
    TY_OBJ_DP_S dp;
    
    // 布尔类型
    memset(&dp, 0x00, SIZEOF(TY_OBJ_DP_S));
    dp.dpid = 101;
    dp.time_stamp = 0;
    dp.type = PROP_BOOL;
    dp.value.dp_bool = TRUE;
    TUYA_CALL_ERR_LOG(dev_report_dp_json_async(NULL, &dp, 1));

    // 数值类型
    memset(&dp, 0x00, SIZEOF(TY_OBJ_DP_S));
    dp.dpid = 102;
    dp.time_stamp = 0;
    dp.type = PROP_VALUE;
    dp.value.dp_value = 2;
    TUYA_CALL_ERR_LOG(dev_report_dp_json_async(NULL, &dp, 1));
    
    // 字符串类型
    memset(&dp, 0x00, SIZEOF(TY_OBJ_DP_S));
    dp.dpid = 103;
    dp.time_stamp = 0;
    dp.type = PROP_STR;
    dp.value.dp_str = "Hello";
    TUYA_CALL_ERR_LOG(dev_report_dp_json_async(NULL, &dp, 1));
    
    // 字符串类型
    memset(&dp, 0x00, SIZEOF(TY_OBJ_DP_S));
    dp.dpid = 104;
    dp.time_stamp = 0;
    dp.type = PROP_STR;
    dp.value.dp_str = "Hello";
    TUYA_CALL_ERR_LOG(dev_report_dp_json_async(NULL, &dp, 1));
    
    // 枚举类型
    memset(&dp, 0x00, SIZEOF(TY_OBJ_DP_S));
    dp.dpid = 105;
    dp.time_stamp = 0;
    dp.type = PROP_ENUM;
    dp.value.dp_enum = 0;
    TUYA_CALL_ERR_LOG(dev_report_dp_json_async(NULL, &dp, 1));    
}

API 说明

接收 DP

/**
 * @brief 注册网关 DP 处理
 * 
 * @param cb 回调接口,参考 TY_GW_DP_CBS_S
 */
OPERATE_RET tuya_gw_user_dp_reg(TY_GW_DP_CBS_S *cb);

上报 OBJ DP

/**
 * @brief 异步上报格式化 DP
 *
 * @param[in] dev_id  如果是网关 DP 上报该参数为 NULL,否则是设备 ID
 * @param[in] dp_data DP 数据数组
 * @param[in] cnt dp  DP 数据数组的长度
 *
 * @return OPRT_OK 成功,其他错误码请参考 tuya_error_code.h
 */
OPERATE_RET dev_report_dp_json_async(IN CONST CHAR_T *dev_id, 
                                     IN CONST TY_OBJ_DP_S *dp_data,
                                     IN CONST UINT_T cnt)

上报 RAW DP

/**
 * @brief 同步上报透传 DP
 *
 * @param[in] dev_id              如果是网关 DP 上报该参数为 NULL,否则是设备 ID
 * @param[in] dpid                DP ID
 * @param[in] data                透传数据
 * @param[in] len                 透传数据的长度
 * @param[in] timeout             同步超时时间,单位是秒
 * @param[in] enable_auto_retrans 是否开启重传,TRUE 表示重传,FALSE 表示不重传
 *
 * @return OPRT_OK: success  Other: fail
 */
OPERATE_RET dev_report_dp_raw_sync_extend(IN CONST CHAR_T *dev_id, 
                                          IN CONST BYTE_T dpid, \
                                          IN CONST BYTE_T *data, 
                                          IN CONST UINT_T len, \
                                          IN CONST UINT_T timeout, 
                                          IN CONST BOOL_T enable_auto_retrans);
#define dev_report_dp_raw_sync(dev_id, dpid, data, len, timeout) \
    dev_report_dp_raw_sync_extend(dev_id, dpid, data, len, timeout, TRUE)

上报查询的 OBJ DP

/**
 * @brief 异步上报查询的格式化 DP,查询上报不会触发联动
 *
 * @param[in] dev_id  如果是网关 DP 上报该参数为 NULL,否则是设备 ID
 * @param[in] dp_data DP 数据数组
 * @param[in] cnt dp  DP 数据数组的长度
 *
 * @return OPRT_OK 成功,其他错误码请参考 tuya_error_code.h
 */
OPERATE_RET dev_query_dp_json_async(IN CONST CHAR_T *dev_id, 
                                    IN CONST TY_OBJ_DP_S *dp_data, 
                                    IN CONST UINT_T cnt);

上报记录型 OBJ DP

/**
 * @brief 同步上报记录型格式化 DP,记录上报时的时间戳
 *
 * @param[in] dev_id              如果是网关 DP 上报该参数为 NULL,否则是设备 ID
 * @param[in] dp_data             DP 数据数组
 * @param[in] cnt dp              DP 数据数组的长度
 * @param[in] timeout             同步超时时间,单位是秒
 * @param[in] enable_auto_retrans 是否开启重传,TRUE 表示重传,FALSE 表示不重传
 *
 * @return OPRT_OK 成功,其他错误码请参考 tuya_error_code.h
 */
OPERATE_RET dev_report_dp_stat_sync_extend(IN CONST CHAR_T *dev_id, 
                                           IN CONST TY_OBJ_DP_S *dp_data, \
                                           IN CONST UINT_T cnt, 
                                           IN CONST UINT_T timeout, 
                                           IN CONST BOOL_T enable_auto_retrans);
#define dev_report_dp_stat_sync(dev_id, dp_data, cnt, timeout) \
    dev_report_dp_stat_sync_extend(dev_id, dp_data, cnt, timeout, TRUE)