zigbee3.0的程序也写了一段时间了,有一些设备的移植也已经完成了,一直想记录一下这个移植的步骤,以便以后回看代码的时候能有一个清晰的思路。恰好最近在搬砖 z-stack 3.0.2 的门锁程序,就借机记录一下。
因为门锁需要串口,所以我直接以窗帘电机的程序作为模板修改
1.修改步骤
- 修改工程类型为End Device,然后修改预编译宏。
SECURE=1
TC_LINKKEY_JOIN
NV_INIT
NV_RESTORE //掉电保存
POWER_SAVING //门锁作为终端设备需要低功耗
NWK_AUTO_POLL
xMT_TASK //不需要MT层的其他功能所以关闭相关预编译宏
xMT_APP_FUNC
xMT_SYS_FUNC
xMT_ZDO_FUNC
xMT_ZDO_MGMT
xMT_APP_CNF_FUNC
LEGACY_LCD_DEBUG //不需要LCD
LCD_SUPPORTED=DEBUG
MULTICAST_ENABLED=FALSE
ZCL_READ
ZCL_WRITE
ZCL_BASIC
ZCL_IDENTIFY
ZCL_SCENES
ZCL_GROUPS
ZCL_REPORTING_DEVICE //门锁需要上报门锁状态信息
ZTOOL_P1 //开启串口,此处使用的是MT层的串口1
ZCL_DOORLOCK //门锁相关预编译宏
- 因为把窗帘的预编译宏取消掉了,所以需要取消掉data.c里面的相关的窗帘的attribute的配置,并按照zcl_specification文档里面的说明(必须的attr文档里一般会标注M)配置好data.c里attribute list。同时,InClusterList以及OutClusterList要添加ZCL_CLUSTER_ID_CLOSURES_DOOR_LOCK。
最后,SimpleDescriptionFormat_t里的DeviceID要记得修改。
// *** DOORLOCK Cluster Attributes ***
{
ZCL_CLUSTER_ID_CLOSURES_DOOR_LOCK,
{ // Attribute record
ATTRID_CLOSURES_LOCK_STATE,
ZCL_DATATYPE_ENUM8,
ACCESS_CONTROL_READ|ACCESS_REPORTABLE,
(void *)&zcl_doorlock_lock_state
}
},
{
ZCL_CLUSTER_ID_CLOSURES_DOOR_LOCK,
{ // Attribute record
ATTRID_CLOSURES_LOCK_TYPE,
ZCL_DATATYPE_ENUM8,
ACCESS_CONTROL_READ,
(void *)&zcl_doorlock_lock_type
}
},
{
ZCL_CLUSTER_ID_CLOSURES_DOOR_LOCK,
{ // Attribute record
ATTRID_CLOSURES_ACTUATOR_ENABLED,
ZCL_DATATYPE_BOOLEAN,
ACCESS_CONTROL_READ,
(void *)&zcl_doorlock_actuator_enable
}
},
{
ZCL_CLUSTER_ID_CLOSURES_DOOR_LOCK,
{ // Attribute record
ATTRID_CLUSTER_REVISION,
ZCL_DATATYPE_UINT16,
ACCESS_CONTROL_READ,
(void *)&zclGenericApp_clusterRevision_all
}
},
- 声明door lock对应的回调结构体并用对应的函数注册此回调结构体,这些结构体和函数一般在对应的cluster.h里面可以找到。要想知道这些回调函数是如何被调用的,则可以进入这个相对应的注册函数实体查看。注意:各注册函数对各个回调的处理不尽相同,我们开发的时候必须要查看函数实体。下面贴出部分应用层初始化代码:
zclGenericApp_TaskID = task_id;
uint8 value_read = 0;
MT_UartInit();//串口初始化,门锁需要用到串口
MT_UartRegisterTaskID(task_id);//注册该事件,注意,该函数必须在MT_UartInit()调用之后才调用
// This app is part of the Home Automation Profile
bdb_RegisterSimpleDescriptor( &zclGenericApp_SimpleDesc );
// Register the ZCL General Cluster Library callback functions
// zclGeneral_RegisterCmdCallbacks( GENERICAPP_ENDPOINT, &zclGenericApp_CmdCallbacks );
// GENERICAPP_TODO: Register other cluster command callbacks here
//注册DoorLock回调结构体
zclClosures_RegisterDoorLockCmdCallbacks( GENERICAPP_ENDPOINT, &zclDoorLock_CmdCallbacks );
// Register the application's attribute list
zcl_registerAttrList( GENERICAPP_ENDPOINT, zclGenericApp_NumAttributes, zclGenericApp_Attrs );
4.编写相关的回调函数并将此函数填写到回调结构体相应位置。此处的回调函数需要查看回调结构体中相关的函数体的定义。注意:每个回调结构体有一些函数是必须的,请参考zcl_specification文档
ZStatus_t zclClosures_DoorLock_CmdCB( zclIncoming_t *pInMsg, zclDoorLock_t *pInCmd )
{
//编写门锁设备接收到DoorLock命令后相关的动作执行代码
return TRUE;
}
static zclClosures_DoorLockAppCallbacks_t zclDoorLock_CmdCallbacks =
{
zclClosures_DoorLock_CmdCB,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
-
编写相关的定时任务、按键处理、串口处理,同时也要处理好网络状态提示,以便用户能清除观察到入网状态。
-
因为门锁是电池设备,所以我们需要开启低功耗模式,开启步骤如下:
<1>.通过添加预编译项POWER_SAVING来使能睡眠模式
<2>.将f8wConfig.cfg文件中的RFD_RCVC_ALWAYS_ON设置为FALSE,DPOLL_RATE、DQUEUED_POLL_RATE以及 DRESPONSE_POLL_RATE都要修改为合适的参数,大小随产品而定
<3>.所有的Z-Stack任务支持powersaving
<4>.所有的定时器任务能取消的尽量取消,如果不能取消的例如定时发送的函数,请尽量增加发送的间隔,因为每一次的发送都会大大拉高平均电流,是否能进入PM3就看是否有定时器任务的存在