基于Z-stack協(xié)議棧ZCL庫且符合HA規(guī)范的ZigBee應(yīng)用開發(fā)
引言
目前,國內(nèi)市場上ZigBee產(chǎn)品雖然很多,但大多采用 的都是私有協(xié)議棧,阻礙了不同廠家產(chǎn)品之間的互用和替代, 這也是ZigBee市場規(guī)模無法迅速擴(kuò)大的一個(gè)重要原因,因 此,開發(fā)具有符合標(biāo)準(zhǔn)規(guī)范的ZigBee產(chǎn)品成為當(dāng)務(wù)之急。目 前國內(nèi)的ZigBee行業(yè)規(guī)范還正在處于形成階段,但國際上的 ZigBee規(guī)范已經(jīng)建立并受到國際上眾多廠商的追隨,因此, 本文就如何開發(fā)符合ZigBee聯(lián)盟規(guī)定的HA規(guī)范的ZigBee 應(yīng)用進(jìn)行了探討。
Z-stack是TI公司推出的ZigBee協(xié)議棧系統(tǒng),這是一個(gè) 通過ZigBee聯(lián)盟認(rèn)證的符合ZigBee2007規(guī)范的平臺(tái)。借由 TI公司ZigBee芯片及SOC產(chǎn)品在國內(nèi)的廣泛接受,Z-stack 也稱為眾多芯片廠商提供的協(xié)議棧中開發(fā)者接受度比較廣的一 款ZigBee協(xié)議棧。本文探討的ZigBee產(chǎn)品應(yīng)用開發(fā)是基于 Z-stack協(xié)議棧的。
收稿日期:2013-01-30
ZCL 庫(ZigBee cluster library)111
在ZigBee協(xié)議棧中,簇是一組命令和屬性的集合,這些 命令和屬性組合起來,構(gòu)成了實(shí)現(xiàn)某一功能的實(shí)體。
ZCL是由ZigBee聯(lián)盟制定的包含了大量功能簇(cluster) 的大集合。在應(yīng)用開發(fā)中,以ZCL中已有的簇作為功能單元 來使用,可以增強(qiáng)通用性,避免重復(fù)開發(fā)。
ZCL對(duì)功能簇進(jìn)行了分類和描述。每個(gè)功能簇都包含有 一個(gè)或多個(gè)屬性及命令,ZCL對(duì)每個(gè)屬性都進(jìn)行了定義和描 述,包括屬性ID、名稱、數(shù)據(jù)類型、數(shù)值范圍、初始值、可 讀寫性以及強(qiáng)制性;同時(shí),也對(duì)此簇所包含的命令進(jìn)行了定義, 包括命令I(lǐng)D、命令名稱、命令數(shù)據(jù)幀內(nèi)容和觸發(fā)效果等。
ZCL中的通信是基于Client/Server模型的以簇為單位進(jìn) 行的。兩個(gè)不同功能設(shè)備之間的相互通信,是基于某一個(gè)或多 個(gè)功能簇的。用來儲(chǔ)存這些簇屬性的設(shè)備,稱為Server端; 而用來操作這些簇屬性的設(shè)備,稱為Client端。針對(duì)Client/ Server端口類型的不同,同一個(gè)簇也具有不同的屬性和命令。例如,操作屬性的命令,通常由Client端發(fā)送給Server 端;而用針對(duì)這些操作命令的回復(fù),通常由Server端發(fā)送給 Client 端。另外,報(bào)告類型的命令(report attribute command) 通常由Server端發(fā)送給Client端。以O(shè)n/Off簇為例,該簇的 作用是實(shí)現(xiàn)開關(guān)設(shè)備的開/關(guān)狀態(tài)的控制,體現(xiàn)在設(shè)備上,分 為Client端和Server端兩種角色的設(shè)備,比如開關(guān)是Client端, 而某個(gè)具有ZigBee模塊的燈節(jié)點(diǎn)則代表了相應(yīng)的Server端。 Server端作為命令的接收者,必須能夠識(shí)別開/關(guān)/切換這幾 個(gè)來自Client端的命令(在ZCL中,已經(jīng)規(guī)定好這些命令對(duì) 應(yīng)的ID,如0x00代表關(guān),0x01代表開,0x02代表切換),同時(shí), 由于命令操作的是屬性,因此,該Server端必須保存有開關(guān) 狀態(tài)這一屬性。
另外,ZCL制定了基于cluster的各類命令幀的格式(包 括讀、寫、報(bào)告等);定義了用于尋址的各指示參數(shù)(包括規(guī) 范ID、設(shè)備ID、簇ID、屬性ID和命令I(lǐng)D);規(guī)定了用于各 屬性和命令中各類數(shù)據(jù)的數(shù)據(jù)類型;還規(guī)定了在通信中可能 會(huì)出現(xiàn)的所有狀態(tài)的枚舉數(shù)組。
HA(home automation)規(guī)范[2]
HA規(guī)范是由ZigBee聯(lián)盟(ZigBee alliance)制定的對(duì)用 于住宅環(huán)境的各類常見應(yīng)用的設(shè)備描述和操作規(guī)范。通過這 一規(guī)范,為不同廠商的ZigBee HA設(shè)備提供了標(biāo)準(zhǔn)的接口和 定義,確保其相互之間能夠相互通信并協(xié)同工作。
HA規(guī)范的范圍主要集中在對(duì)家用設(shè)備進(jìn)行的實(shí)時(shí)操 作,該規(guī)范可以構(gòu)筑在ZigBee2007的兩個(gè)子規(guī)范(ZigBee、 ZigBee pro)之上。
HA規(guī)范可以簡單分成圍繞網(wǎng)絡(luò)特性的參數(shù)設(shè)置和圍繞 功能實(shí)現(xiàn)的設(shè)備描述分類(包括相應(yīng)設(shè)備的簇以及特性和功 能)這兩大部分的內(nèi)容。
2.1參數(shù)設(shè)置
HA規(guī)范對(duì)涉及到協(xié)議棧各功能方面的一些參數(shù)進(jìn)行 了明確的規(guī)定,例如用于設(shè)備啟動(dòng)時(shí)的啟動(dòng)參數(shù)集(startup attribute sets),要求每個(gè)設(shè)備都必須內(nèi)置這些參數(shù),例如將 PAN ID設(shè)置成0xffff等。還有比如用于網(wǎng)絡(luò)重連接的時(shí)間間 隔、安全中心連接秘鑰等等參數(shù)。
在安全參數(shù)的設(shè)置方面,HA規(guī)范中規(guī)定,設(shè)備的初始 網(wǎng)絡(luò)安全秘鑰(network key)是空的,即每個(gè)設(shè)備的網(wǎng)絡(luò)安全 秘鑰必須由安全中心來統(tǒng)一分配;而安全中心連接秘鑰(trust center link key)是每個(gè)設(shè)備都預(yù)置好的。
2.2設(shè)備描述
HA規(guī)范對(duì)可能會(huì)用到的設(shè)備進(jìn)行了劃分并設(shè)置了相應(yīng)的 ID,在HA網(wǎng)絡(luò)中的每個(gè)終端都必須符合至少一項(xiàng)該分類圖 中給出的設(shè)備描述分類(如果同時(shí)符合多個(gè)設(shè)備描述的話,需 要在自己的設(shè)備描述中枚舉這些設(shè)備類型)。
在HA規(guī)范中,每個(gè)設(shè)備描述都詳細(xì)規(guī)定了其所支持的 簇,以及所支持的特性和功能。以通用設(shè)備中的開關(guān)(On/Off Switch)設(shè)備為例。其所支持的簇如表1所列。
也就是說,如果某個(gè)設(shè)備是開關(guān)的Client端節(jié)點(diǎn),則必 須具有On/Off簇,用以發(fā)出控制On/Off屬性的命令。
針對(duì)每一類設(shè)備,HA規(guī)范都通過特性和功能描述對(duì)其 進(jìn)行行為上的描述,而通過其所包含的cluster來對(duì)其進(jìn)行程 序?qū)用嫔瞎δ苡蚺c接口的界定。從整體上來講,HA規(guī)范中為 一個(gè)設(shè)備應(yīng)該實(shí)現(xiàn)什么以及如何實(shí)現(xiàn)進(jìn)行了明確的說明。
Z-stack中的ZCL庫及使用
Z-stack協(xié)議棧中包含有針對(duì)ZigBee聯(lián)盟的ZCL規(guī)范進(jìn) 行編寫的ZCL庫,用以在自己的協(xié)議棧中支持ZCL的實(shí)現(xiàn)叫 ZCL層API封裝了大量針對(duì)ZCL的包括幀格式、命令I(lǐng)D等 細(xì)節(jié),而只是向開發(fā)者提供了簡單明了的命令函數(shù),通過引入 ZCL層API,可以大大簡化標(biāo)準(zhǔn)化應(yīng)用的開發(fā)。在Z-stack中, 利用ZCL層API開發(fā)符合HA規(guī)范的應(yīng)用的步驟如下叫 3.1 ZCL層的注冊及初始化
首先,必須將ZCL層初始化并注冊到任務(wù)列表中 去。ZCL的初始化是在osalInitTasks函數(shù)中添加zcl_Init( taskID++ )語句,用來給ZCL層的事件分配一個(gè)任務(wù)ID ;注 冊即是在OSAL的任務(wù)列表tasksArr[]中,添加zcl_event_ loop, zcl_event_loop是在zcl.c里定義的用來處理ZCL層事 件的一個(gè)任務(wù)循環(huán)函數(shù)。
ZCL層的注冊和初始化必須放在應(yīng)用層之前。
3.2應(yīng)用層的注冊和初始化
用ZCL來構(gòu)建基于HA規(guī)范的應(yīng)用層,與ZCL層的注 冊和初始化相類似,也必須在任務(wù)列表里添加應(yīng)用層的任務(wù) 循環(huán),并在初始化函數(shù)中進(jìn)行初始化。
應(yīng)用層的初始化主要包括以下幾個(gè)方面。
3.2.1終端節(jié)點(diǎn)的注冊
通過zclHA_Init函數(shù)對(duì)終端節(jié)點(diǎn)進(jìn)行注冊,表明該節(jié)點(diǎn) 是HA規(guī)范中的一個(gè)節(jié)點(diǎn),該注冊過程同時(shí)也包括了該節(jié)點(diǎn)相 應(yīng)功能簇的注冊。
3.2.2 ZCL回調(diào)函數(shù)集的注冊
ZCL中每一類設(shè)備都會(huì)包含一系列與其實(shí)現(xiàn)功能相關(guān)的命令(包括自身發(fā)出的和來自其他設(shè)備的),ZCL回調(diào)函數(shù)集 用以接收并處理這些來自其他設(shè)備發(fā)出的命令。
HA規(guī)范中每個(gè)功能域都有不同的回調(diào)函數(shù)集,用以接收 不同種類的命令。以HA規(guī)范中的General功能域?yàn)槔渌?包含的回調(diào)函數(shù)類型如下:
typedef struct
{
zclGCB_BasicReset_t pfnBasicReset; // Basic Reset zclGCB_Identify _t pfnIdentify; // Identify Response zclGCB_IdentifyQueryRsp_t pfnIdentifyQueryRsp; // Identify Query Rsp
zclGCB_OnOff_t pfnOnOff; // On/Off cluster zclGCB_LevelControlMoveToLevel_t pfnLevelControlMoveTbLevel; // MoveToLevel
zclGCB_LevelControlMove_t pfnLevelControlMove; // Move
zclGCB_LevelControlStep_t pfnLevelControlStep; // Step zclGCB_LevelControlStop_t pfnLevelControlStop; // Stop zclGCB_GroupRsp_t pfnGroupRsp; // Group Response zclGCB_SceneStoreReq_t pfnSceneStoreReq; // Scene Store Request
zclGCB_SceneRecallReq_t pfnSceneRecallReq; // Scene Recall Request
zclGCB_SceneRsp_t pfnSceneRsp; // Scene Response zclGCB_Alarm_t pfnAlarm; // Alarm Req & Rsp zclGCB_Location_t pfnLocation; // RSSI Location zclGCB_LocationRsp_t pfnLocationRsp; // RSSI Location Rsp
} zclGeneral_AppCallbacks_t;
每個(gè)節(jié)點(diǎn)根據(jù)功能域的劃分來選擇對(duì)應(yīng)的回調(diào)函數(shù)集的 類型(例如節(jié)點(diǎn)用到的是General功能域下的某些功能簇,則 使用zclGeneral_AppCallbacks_t類型來構(gòu)建回調(diào)函數(shù)集),并 根據(jù)實(shí)際功能的需要來裁剪和自定義自己的回調(diào)函數(shù)集。
在完成回調(diào)函數(shù)集的構(gòu)建之后,通過調(diào)用相應(yīng)功能 域的注冊函數(shù)來注冊該功能域的回調(diào)函數(shù)集(如要注冊 zclGeneral_AppCallbacks_t類型的回調(diào)函數(shù)集,則需要使用 相應(yīng)的 zclGeneral_RegisterCmdCallbacks 函數(shù))。
3.2.3 ZCL屬性的注冊
每個(gè)簇都有相應(yīng)的一個(gè)或者多個(gè)屬性,在Z-stack中, 簇屬性由zclAttribute_t類型來表征。具體結(jié)構(gòu)如下所示:
typedef struct
{
uintl6 attrId; // Attribute ID
uint8 dataType; // Data Type - defined in AF.h
uint8 accessControl; // Read/write - bit field
void *dataPtr; // Pointer to data field
} zclAttribute_t;
由于每個(gè)簇可能有多個(gè)屬性,并且每個(gè)節(jié)點(diǎn)可以有多個(gè)功 能簇,因此,通過屬性列表zclAttrRec_t類型來表征一個(gè)節(jié) 點(diǎn)所具有的屬性集合。
typedef struct
{
uint16 clusterID; // Cluster ID
zclAttribute_t attr; // Attribute record
} zclAttrRec_t;
開發(fā)人員在構(gòu)建了該應(yīng)用節(jié)點(diǎn)的屬性列表之后,通過zcl_ registerAttrList函數(shù)完成這些屬性的注冊。
3.2.4 ZCL層消息的注冊
由于ZCL是一個(gè)中間層,其負(fù)責(zé)接收并初步處理的一些 消息需要上傳至應(yīng)用層來處理。為了實(shí)現(xiàn)這一功能,需要調(diào)用 zcl_registerForMsg函數(shù)來在應(yīng)用層進(jìn)行注冊,確保經(jīng)ZCL層 預(yù)加工的消息能夠傳達(dá)到應(yīng)用層。
3.2.5其他注冊
其他注冊包括一般應(yīng)用都需要的按鍵事件的注冊、ZDO 層消息的注冊[5]以及一些非HA規(guī)范節(jié)點(diǎn)的注冊等。
3.3應(yīng)用層邏輯的實(shí)現(xiàn)
應(yīng)用層邏輯的開發(fā)與一般應(yīng)用開發(fā)的區(qū)別,主要就是 使用ZCL層API來進(jìn)行命令的發(fā)送,比如當(dāng)觸發(fā)開關(guān)按 鍵時(shí),使用ZCL庫的API來發(fā)送相應(yīng)的命令zclGeneral_ SendOnOff_CmdOn,可以看到,在應(yīng)用層只需寫入這種標(biāo)準(zhǔn) 命令函數(shù),協(xié)議棧會(huì)自動(dòng)調(diào)用下層的函數(shù)庫來進(jìn)行相應(yīng)的操作 并實(shí)現(xiàn)命令的發(fā)送。
另外還需要注意的一點(diǎn)是,在應(yīng)用層的節(jié)點(diǎn)行為以及網(wǎng) 絡(luò)層的參數(shù)設(shè)置上,也必須符合HA規(guī)范給出的限定,例如 PAN ID的設(shè)置、安全相關(guān)的一些秘鑰的初始值設(shè)置以及終端 設(shè)備向父節(jié)點(diǎn)輪詢的時(shí)間間隔等參數(shù)和行為的設(shè)定。
4結(jié)語
可以看到,通過在協(xié)議棧中引入ZCL層,可以大大簡化 符合HA標(biāo)準(zhǔn)的ZigBee應(yīng)用的開發(fā):來自應(yīng)用層的數(shù)據(jù)通過 ZCL層的封裝處理后,實(shí)現(xiàn)了數(shù)據(jù)和命令格式的標(biāo)準(zhǔn)化;同樣, 來自其他設(shè)備或節(jié)點(diǎn)的消息通過ZCL層的分析和提取,能夠 將應(yīng)用層敏感的命令和相關(guān)數(shù)據(jù)直接呈現(xiàn)給應(yīng)用層,從而保 證應(yīng)用層只需關(guān)注于其節(jié)點(diǎn)自身功能的實(shí)現(xiàn),而將繁瑣的標(biāo)準(zhǔn) 化通信任務(wù)交給下層來處理。
20211020_61702baf2afa0__基于Z