Zigbee高频问题集合
持续补充中 。。。 欢迎各位开发者留言支持
持续补充中 。。。 欢迎各位开发者留言支持
PHY622X 平台需安装 keil v5.26 版本
MG21平台需安装IAR for ARM8.4版本
MG24平台需安装IAR for ARM9.3版本
TLSR8258 平台开发框架自带编译链不依赖外部编译器
PHY622X 平台遇到permission error
这是 keil打开时使用ide进行编译,请关闭keil后继续操作
MG2x平台:FileExistsError: 当文件已存在时,无法创建该文件。
问题原因: IDE build 工程时,编译脚本会从\TuyaOS\tools\templates中拷贝模板并扫描应用文件夹下的源文件重新构建IAR工程,如果此时IAR工程已经打开,则会报错。
解决方案: 关闭对应的IAR工程,重新build。
PHY622X平台:No python at ...
TLSR825X平台:prebuild.py execution failed!!!
这是由于依赖的python3.exe 无法正确调用导致的问题,需要注意的是:
1.安装了python3.8并且配置了环境变量。
2.在python3.8安装路径下复制python.exe重命名为python3.exe
3.python3.8环境变量优先级高于其他python版本。
若无法确认是否安装了python3.8,打开cmd,输入where python可看到当前安装的所有python版本
可以的,使用MG21平台调试时,编译脚本已经完成IAR工程配置,一般不用修改,进入调试界面需选择Cortex-M33内核;
问题原因:基于tuyaSDK开发zigbee设备必须支持OTA升级,这种情况大概率是没有烧录bootloader。
解决方案:IDE build之后会在目录TuyaOS\apps\tuyaos_demo_xx\output生成目标文件:
Code: Select all
• tuyaos_demo_xx_DIFF_[version].bin 用于差分ota的升级文件
• tuyaos_demo_xx_QIO_[version].bin 包含bootloader的完整目标文件
• tuyaos_demo_xx_UG_[version].bin OTA升级固件包文件
烧录QIO文件或者单独烧录bootloader文件之后即可正常调试。
bootloader文件在目录TuyaOS\tools\bootloader中,需区分目标平台。
烧录软件在目录TuyaOS\tools\commander中,烧录方式请参考TuyaOS\docs\0_快速入门.md文档的6.6章节。
无线设备的开发和调试,必定需要搭建一个抓包环境,有了这个抓包,可以直观的看到空气中的数据交互,对分析和定位问题有很大的帮助。正所谓磨刀不误砍柴工,zigbee抓包,可以达到事半功倍的效果。那么按照如下步骤,搭建我们自己的抓包环境吧。
硬件: CC2531 USB Dongle
软件:Ubiqua 抓包工具。该工具为付费软件,可以有两个月的免费试用,试用期过了之后,需要购买,65美元每个月。官方下载网址:https://www.ubilogix.com/ubiqua/,我们要多多支持正版哦。
Ubiqua 抓包器,主页面如下:
常用工具介绍:
首先我们要插上我们的抓包器 CC2531 USB Dongle。(若显示设备添加失败,那就下载一个驱动精灵装一下驱动吧)点击菜单栏:Device-->Add Device--,弹出设备添加框:选择“Texas Instruments”,然后选中“Texas Instruments CC2531”,再点“Add Device”
首先我就必须要知道网关的所在信道啦,接下来教大家一个找信道的方法,如果接入的是涂鸦的zigbee网关和涂鸦的app,非常方便哦
涂鸦的app配上我们的涂鸦zigbee网关之后,通过查看,网关的设备信息,可以方便的获取信道。如上图,当前信道在24信道。
然后点击设备上的开关按钮即可开始
添加 Trust Center Link Key 输入5A:69:67:42:65:65:41:6C:6C:69:61:6E:63:65:30:39
点击“Add”添加 Key
到此抓包环境全部搭建好。
抓包器,需要抓到设备和网关完整的整个组网流程,才能将加密的数据的解密出来。我们现在要做的就是组网了。app打开网关组网通道,设备本地触发组网。开启你的无线世界吧。
下图是收到了一部分数据
TUYA网关配网时会读取入网设备basic cluster下6个属性来识别设备,子设备回复数据后,app上就会跳出子设备面板
Zigbee 3.0规定入网流程中需要获取tc link key 如果获取tc link key失败则会离网
Code: Select all
综上:出现配网成功后就离线的问题可能是设备获取tc link key失败,导致该问题的原因可能是:
1.网关读取basic cluster下属性注册到云端,app上刚刚跳出子设备界面后,用户就退出了配网界面,这时候由于退出了配网模式导致设备获取tc link key失败
2.大规模设备配网 并发入网较多,网关进行处理忙碌导致设备获取tc link key没有被响应
3.由于干扰等因素,导致子设备request key,网关transport ,后续的 verify 和confirm 及其 APS ACK没有被响应导致tc link key交互失败
建议使用者采取以下措施规避:
1.使用网关本地按键(短按一下)开启长配网,长配网模式网关会在设备tc link key交互后才会向云端注册,解决了设备还会由于tc link key没有获取到而离线的问题
2.app配网时出现子设备面板界面后不要直接退出界面,在该界面等待 30s ,可以使得网关处于配网状态,便于子设备获取tc link key
3.参考 4.1章节排查wifi干扰对于交互的影响
1.2023年5月9日起,由涂鸦平台Zigbee方案创建pid的新设备,如未购买涂鸦授权码,将默认限制接入。设备需要经过烧录授权才能接入并识别面板
2.网关识别设备并向云端注册需要时间,子设备入网成功提示后需要等待 30s 左右确认是否可以正常跳出面板。
可以查看 3.1 章节 子设备入网时网关会读取子设备 basic cluster下6个属性,其中会通过 manufacturer name 和 mode id
其中涂鸦公版设备 manufacturer name 是由能力值字段+pid字段组成
mode id可以通过该链接确认 Zigbee 对接规范
Zigbee在有干扰的情况下,会经常造成ota失败,如何确认是否存在干扰,请照以下步骤:
或者app市场下载:WiFi魔盒
1.分别在Zigbee设备和网关所处的地方(贴近设备和网关才能真实反映设备状态):打开WiFi魔盒 app--看干扰
2.底部的干扰数,越多表示这里wifi越密集
3.通过tuya app网关界面查看网关信道,然后通过对比wifi密集的wifi信道,和所处zigbee信道如果有重合就说明有干扰
右上角铅笔-设备信息-信道
Code: Select all
• 如上图网关信道20,对应wifi 8和9 信道
• 我们就查看8和9信道下的干扰数.上图所示确实有干扰
有WiFi干扰的情况下,可以通过以下措施改善:
Code: Select all
• 将网关远离WiFi路由器
• 或者是切换并固定wifi信道,是的wifi信道与zigbee信道错开
Code: Select all
DP(Data Point)是描述一个设备对象功能点的抽象方式。DP 操作代表通过预定的功能特性来改变设备的状态,例如使用 开关 DP 来改变一个设备的开启和关闭。涂鸦定义了100以内为涂鸦公版DP,101-255为开发者自定义DP。
Code: Select all
DP常见类型有布尔型、数值型、枚举型、字符型、bitmap、透传(RAW)型。
Code: Select all
自定义DP为终端设备在接入涂鸦云端时,可以通过创建自定义DP进行个性化功能开发。
Code: Select all
#define PRIVATE_ATTR_LIST \
{0x0000, ATTR_INT8U_ATTRIBUTE_TYPE, 1, (ATTR_MASK_TOKEN_FAST|ATTR_MASK_SINGLETON), 0, (UINT8_T*)0x00 }, /* current positiong lift percentage*/\
{0xFFFD, ATTR_INT16U_ATTRIBUTE_TYPE, 2, (ATTR_MASK_READABLE), 0, (UINT8_T *)0x0002},
const TAL_ATTR_T g_private_attr_list[] = {
PRIVATE_ATTR_LIST};
#define DEF_CLUSTER_PRIVATE_CLUSTER_ID(a) \
{ CLUSTER_PRIVATE_TUYA_CLUSTER_ID, (TAL_ATTR_T *)&((a)[0]), GET_ARRAY_LEN((a)) },
CONST TAL_CLUSTER_T app_server_cluster_list[] = {
DEF_CLUSTER_PRIVATE_CLUSTER_ID(g_private_attr_list)
在 apps/xxx_demo/appconfig.json 中修改"manufacture_name":"TZ3210"
需要注意的是,涂鸦面板中的功能与DP一一对应。开发者会定义一些私有DP,但是功能与涂鸦公版DP相同的功能,但是使用公版面板下发功能时,面板下发的为公版的DP。
注:开发时可以使用调试面板进行开发
涂鸦定义了模组与网关交互的命令
Code: Select all
网关下发DP至模组: 0x04
模组应答网关下发DP: 0x05
模组主动上报DP至网关: 0x06
Code: Select all
TAL_MSG_RET_E tal_zcl_specific_msg_recv_callback(TAL_ZCL_MSG_T *msg)
switch(msg->cluster)
case 0xEF00{
switch(msg->command){
case 0x04 :{
air_data_response(msg->dst_ep,
msg->len, &(msg->playload[0]), 0x05, QOS_1)
}
}
}
...
设备应答回复
Code: Select all
air_data_response(uint8_t ep, uint8_t len uint8_t *data, uint8_t command_id TAL_SEND_QOS_E qos ){
tal_system_memset(&send_data, 0, SIZEOF(TAL_ZG_SEND_DATA_T));
send_data.qos = qos;
send_data.delay_time = 0;
send_data.zcl_id = 0x68;
send_data.direction = ZG_ZCL_DATA_SERVER_TO_CLIENT;
send_data.frame_type = ZG_ZCL_FRAME_TYPE_SPEC_TO_CLUSTER;
send_data.command_id = command_id;/*respose cmd 0x05 */
send_data.addr.mode = SEND_MODE_DEV;
send_data.addr.type.dev.cluster_id = 0xEF00;
send_data.addr.type.dev.src_ep = ep;
send_data.data.private.len = len;
memcpy((send_data.data.private.data), data, len);
tal_zg_clear_send_data(ZG_CLEAR_ALL_ZCL_ID, &send_data.zcl_id);
tal_zg_send_data(&send_data, NULL, 2000);
}
Code: Select all
tal_system_memset(&send_data, 0, SIZEOF(TAL_ZG_SEND_DATA_T));
send_data.qos = QOS_1;
send_data.delay_time = 0;
send_data.zcl_id = 0x68;
send_data.direction = ZG_ZCL_DATA_SERVER_TO_CLIENT;
send_data.frame_type = ZG_ZCL_FRAME_TYPE_SPEC_TO_CLUSTER;
send_data.command_id = 0x06;/*report cmd*/
send_data.addr.mode = SEND_MODE_DEV;
send_data.addr.type.dev.dst_addr = TUYA_GATEWAY_ADDRESS;
send_data.addr.type.dev.dst_ep = 0x01;
send_data.addr.type.dev.src_ep = TUYA_PRIMARY_ENDPOINT;
send_data.addr.type.dev.cluster_id = CLUSTER_PRIVATE_TUYA_CLUSTER_ID;
send_data.data.private.len = 7;
send_data.data.private.data[2] = 101; /* DP id*/
send_data.data.private.data[3] = ATTR_ENUM8_ATTRIBUTE_TYPE; /*DP type*/
send_data.data.private.data[4] = 0x00;
send_data.data.private.data[5] = 0x01;/*DP len*/
send_data.data.private.data[6] = day_up_down_change_flag; /*DP data*/
tal_zg_clear_send_data(ZG_CLEAR_ALL_ZCL_ID, &send_data.zcl_id);
tal_zg_send_data(&send_data, NULL, 2000);
1.遇到调用tal_pwm_init()到tal_pwm_start()期间电平不可控时可以使用tkl_pwm_idle_level_set()来配置电平
2.遇到多路pwm 输出不同步时,可以使用tal_pwm_start(0xFF) 多路同时输出
Code: Select all
/*
* zigbee poll configuration
*/
typedef struct {
UINT8_T forever_flag; ///< TRUE: forever poll if device no network(TAL_ZG_NWK_POWER_ON_ONLINE/TAL_ZG_NWK_JOIN_OK/TAL_ZG_NWK_REJOIN_OK)
UINT8_T fast_swicth_parent; ///< TRUE: if ack isn't received, will continue polling until the max number of failures is reached before switching the parent
UINT16_T interval_ms; ///< poll period (bet: ms)
UINT16_T max_failed_times; ///< enter parent-lost status when poll failed x times.
UINT16_T duration_after_data_ms; ///< tiemout waitting app ack (bet: ms)
UINT_T duration_after_join_ms; ///< wakeup time when join success.(for gateway get cluser data) (bet:ms)
UINT_T duration_after_rejoin_ms; ///< wakeup time when rejoin success.(for app use) (bet:ms)
} TAL_ZG_POLL_CFG_T;
Code: Select all
/*
* zigbee end-device rejoin config
*/
typedef struct {
UINT8_T power_on_active; ///< auto rejoin when power on.
UINT8_T send_data_active; ///< auto rejoin when send data if parent lost.
UINT8_T reserved; ///< Reserved
UINT8_T attempts; ///< max rejoin attempts when parent lost.
UINT16_T interval; ///< rejoin attempt interval when parent lost.
} TAL_ZG_REJOIN_CFG_T;
Code: Select all
/**
* @brief register router or sleep device
* @return none
*/
STATIC VOID_T app_sleep_device_node_init(VOID_T)
{
// sleep end device node init
TAL_ZG_NODE_CFG_T node_config = {
.node_type = ZG_SLEEPY_END_DEVICE,
.tx_power = 10,
.scan_interval = 100,
.scan_duration = ZG_SCAN_DURATION_3,
.config.sleep_ed_cfg.poll_config.forever_flag = 1,
.config.sleep_ed_cfg.poll_config.fast_swicth_parent = 1,
.config.sleep_ed_cfg.poll_config.interval_ms = 250,
.config.sleep_ed_cfg.poll_config.max_failed_times = 10,
.config.sleep_ed_cfg.poll_config.duration_after_data_ms = 1000,
.config.sleep_ed_cfg.poll_config.duration_after_join_ms = 60000,
.config.sleep_ed_cfg.poll_config.duration_after_rejoin_ms = 15000,
.config.sleep_ed_cfg.rejoin_config.power_on_active = 1,
.config.sleep_ed_cfg.rejoin_config.send_data_active = 1,
.config.sleep_ed_cfg.rejoin_config.attempts = 3,
.config.sleep_ed_cfg.rejoin_config.interval = 3000,
};
//config zigbee node
tal_zg_node_config(&node_config);
}
Code: Select all
forever_flag 表示在网时设备是否定时发送data request向父节点请求数据;
建议开启forever_flag的设备,一般会有网关下发给该设备数据的机制,比如单火开关;
像门磁等只有状态上报而没有下发交互的设备,可以将forever_flag置为false。
fast_swicth_parent 一般用于forever_flag false 时快速判断是否与父节点断开链接
forever_flag false 时设备通过比如按键等触发数据上报,如果父节点没有数据响应,设备会最多发送 fast poll times+short poll times的data request;这个次数可能没有达到 max_failed_times。这使得一次按键没法让设备触发rejoin,需要多次按键才能让设备进行rejoin。而fast_swicth_parent 置为 TRUE后,一次按键附带的data request将会为max_failed_times 一次就会触发rejoin。
interval_ms 是设置 data request的发送间隔
max_failed_times 是发送多少次data request直到触发rejoin
duration_after_data_ms / interval_ms 是forever_flag = false时,在网发送一次数据后持续的data request次数
duration_after_join_ms / interval_ms 是forever_flag = false时,配网成功时持续的data request次数
duration_after_rejoin_ms / interval_ms 是forever_flag = false时,rejoin成功时持续的data request次数
Code: Select all
power_on_active 是 lost状态 上电主动触发rejoin机制,建议开启
send_data_active 是 lost状态 发数据时触发rejoin机制,建议开启
attempts 是lost状态 触发rejoin机制一组发多少次beacon request
attempts 是lost状态 触发rejoin机制一组隔多久发一次beacon request
如上图所示:一次rejoin尝试3次beacon request,每次beacon request间隔3秒
点击下载目前tuya网关接入的设备dp与zigbee cluster 下attr和command 对应关系文档
如果上述文档所有品类接入的dp list,无法覆盖对应用户需要开发的设备所对应的dp 功能,则建议开发者通用对接方案。
即在 5.1 章的基础上 APP_MODEL_ID 填 TS0601;APP_CAPACITY 填 TZE204
Code: Select all
1.产测部分代码sdk底层托管,应用层不需要再实现相关的串口交互
2.同时需要注意的不要在产测中添加耗时很久的设备操作,比如下图:
在进入产测处理函数中初始化IIC操作的外设,耗时过久导致上位机下发的后续数据设备无法收到
3.无法定位问题时,先将demo编译产物上传涂鸦后台,进行烧录授权,确保demo烧录授权可以正常完成,确保环境没有问题
针对泰凌平台:
1.正常的量产程序,不应该存在抢占式log输出,应避免由此导致的异常
2.开启抢占式串口打印,会在打印时关闭中断源,这使得串口接收异常
手动点赞,太优秀了
标准dp与zigbee cluster下attr和command 的对应关系,下载的文档里,照明调光遥控器里,为什么对应clusterId,attr,command 是空的
你好,这个设备涉及网关群组功能,特殊设备,暂不支持接入
那我这边如何实现通过APP将群组与遥控器的相应按键绑定