更新时间:2024-11-20 08:51:29下载pdf
子设备接入是网关最重要的能力之一,本文档对子设备接入的关键流程进行详细说明,通过本文档开发者将会了解基于综合 SDK 如何接入子设备。
本文档的前置条件是在涂鸦开发者平台上创建一个子设备产品,详细请参见 创建子设备。
创建子设备产品跟创建网关产品是大同小异的,本小节只介绍关键的步骤,将会演示在涂鸦开发者平台上创建一个三路开关产品。
登录 涂鸦开发者平台。
在 标准类目 中选择 电工 > 开关。
智能化方式选择 产品开发,产品方案选择 自定义方案。
填写产品名称和产品型号,通讯协议选择 Zigbee,这里的通讯协议只作为产品的描述,不影响实际使用,所以无论实际是接入什么类型协议子设备,默认选择 Zigbee 即可。
本文以创建三路开关为例,所以添加了三个标准功能点,分别代表三路控制。
单击 设备面板 选项卡,在 设备面板 页面根据个人偏好,选择合适的 App 面板。
至此,三路开关产品已经创建完成了。
网关是涂鸦云与子设备通讯的桥梁,网关与涂鸦云间的通信逻辑由 SDK 实现,网关与子设备的通信逻辑需要开发者实现,开发者开发的代码称为 应用。
SDK 和应用的交互机制:
通常,网关主控使用串口方式与无线模组通讯,无线模组使用特定的无线协议(如 Zigbee、Bluetooth 等)跟子设备进行无线通讯。
设备入网是子设备通过网关绑定到涂鸦云的过程,也称设备激活。
从 C 端用户的角度来看,标准的操作流程:
打开涂鸦智能 App,选择网关进入网关面板主页,单击 添加子设备,让网关处于允许添加子设备状态;
长按子设备复位按键,让子设备进入配网状态,进入配网状态的子设备定时广播;
子设备加入到网关所在的网络后,网关把子设备绑定到涂鸦云,App 上会显示已入绑定的子设备列表,再单击 完成 结束入网。
设备入网的交互流程示意图:
根据以上示意图,SDK 与应用涉及三部分交互:
代码的实现步骤:
调用 tuya_iot_reg_gw_mgr_cb
接口注册设备管理回调,并实现对应的回调接口。
实现网关与子设备的通信逻辑开发。
子设备入网后,调用 tuya_iot_gw_bind_dev
接口把子设备绑定到涂鸦云。
示例代码:
STATIC BOOL_T __dev_add_cb(CONST GW_PERMIT_DEV_TP_T tp, CONST BOOL_T permit, CONST UINT_T timeout)
{
/** TODO
* permit == TRUE,允许子设备入网,入网超时时间为 timeout,超时禁止子设备入网
* permit == FALSE, 禁止子设备入网
*/
/**
* 以下代码为演示子设备接入,应用收到 SDK 的允许子设备入网通知时:
* a) 直接使用固定的信息绑定子设备。
* b) 绑定之前,检查该子设备是否已绑定,避免重复绑定。
*/
DEV_DESC_IF_S *dev_if = NULL;
CHAR_T *dev_id = "abcdefabcdef";
CHAR_T *pid = "d1xabwgg"; // 涂鸦开发者平台上创建的三路开关
if (permit) {
dev_if = tuya_iot_get_dev_if(dev_id);
if (dev_if && dev_if->bind) {
return TRUE;
}
tuya_iot_gw_bind_dev(DEV_ATTACH_MOD_1, 0, dev_id, pid, "1.0.0");
}
return TRUE;
}
STATIC VOID __dev_bind_cb(CONST CHAR_T *dev_id, CONST OPERATE_RET result)
{
/**
* result != OPRT_OK,绑定失败,移除子设备
* result == OPRT_OK
* a) 使用 tuya_iot_set_dev_hb_cfg 接口配置子设备心跳超时
* b) 读取子设备当前状态并上报
*/
/**
* 以下代码为演示子设备接入,绑定成功时:
* a) 配置子设备心跳超时时间为3分钟,查询次数为3次。
* b) 上报子设备状态。
*/
if (result == OPRT_OK) {
tuya_iot_set_dev_hb_cfg(dev_id, 120, 3, FALSE);
TY_OBJ_DP_S *dps = (TY_OBJ_DP_S *)Malloc(3 * SIZEOF(TY_OBJ_DP_S));
if (dps == NULL) {
return;
}
// 三路开关全开
for (int i = 0; i < 3; i++) {
dps[i].dpid = (i + 1);
dps[i].type = PROP_BOOL;
dps[i].value.dp_bool = TRUE;
}
dev_report_dp_json_async(dev_id, dps, 3);
}
}
/**
* 定义回调处理,入网过程涉及 dev_add 和 dev_bind_ifm 回调
*/
TY_IOT_DEV_CBS_S dev_mgr_cbs = {
.dev_add = __dev_add_cb,
.dev_bind_ifm = __dev_bind_cb,
};
/**
* 参数1:协议类型,tp 合理范围 [DEV_ATTACH_MOD_1, DEV_ATTACH_MOD_10]
* tp < DEV_ATTACH_MOD_1 预留给 SDK
* 参数2:设备管理回调结构体
*/
tuya_iot_reg_gw_mgr_cb(DEV_ATTACH_MOD_1, &dev_mgr_cbs);
涂鸦对设备功能进行了抽象,用功能点来表示。功能点支持数值型、布尔型、枚举型、字符串型、故障型以及 RAW 透传数据,类似 C 语言的数据类型,对嵌入式开发非常友好。
指令下发时,开发者需要把功能点转成特定协议指令下发给子设备,子设备执行完控制指令,要把新状态同步到涂鸦云,涂鸦云以上报信息作为控制的确认响应。
数据上报时,开发者需要把特定协议指令转成功能点上报到涂鸦云。
设备控制的交互流程示意图:
根据以上示意图,SDK 与应用涉及两部分交互:
代码的实现步骤:
调用 tuya_iot_reg_dp_cb
接口注册功能点管理回调,并实现对应的回调接口。
实现网关与子设备的通信逻辑开发。
收到子设备的上报数据,把数据转成功能点,调用 dev_report_dp_json_async
或 dev_report_dp_raw_sync
接口把子设备的功能点数据上报到涂鸦云。
示例代码:
STATIC VOID __dev_cmd_obj_cb(CONST TY_RECV_OBJ_DP_S *cmd)
{
/**
* 回调中实现把 OBJ 类型功能点转成特定协议数据下发给子设备
* a) 读取子设备的 uddd 信息,uddd 是绑定接口的参数,由开发者自定义,用来描述子设备,以方便映射处理
* b) 根据 uddd 把功能点映射到子设备特定协议数据
*/
/**
* 以下代码为演示子设备控制处理,收到控制指令时:
* a) 解析收到的功能点数据并打印。
* b) 直接把收到的数据上报给涂鸦云。
*/
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);
}
STATIC VOID __dev_cmd_raw_cb(CONST TY_RECV_RAW_DP_S *dp)
{
/**
* 回调中实现把 RAW 类型功能点转成特定协议数据下发给子设备
*/
}
TY_IOT_DP_CBS_S dev_dp_cbs = {
.obj = __dev_cmd_obj_cb,
.raw = __dev_cmd_raw_cb,
};
/**
* 参数1:设备类型,可以指定功能点回调是仅子设备、仅网关、还者子设备+网关
* 参数2:协议类型,tp 合理范围 [DEV_ATTACH_MOD_1, DEV_ATTACH_MOD_10]
* tp < DEV_ATTACH_MOD_1 预留给 SDK
* 参数3:功能点管理回调
*/
tuya_iot_reg_dp_cb(DP_DEV, DEV_ATTACH_MOD_1, &dev_dp_cbs);
子设备的在线和离线状态是通过心跳机制来实现的,有两种实现方式:
SDK 实现了心跳管理,采用的是方式1,当心跳超时时,通知应用查询子设备是否在线,应用收到子设备上报的任何信息,都调用 tuya_iot_fresh_dev_hb
接口刷新心跳。
注册心跳超时通知回调:
STATIC VOID __dev_hb_cb(CONST CHAR_T *dev_id)
{
/**
* 回调中查询子设备是否在线,如读取版本号。
* 当收到子设备上报任何消息,都调用 tuya_iot_fresh_dev_hb 接口刷新心跳。
*/
/**
* 以下代码为演示子设备心跳,收到心跳超时时:
* a) 直接调用心跳刷新,让其一直保持在线。
*/
tuya_iot_fresh_dev_hb(dev_id);
}
TY_IOT_DEV_CBS_S dev_mgr_cbs = {
.dev_hb = __dev_hb_cb,
.dev_add = __dev_add_cb,
.dev_bind_ifm = __dev_bind_cb,
};
tuya_iot_reg_gw_mgr_cb(DEV_ATTACH_MOD_1, &dev_mgr_cbs);
SDK 默认的心跳超时是 10 秒,如需要调整心跳超时时间,需要在程序启动的时候遍历所有子设备,然后配置心跳超时时间。
DEV_DESC_IF_S *dev_if = NULL;
VOID *iter = NULL;
dev_if = tuya_iot_dev_traversal(&iter);
while (dev_if) {
if (dev_if->tp == DEV_ATTACH_MOD_1) {
// 读取子设备状态,同步到涂鸦云
// 调用 tuya_iot_set_dev_hb_cfg 设置心跳超时
/**
* 以下代码为演示子设备心跳配置,程序启动时把已入网的子设备心跳超时都配置成 3 分钟。
*/
tuya_iot_set_dev_hb_cfg(dev_if->id, 120, 3, FALSE);
}
}
重置和移除的逻辑比较简单,从 App 上 移除 或 移除并清除数据 时,SDK 触发回调通知应用处理。
注册移除和重置回调:
STATIC VOID __dev_del_cb(CONST CHAR_T *dev_id, CONST GW_DELDEV_TYPE type)
{
/**
* 回调中实现移除子设备逻辑。
* type == GWDEV_DELTYPE_MQTT:MQTT 实时移除。
* type == GWDEV_DELTYPE_SYNC:设备列表同步移除。
*/
}
STATIC VOID __dev_reset_cb(CONST CHAR_T *dev_id, DEV_RESET_TYPE_E type)
{
/**
* 回调中实现重置子设备逻辑。
* type == DEV_REMOTE_RESET_FACTORY:App 移除
* type == DEV_RESET_DATA_FACTORY:激活时需要清除数据
*/
}
TY_IOT_DEV_CBS_S dev_mgr_cbs = {
.dev_del = __dev_del_cb,
.dev_reset = __dev_reset_cb,
.dev_hb = __dev_hb_cb,
.dev_add = __dev_add_cb,
.dev_bind_ifm = __dev_bind_cb,
};
tuya_iot_reg_gw_mgr_cb(DEV_ATTACH_MOD_1, &dev_mgr_cbs);
OTA 是嵌入式设备非常重要的功能,一般嵌入式产品都要求支持 OTA。
本小节将会介绍基于 SDK 开发子设备 OTA 的关键流程,通过本小节开发者将会了解如何实现子设备 OTA。
涂鸦开发者平台从固件 KEY 的维度来管理固件,一个固件 KEY 对应 N 个版本固件,所以在上传固件之前,我们需要先创建固件 KEY。
创建固件 KEY 的步骤如下:
我们在 创建子设备 章节创建了一个三路开关产品,在涂鸦开发者平台产品管理页面选择该产品,单击 继续开发。
进入产品开发页面,单击 硬件开发 选项卡,在 硬件开发 页面选择 新增自定义固件。
在新增固件页面填写信息,完成后单击 生成固件KEY,完成固件 KEY 创建。
关键字段说明:
固件类型:协议类型 < 10 是 SDK 预留,开发者要使用 >= 10,所以此处选择 扩展固件。
升级通道号:与绑定子设备接口的协议类型入参一致。
固件升级超时时间:在超时时间内未上报新的版本号,App 提示升级超时。
上一小节已成功创建固件 KEY,本小节介绍如何上传固件。
单击 新增固件版本。
填写 固件版本,并上传 生产固件 和 升级固件,单击 保存并上架。
说明:此处仅为了演示,上传的固件内容为 “Hello World” 字符串。
上架确认,单击 确认上架。
上一小节已新建一个固件版本,并将固件上传到涂鸦开发者平台,本小节介绍如何添加白名单验证。
展开 更多,选择 OTA升级。
选择我们新创建的固件 KEY,并单击 新建固件升级。
选择刚才新建的固件版本作为 固件版本 ,选择 App 提醒升级 作为 升级方式,并输入版本描述后,单击 确定。
单击 验证,需要输入设备虚拟 ID 添加到白名单,打开 App 进入子设备的面板主页,会提示有新版可升级。
说明:设备虚拟 ID 可以在 App 上查看。进入子设备的面板后,轻按右上角的 “…” 打开高级页面,再轻按 设备信息 就能看到。
子设备 OTA 的交互流程示意图:
SDK 与应用涉及以下几部分交互:
代码实现示例:
STATIC CHAR_T upg_dev[DEV_ID_LEN] = {0};
STATIC OPERATE_RET __dev_ota_data(IN CONST FW_UG_S *fw,
IN CONST UINT_T total_len,
IN CONST UINT_T offset,
IN CONST BYTE_T *data,
IN CONST UINT_T len,
OUT UINT_T *remain_len,
IN PVOID_T pri_data)
{
/**
* 固件数据接收回调接口,在该回调接口中实现把固件数据写入到文件。
*/
/**
* 以下代码为演示子设备固件下载:
* a) 直接把数据打印,没有做保存处理。
* b) 根据下载进度上报进度条。
*/
for (INT_T i = 0; i < len; i++) {
PR_DEBUG_RAW("%02x ", data[i]);
}
PR_DEBUG_RAW("\n");
UINT_T percent = 0;
percent = ((offset * 100) / (total_len+1));
if (percent >= 99) {
percent = 98;
}
tuya_iot_dev_upgd_progress_rept(percent, upg_dev, fw->tp);
return OPRT_OK;
}
STATIC VOID __dev_ota_notify(IN CONST FW_UG_S *fw,
IN CONST INT_T download_result,
IN PVOID_T pri_data)
{
/**
* download_result == OPRT_OK,固件下载成功,通知子设备升级,并把固件发送给子设备。
* download_result != OPRT_OK,固件下载失败,上报升级状态。
*/
/**
* 以下代码为演示子设备升级通知处理:
* 下载成功:上报新版本。
* 下载失败:上报升级状态。
*/
if (download_result == OPRT_OK) {
tuya_iot_gw_subdevice_update(upg_dev, fw->sw_ver);
} else {
tuya_iot_dev_upgd_result_report(upg_dev, fw->tp, 4);
}
}
STATIC VOID __dev_upgrade_cb(CONST CHAR_T *dev_id, CONST FW_UG_S *fw)
{
/**
* 在回调接口中调用固件下载接口,开发者可以根据实际情况添加处理逻辑
*/
strncpy(upg_dev, dev_id, SIZEOF(upg_dev));
tuya_iot_upgrade_dev(dev_id, fw, __dev_ota_data, __dev_ota_notify, NULL);
}
TY_IOT_DEV_CBS_S dev_mgr_cbs = {
.dev_upgrade = __dev_upgrade_cb,
.dev_del = __dev_del_cb,
.dev_reset = __dev_reset_cb,
.dev_hb = __dev_hb_cb,
.dev_add = __dev_add_cb,
.dev_bind_ifm = __dev_bind_cb,
};
tuya_iot_reg_gw_mgr_cb(DEV_ATTACH_MOD_1, &dev_mgr_cbs);
#include <unistd.h>
#include "uni_log.h"
#include "mem_pool.h"
#include "base_os_adapter.h"
#include "tuya_iot_base_api.h"
#include "tuya_iot_com_api.h"
#include "tuya_iot_sdk_api.h"
#include "tuya_iot_sdk_defs.h"
#include "tuya_gw_subdev_api.h"
#if defined(TY_BT_MOD) && (TY_BT_MOD == 1)
#include "tuya_os_adapt_bt.h"
#endif
#define PID "fljmamufiym5fktz" // 替换成自己的产品 ID
#define UUID "tuya461dbc63aeeb991f" // 替换成自己的 UUID
#define AUTHKEY "c8X4PR4wx1gMFaQlaZu5dfgVvVRwB8Ug" // 替换成自己的 AUTHKEY
STATIC CHAR_T upg_dev[DEV_ID_LEN] = {0};
STATIC VOID __gw_reset_cb(GW_RESET_TYPE_E type)
{
PR_DEBUG("gw reset callback, type: %d", type);
if (GW_RESET_DATA_FACTORY != type) {
exit(0);
}
return;
}
STATIC VOID __gw_upgrade_cb(CONST FW_UG_S *fw)
{
PR_DEBUG("gw upgrade callback");
if (fw == NULL) {
PR_ERR("invalid param");
return;
}
PR_DEBUG(" tp: %d", fw->tp);
PR_DEBUG(" fw_url: %s", fw->fw_url);
PR_DEBUG(" sw_ver: %s", fw->sw_ver);
PR_DEBUG(" fw_hmac: %s", fw->fw_hmac);
PR_DEBUG(" file_size: %u", fw->file_size);
return;
}
STATIC VOID __gw_active_stat_cb(GW_STATUS_E status)
{
PR_DEBUG("gw active stat callback, status: %d", status);
return;
}
STATIC VOID __gw_reboot_cb(VOID)
{
PR_DEBUG("gw reboot callback");
exit(0);
return;
}
STATIC VOID __nw_stat_cb(IN CONST SDK_NW_STAT_T stat)
{
PR_DEBUG("network stat: %d", stat);
return;
}
STATIC VOID __wired_stat_cb(IN CONST SDK_WIRED_NW_STAT_T stat)
{
PR_DEBUG("wired stat: %d", stat);
return;
}
STATIC BOOL_T __dev_add_cb(CONST GW_PERMIT_DEV_TP_T tp, CONST BOOL_T permit, CONST UINT_T timeout)
{
/** TODO
* permit == TRUE,允许子设备入网,入网超时时间为 timeout,超时禁止子设备入网
* permit == FALSE, 禁止子设备入网
*/
/**
* 以下代码为演示子设备接入,应用收到 SDK 的允许子设备入网通知时:
* a) 直接使用固定的信息绑定子设备。
* b) 绑定之前,检查该子设备是否已绑定,避免重复绑定。
*/
DEV_DESC_IF_S *dev_if = NULL;
CHAR_T *dev_id = "abcdefabcdef";
CHAR_T *pid = "d1xabwgg"; // 涂鸦开发者平台上创建的三路开关
if (permit) {
dev_if = tuya_iot_get_dev_if(dev_id);
if (dev_if && dev_if->bind) {
return TRUE;
}
tuya_iot_gw_bind_dev(DEV_ATTACH_MOD_1, 0, dev_id, pid, "1.0.0");
}
return TRUE;
}
STATIC VOID __dev_bind_cb(CONST CHAR_T *dev_id, CONST OPERATE_RET result)
{
/**
* result != OPRT_OK,绑定失败,移除子设备
* result == OPRT_OK
* a) 使用 tuya_iot_set_dev_hb_cfg 接口配置子设备心跳超时
* b) 读取子设备当前状态并上报
*/
/**
* 以下代码为演示子设备接入,绑定成功时:
* a) 配置子设备心跳超时时间为3分钟,查询次数为3次。
* b) 上报子设备状态。
*/
if (result == OPRT_OK) {
tuya_iot_set_dev_hb_cfg(dev_id, 120, 3, FALSE);
TY_OBJ_DP_S *dps = (TY_OBJ_DP_S *)Malloc(3 * SIZEOF(TY_OBJ_DP_S));
if (dps == NULL) {
return;
}
// 三路开关全开
for (int i = 0; i < 3; i++) {
dps[i].dpid = (i + 1);
dps[i].type = PROP_BOOL;
dps[i].value.dp_bool = TRUE;
}
dev_report_dp_json_async(dev_id, dps, 3);
}
}
STATIC VOID __dev_hb_cb(CONST CHAR_T *dev_id)
{
/**
* 回调中查询子设备是否在线,如读取版本号。
* 当收到子设备上报任何消息,都调用 tuya_iot_fresh_dev_hb 接口刷新心跳。
*/
/**
* 以下代码为演示子设备心跳,收到心跳超时时:
* a) 直接调用心跳刷新,让其一直保持在线。
*/
tuya_iot_fresh_dev_hb(dev_id);
}
STATIC VOID __dev_del_cb(CONST CHAR_T *dev_id, CONST GW_DELDEV_TYPE type)
{
/**
* 回调中实现移除子设备逻辑。
* type == GWDEV_DELTYPE_MQTT:MQTT 实时移除。
* type == GWDEV_DELTYPE_SYNC:设备列表同步移除。
*/
}
STATIC VOID __dev_reset_cb(CONST CHAR_T *dev_id, DEV_RESET_TYPE_E type)
{
/**
* 回调中实现重置子设备逻辑。
* type == DEV_REMOTE_RESET_FACTORY:App 移除
* type == DEV_RESET_DATA_FACTORY:激活时需要清除数据
*/
}
STATIC OPERATE_RET __dev_ota_data(IN CONST FW_UG_S *fw,
IN CONST UINT_T total_len,
IN CONST UINT_T offset,
IN CONST BYTE_T *data,
IN CONST UINT_T len,
OUT UINT_T *remain_len,
IN PVOID_T pri_data)
{
/**
* 固件数据接收回调接口,在该回调接口中实现把固件数据写入到文件。
*/
/**
* 以下代码为演示子设备固件下载:
* a) 直接把数据打印,没有做保存处理。
* b) 根据下载进度上报进度条。
*/
for (INT_T i = 0; i < len; i++) {
PR_DEBUG_RAW("%02x ", data[i]);
}
PR_DEBUG_RAW("\n");
UINT_T percent = 0;
percent = ((offset * 100) / (total_len+1));
if (percent >= 99) {
percent = 98;
}
tuya_iot_dev_upgd_progress_rept(percent, upg_dev, fw->tp);
return OPRT_OK;
}
STATIC VOID __dev_ota_notify(IN CONST FW_UG_S *fw,
IN CONST INT_T download_result,
IN PVOID_T pri_data)
{
/**
* download_result == OPRT_OK,固件下载成功,通知子设备升级,并把固件发送给子设备。
* download_result != OPRT_OK,固件下载失败,上报升级状态。
*/
/**
* 以下代码为演示子设备升级通知处理:
* 下载成功:上报新版本。
* 下载失败:上报升级状态。
*/
if (download_result == OPRT_OK) {
tuya_iot_gw_subdevice_update(upg_dev, fw->sw_ver);
} else {
tuya_iot_dev_upgd_result_report(upg_dev, fw->tp, 4);
}
}
STATIC VOID __dev_upgrade_cb(CONST CHAR_T *dev_id, CONST FW_UG_S *fw)
{
/**
* 在回调接口中调用固件下载接口,开发者可以根据实际情况添加处理逻辑
*/
strncpy(upg_dev, dev_id, SIZEOF(upg_dev));
tuya_iot_upgrade_dev(dev_id, fw, __dev_ota_data, __dev_ota_notify, NULL);
}
STATIC VOID __dev_cmd_obj_cb(CONST TY_RECV_OBJ_DP_S *cmd)
{
/**
* 回调中实现把 OBJ 类型功能点转成特定协议数据下发给子设备
* a) 读取子设备的 uddd 信息,uddd 是绑定接口的参数,由开发者自定义,用来描述子设备,以方便映射处理
* b) 根据 uddd 把功能点映射到子设备特定协议数据
*/
/**
* 以下代码为演示子设备控制处理,收到控制指令时:
* a) 解析收到的功能点数据并打印。
* b) 直接把收到的数据上报给涂鸦云。
*/
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);
}
STATIC VOID __dev_cmd_raw_cb(CONST TY_RECV_RAW_DP_S *dp)
{
/**
* 回调中实现把 RAW 类型功能点转成特定协议数据下发给子设备
*/
}
STATIC OPERATE_RET __user_init(VOID)
{
OPERATE_RET rt = OPRT_OK;
DEV_DESC_IF_S *dev_if = NULL;
VOID *iter = NULL;
TY_IOT_DP_CBS_S dev_dp_cbs = {
.obj = __dev_cmd_obj_cb,
.raw = __dev_cmd_raw_cb,
};
/**
* 定义回调处理,入网过程涉及 dev_add 和 dev_bind_ifm 回调
*/
TY_IOT_DEV_CBS_S dev_mgr_cbs = {
.dev_upgrade = __dev_upgrade_cb,
.dev_del = __dev_del_cb,
.dev_reset = __dev_reset_cb,
.dev_hb = __dev_hb_cb,
.dev_add = __dev_add_cb,
.dev_bind_ifm = __dev_bind_cb,
};
/**
* 参数1:协议类型,tp 合理范围 [DEV_ATTACH_MOD_1, DEV_ATTACH_MOD_10]
* tp < DEV_ATTACH_MOD_1 预留给 SDK
* 参数2:设备管理回调结构体
*/
TUYA_CALL_ERR_RETURN(tuya_iot_reg_gw_mgr_cb(DEV_ATTACH_MOD_1, &dev_mgr_cbs));
/**
* 参数1:设备类型,可以指定功能点回调是仅子设备、仅网关、还者子设备+网关
* 参数2:协议类型,tp 合理范围 [DEV_ATTACH_MOD_1, DEV_ATTACH_MOD_10]
* tp < DEV_ATTACH_MOD_1 预留给 SDK
* 参数3:功能点管理回调
*/
TUYA_CALL_ERR_RETURN(tuya_iot_reg_dp_cb(DP_DEV, DEV_ATTACH_MOD_1, &dev_dp_cbs));
dev_if = tuya_iot_dev_traversal(&iter);
while (dev_if) {
if (dev_if->tp == DEV_ATTACH_MOD_1) {
// 读取子设备状态,同步到涂鸦云
// 调用 tuya_iot_set_dev_hb_cfg 设置心跳超时
/**
* 以下代码为演示子设备心跳配置,程序启动时把已入网的子设备心跳超时都配置成 3 分钟。
*/
tuya_iot_set_dev_hb_cfg(dev_if->id, 120, 3, FALSE);
}
}
}
int main(int argc, char **argv)
{
OPERATE_RET rt = OPRT_OK;
GW_PROD_INFO_S prod_info = {0};
/* gw base callback */
TY_GW_INFRA_CBS_S gw_cbs = {
.gw_reset_cb = __gw_reset_cb,
.gw_upgrade_cb = __gw_upgrade_cb,
.gw_active_stat_cb = __gw_active_stat_cb,
.gw_reboot_cb = __gw_reboot_cb,
};
#if defined(TY_BT_MOD) && (TY_BT_MOD == 1)
tuya_os_adapt_reg_bt_intf();
#endif
/* initiate os-layer service*/
tuya_os_intf_init();
/* initiate iot-layer service */
TUYA_CALL_ERR_RETURN(tuya_iot_init("./"));
/* set the logging level to debug */
SET_PR_DEBUG_LEVEL(TY_LOG_LEVEL_DEBUG);
PR_DEBUG("SDK INFO: %s", tuya_iot_get_sdk_info());
/* set uuid and authkey */
prod_info.uuid = UUID;
prod_info.auth_key = AUTHKEY;
TUYA_CALL_ERR_RETURN(tuya_iot_set_gw_prod_info(&prod_info));
/* pre-initiate sdk service */
TUYA_CALL_ERR_RETURN(tuya_iot_sdk_pre_init(TRUE));
/* initiate application service, more service in here */
TUYA_CALL_ERR_RETURN(tuya_user_svc_init(&gw_cbs));
TUYA_CALL_ERR_RETURN(__user_init());
/* initiate sdk service */
#if defined(GW_SUPPORT_WIRED_WIFI) && (GW_SUPPORT_WIRED_WIFI==1)
TUYA_CALL_ERR_RETURN(tuya_iot_wired_wf_sdk_init(IOT_GW_NET_WIRED_WIFI, GWCM_OLD, WF_START_AP_ONLY, PID, USER_SW_VER, NULL, 0));
#elif defined(WIFI_GW) && (WIFI_GW==1)
TUYA_CALL_ERR_RETURN(tuya_iot_wf_sdk_init(GWCM_OLD, WF_START_AP_ONLY, PID, USER_SW_VER, NULL, 0));
#else
TUYA_CALL_ERR_RETURN(tuya_iot_sdk_init(PID, USER_SW_VER, NULL, 0));
#endif
/* register net stat notification callback */
TUYA_CALL_ERR_RETURN(tuya_iot_sdk_reg_netstat_cb(__nw_stat_cb, __wired_stat_cb, NULL));
/* start application service, more service in here */
TUYA_CALL_ERR_RETURN(tuya_user_svc_start(NULL));
while (1) {
sleep(10);
}
return 0;
}
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈