子设备 DP 操作

更新时间:2023-09-06 10:18:45下载pdf

DP(Data Point)是描述一个设备对象功能点的抽象方式。DP 操作代表通过预定的功能特性来改变设备的状态,例如使用 开关 DP 来改变一个设备的开启和关闭。

基本概念

  • DP 类型:表示 DP 的取值属性,决定了值的数据类型。DP 的类型可以分为:

    • 对象类型(Object):
      • 布尔型:bool
      • 数值型:value
      • 枚举型:enum
      • 字符型:string
      • 故障型:bitmap
    • 透传类型(Raw)
  • DP 作用:面对海量各式各样的设备,为了规模化和数字化管理这些设备则需要使用一种抽象语言来描述这些设备。使用 DP 描述子设备可以屏蔽底层终端的差异,标准化设备能力,达到低耦合的效果。

  • DP 示例:以一个智能灯泡为例,核心功能可以为 开关调节亮度调节色温 三种。

    开关
    调光
    色温
    DP 1:布尔类型
    DP 2:数值类型
    DP 3:数值类型

功能描述

  • 指令下发时,您需要把 DP 转成特定协议指令下发给子设备。子设备执行完控制指令,要把新状态同步到云端。云端以上报的信息,作为 DP 操作的确认响应。

  • 数据上报时,您需要把特定协议指令转成 DP 上报到云端。

设备控制的交互流程示意图:

AppCloudSDKApplicationSub-deviceSend DP command (MQTT)Send DP command (MQTT)dp_cmd_obj callbackSend dataReport datadev_report_dp_json_asyncReport DP command (MQTT)Report DP command (MQTT)Report DP command (TCP in LAN)AppCloudSDKApplicationSub-device

根据以上示意图,SDK 与应用涉及两部分交互:

  1. SDK 通知应用处理 DP 指令。
  2. 应用调用 SDK 的 DP 上报接口,把子设备的 DP 上报到云端。

使用方法

  • DP 下发

    调用 tuya_subdev_user_sigle_type_reg 接口,注册 子设备操作,并实现对应的DP回调接口。

  • DP 上报

    调用 dev_report_dp_json_asyncdev_report_dp_raw_sync 接口,把子设备的 DP 数据上报到云端。

数据结构

  • 对象类型(Object)DP 结构:

    /**
    * @brief Definition of structured dp
    */
    typedef struct {
    	/** dp id */
    	BYTE_T dpid;
    	/** dp type, see DP_PROP_TP_E */
    	DP_PROP_TP_E type;
    	/** dp value, see TY_OBJ_DP_VALUE_U */
    	TY_OBJ_DP_VALUE_U value;
    	/** dp happen time. if 0, mean now */
    	UINT_T time_stamp;
    } TY_OBJ_DP_S;
    
    /**
    * @brief Definition of received structured dp
    */
    typedef struct {
    	/** see DP_CMD_TYPE_E */
    	DP_CMD_TYPE_E cmd_tp;
    	/** see DP_TRANS_TYPE_T */
    	DP_TRANS_TYPE_T dtt_tp;
    	/** if(NULL == cid), then the cid represents gwid */
    	CHAR_T *cid;
    	/** mb id */
    	CHAR_T *mb_id;
    	/** count of dp */
    	UINT_T dps_cnt;
    	/** the dp data */
    	TY_OBJ_DP_S dps[0];
    } TY_RECV_OBJ_DP_S;
    
  • 透穿类型(Raw)DP 结构:

    typedef struct {
    	/** see DP_CMD_TYPE_E */
    	DP_CMD_TYPE_E cmd_tp;
    	/** see DP_TRANS_TYPE_T */
    	DP_TRANS_TYPE_T dtt_tp;
    	/** if(NULL == cid), then the cid represents gwid */
    	CHAR_T *cid;
    	/** dp id */
    	BYTE_T dpid;
    	/** mb id */
    	CHAR_T *mb_id;
    	/** data len */
    	UINT_T len;
    	/** the data */
    	BYTE_T data[0];
    } TY_RECV_RAW_DP_S;
    

API 说明

子设备接口注册

/**
  * @brief register callback with protocol type
  *
  * @param[in] p_user_dev_node_cbs callback, see TY_GW_SUBDEV_MGR_CBS_S
  * @param[in] user_dev_type       custom protocol type, ranging from 10 to 19
  *
  * @return OPRT_OK on success. For others on error, please refer to tuya_error_code.h
  */
OPERATE_RET tuya_subdev_user_sigle_type_reg(TY_GW_SUBDEV_MGR_CBS_S *p_user_dev_node_cbs, BYTE_T user_dev_type);

子设备注册接口函数。需要您分别实现 Object 类型 DP 命令下发,Raw 类型 DP 命令下发、DP 查询命令、以及其他您需要用到的回调函数。

DP上报到云端

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);

使用该接口可以将 DP 信息异步上报到云端,需要您对 DP 信息进行组装。

使用示例

/**
 * @brief dp( object type ) callback
 * @param[in]     cmd      : struct of dp object type command
 */
STATIC VOID __dev_cmd_obj_cb(CONST TY_RECV_OBJ_DP_S *cmd)
{

     /**
      * TODO:
      *   In this callback, we should change to bus protocol
      *   from DP struct.
      */

     /**
      * Here we have an example :
      *     a) parse the DP value.
      *     b) print out the DP value.
      */
     for (INT_T i = 0; i < cmd->dps_cnt; i++) {
         PR_DEBUG("dpid: %d", cmd->dps[i].dpid);
             switch (cmd->dps[i].type) {
             case PROP_BOOL:
                 PR_DEBUG("dp_bool value: %d", cmd->dps[i].value.dp_bool);
                 break;
             case PROP_VALUE:
                 PR_DEBUG("dp_value value: %d", cmd->dps[i].value.dp_value);
                 break;
             case PROP_ENUM:
                 PR_DEBUG("dp_enum value: %d", cmd->dps[i].value.dp_enum);
                 break;
             case PROP_STR:
                 PR_DEBUG("dp_str value: %s", cmd->dps[i].value.dp_str);
                 break;
             }
     }

     dev_report_dp_json_async(cmd->cid, cmd->dps, cmd->dps_cnt);
}

/**
 * @brief dp( object type ) callback
 * @param[in] TY_GW_STY_GW_SUBDEV_MGR_CBS_S  ruct of dp raw type command
 */
STATIC VOID __dev_cmd_raw_cb(CONST TY_RECV_RAW_DP_S *dp)
{

    /**
     * TODO:
     *      It's raw callback. DIY for the user.
     */
}

TY_GW_SUBDEV_MGR_CBS_S dev_dp_cbs = {
    .dp_cmd_obj   = __dev_cmd_obj_cb,
    .dp_cmd_raw   = __dev_cmd_raw_cb,
};

tuya_subdev_user_sigle_type_reg( &dev_dp_cbs ,  DEV_ATTACH_MOD_1 );