新編TinyOS操作系統(tǒng)開發(fā)技術(shù)及實(shí)踐(西電版)第6章TinyOS網(wǎng)絡(luò)協(xié)議課件_第1頁
新編TinyOS操作系統(tǒng)開發(fā)技術(shù)及實(shí)踐(西電版)第6章TinyOS網(wǎng)絡(luò)協(xié)議課件_第2頁
新編TinyOS操作系統(tǒng)開發(fā)技術(shù)及實(shí)踐(西電版)第6章TinyOS網(wǎng)絡(luò)協(xié)議課件_第3頁
新編TinyOS操作系統(tǒng)開發(fā)技術(shù)及實(shí)踐(西電版)第6章TinyOS網(wǎng)絡(luò)協(xié)議課件_第4頁
新編TinyOS操作系統(tǒng)開發(fā)技術(shù)及實(shí)踐(西電版)第6章TinyOS網(wǎng)絡(luò)協(xié)議課件_第5頁
已閱讀5頁,還剩102頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、第6章 TinyOS網(wǎng)絡(luò)協(xié)議 6.1 概述 6.2 分發(fā)路由協(xié)議 6.3 匯聚型路由協(xié)議 6.4 CTP協(xié)議的實(shí)現(xiàn) 小結(jié) 6.1 概述路由協(xié)議一直是無線傳感器網(wǎng)絡(luò)研究的一個(gè)重要方向,在TinyOS 2.x中有兩種基本的多跳路由協(xié)議:分發(fā)路由協(xié)議(Dissemination Protocol)和匯聚型路由協(xié)議(Collection Protocol)。分發(fā)協(xié)議能夠可靠地傳送小數(shù)據(jù)項(xiàng)到網(wǎng)絡(luò)中的每一個(gè)節(jié)點(diǎn);匯聚型路由協(xié)議可以把網(wǎng)絡(luò)中每個(gè)節(jié)點(diǎn)的小數(shù)據(jù)項(xiàng)傳遞到指定的根節(jié)點(diǎn)。本章主要介紹這兩種協(xié)議以及實(shí)現(xiàn)過程。6.2 分發(fā)路由協(xié)議分發(fā)協(xié)議主要用于實(shí)現(xiàn)共享變量的網(wǎng)絡(luò)一致性。網(wǎng)絡(luò)中的每個(gè)節(jié)點(diǎn)都保存有該共享變量

2、的一個(gè)副本。分發(fā)服務(wù)會(huì)通知節(jié)點(diǎn)該變量值更改的時(shí)間,同時(shí)交換數(shù)據(jù)包以達(dá)到整個(gè)網(wǎng)絡(luò)的一致性。在任意給定時(shí)刻,可能會(huì)有兩個(gè)節(jié)點(diǎn)的變量值不相同。但過一段時(shí)間后,不一致的節(jié)點(diǎn)數(shù)會(huì)越來越少,最終整個(gè)網(wǎng)絡(luò)都將同一于一個(gè)相同的變量值。分發(fā)協(xié)議具有以下幾個(gè)特點(diǎn):分發(fā)協(xié)議能夠達(dá)到網(wǎng)絡(luò)的高度一致性,能有效避免臨時(shí)性通信鏈路失效以及高丟包率等網(wǎng)絡(luò)傳輸問題。分發(fā)協(xié)議要求在有鏈路連接的情況下確保能夠達(dá)到某個(gè)變量值一致。對(duì)于不同大小的數(shù)據(jù)項(xiàng),分發(fā)協(xié)議的設(shè)計(jì)會(huì)有很大的不同。以下內(nèi)容將講解分發(fā)協(xié)議的一系列接口和組件,以及具體的實(shí)現(xiàn)過程。6.2.1 相關(guān)接口和組件在TinyOS 2.x中為分發(fā)協(xié)議提供了實(shí)現(xiàn),下面講解涉及到的重要

3、接口和組件。1. 分發(fā)協(xié)議的接口在分發(fā)協(xié)議中分發(fā)服務(wù)提供了兩個(gè)主要的接口:DisseminationValue接口和DisseminationUpdate接口。它們都位于“tinyos-2.x/tos/lib/net/”目錄下。(1) DisseminationValue接口。DisseminationValue接口適用于接收從網(wǎng)絡(luò)中分發(fā)過來的數(shù)據(jù),在此接口中包含兩個(gè)命令函數(shù)和一個(gè)事件函數(shù),其具體代碼如代碼6-1所示。【代碼6-1】 DisseminationValue.ncinterface DisseminationValue command const t* get();command

4、void set( const t* );event void changed();其中,各個(gè)函數(shù)的功能如下所述:DisseminationValue.get()命令獲取const類型的指針指向數(shù)據(jù)區(qū)域。DisseminationValue.set()命令允許節(jié)點(diǎn)改變其當(dāng)前的變量值,并幫助節(jié)點(diǎn)給變量分配一個(gè)初始值。DisseminationValue.changed()觸發(fā)節(jié)點(diǎn)改變變量值的事件。(2) DisseminationUpdate接口。DisseminationUpdate接口用于產(chǎn)生分發(fā)的數(shù)據(jù),此接口只包含一個(gè)命令函數(shù),該命令有一個(gè)指針類型的參數(shù),提供DisseminationUp

5、date接口的組件必須將數(shù)據(jù)賦值到自己分配的內(nèi)存中,DisseminationValue接口必須觸發(fā)change()事件,以此作為對(duì)change()調(diào)用的響應(yīng)。其接口定義如代碼6-2所示?!敬a6-2】 DisseminationUpdate.ncinterface DisseminationUpdate command void change(t* ONE newVal);2. 分發(fā)協(xié)議的組件在分發(fā)協(xié)議中有較多的組件,本文將講解比較重要的組件為DisseminatorC組件,該組件提供了DisseminationValue接口和DisseminationUpdate接口。該組件位于“tiny

6、os-2.x /tos/lib/net/drip”,其具體代碼如代碼6-3所示?!敬a6-3】 DisseminatorC.ncgeneric configuration DisseminatorC(typedef t, dip_key_t key) provides interface DisseminationValue;provides interface DisseminationUpdate;在DisseminatorC組件中提供了兩個(gè)參數(shù):參數(shù)t和參數(shù)key。參數(shù)t:數(shù)據(jù)包結(jié)構(gòu)類型,其大小必須能夠包含單個(gè)message_t包。參數(shù)key:即鍵值key,允許創(chuàng)建不同的Dissemin

7、atorC實(shí)例組件,類似于AM標(biāo)識(shí)號(hào)可以虛擬化AM服務(wù)。該鍵值一般由unique()函數(shù)產(chǎn)生。6.2.2 分發(fā)協(xié)議的實(shí)現(xiàn)以下內(nèi)容將實(shí)現(xiàn)任務(wù)描述6.D.1,使用分發(fā)協(xié)議進(jìn)行小數(shù)據(jù)的發(fā)送接收,當(dāng)節(jié)點(diǎn)收到分發(fā)者發(fā)送的數(shù)據(jù)時(shí),點(diǎn)亮LED。需要以下幾個(gè)步驟:(1) 在“cygwinoptmytinyosapps”目錄下創(chuàng)建myDissemination子目錄。(2) 在myDissemination目錄下創(chuàng)建并編寫myDisseminationApp.nc文件(核心應(yīng)用模塊)、myDisseminationC.nc文件(頂層配件)和BlinkToRadioMsg.h文件(定義相關(guān)數(shù)據(jù)結(jié)構(gòu)體)。(3) 編

8、寫Makefile文件。1. 創(chuàng)建myDissemination文件夾參照6.3.2節(jié)創(chuàng)建MultihopOscilloscope文件夾的步驟創(chuàng)建myDissemination文件夾。創(chuàng)建完成后如圖6-1所示。圖6-1 myDissemination文件夾 2. 編寫程序(1) myDisseminationApp.nc。在myDisseminationApp.nc文件中列出了實(shí)現(xiàn)分發(fā)協(xié)議所需要的一系列組件以及組件與組件的關(guān)系,具體代碼如描述6.D.1 myDisseminationAppC.nc所示。【描述6.D.1】 myDisseminationAppC.nc#define MYID 8

9、configuration myDisseminationAppC implementation components myDisseminationC;components MainC;myDisseminationC.Boot - MainC;components ActiveMessageC;myDisseminationC.RadioControl - ActiveMessageC;components DisseminationC;myDisseminationC.DisseminationControl - DisseminationC;components new Dissemi

10、natorC(uint16_t, 0 x2345) as Object16C;myDisseminationC.Value16 - Object16C;myDisseminationC.Update16 - Object16C;components LedsC;myDisseminationC.Leds - LedsC;components new TimerMilliC();myDisseminationC.Timer - TimerMilliC;components new AMSenderC(MYID);myDisseminationC.AMSend-AMSenderC;myDissem

11、inationC.Packet-AMSenderC;myDisseminationC.AMPacket-AMSenderC;components new AMReceiverC(MYID);myDisseminationC.Receive-AMReceiverC;(2) myDisseminationC.nc。在myDissemination文件中實(shí)現(xiàn)了小數(shù)據(jù)的分發(fā)協(xié)議,首先分發(fā)者獲得需要分發(fā)的數(shù)據(jù),然后將數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)中;接收者接收到數(shù)據(jù)后,按照接收到的數(shù)據(jù)不同點(diǎn)亮不同的LED,具體代碼如描述6.D.1 myDisseminationC.nc所示。【描述6.D.1】 myDisseminat

12、ionC.nc#include #include “BlinkToRadio.h”module myDisseminationC usesinterface AMSend;interface Receive;interface Packet;interface AMPacket;interface Boot;interface SplitControl as RadioControl;interface StdControl as DisseminationControl;interface DisseminationValue as Value16;interface Disseminati

13、onUpdate as Update16;interface Leds;interface Timer;implementation uint16_t counter;am_addr_t DES = 0 x0003;/*點(diǎn)亮LED任務(wù)*/task void ShowCounter()if(counter&0 x1)call Leds.led0On();if(counter&0 x2)call Leds.led1On();if(counter&0 x4)call Leds.led2On();if(counter&0 x8)call Leds.led3On();event void Boot.bo

14、oted() /開啟無線電服務(wù)call RadioControl.start();event void RadioControl.startDone( error_t result ) if ( result != SUCCESS )call RadioControl.start();else/開啟分發(fā)服務(wù)call DisseminationControl.start();counter = 0;/開啟定時(shí)器call Timer.startPeriodic( 2000 );event void RadioControl.stopDone( error_t result ) ;event voi

15、d Timer.fired() message_t pkt;BlinkToRadioMsg* btrpkt;counter = counter+1;/設(shè)定分發(fā)值call Update16.change(&counter);btrpkt=(BlinkToRadioMsg*)call Packet.getPayload(&pkt,sizeof(BlinkToRadioMsg);btrpkt-nodeid = DES;btrpkt-num = counter;/發(fā)送數(shù)據(jù)if(call AMSend.send(AM_BROADCAST_ADDR,&pkt,sizeof(BlinkToRadioMsg)

16、= SUCCESS);/*發(fā)現(xiàn)分發(fā)值發(fā)生變化*/event void Value16.changed() const uint16_t* newVal = call Value16.get();counter = *newVal;/如果數(shù)據(jù)發(fā)送成功,觸發(fā)LED1閃爍event void AMSend.sendDone(message_t* Pkt,error_t err)call Leds.led0Toggle(); /接收部分event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len) if(len=

17、sizeof(BlinkToRadioMsg)/獲得接收信息的負(fù)載BlinkToRadioMsg* btrpkt = (BlinkToRadioMsg*)payload;/取出發(fā)送的數(shù)值counter = btrpkt-num;/觸發(fā)LED閃爍post ShowCounter();return msg;(3) BlinkToRadioMsg.h。在BlinkToRadioMsg.h文件中定義了myDisseminationC.nc文件中發(fā)送數(shù)據(jù)所使用的結(jié)構(gòu)體。其具體代碼如描述6.D.1 BlinkToRadioMsg.h所示?!久枋?.D.1】 BlinkToRadioMsg.h#ifndef

18、 _BLINKTORADIO_H#define _BLINKTORADIO_Htypedef nx_struct BlinkToRadioMsgnx_uint16_t nodeid;nx_uint16_t num;BlinkToRadioMsg;#endif3. 編寫Makefile文件在myDissemination文件夾下創(chuàng)建Makefile文件,并在Makefile文件中添加描述6.D.1 Makefile文件內(nèi)容。【描述6.D.1】 Makefile文件COMPONENT=myDisseminationAppCCFLAGS += -I$(TOSDIR)/lib/net -I%T/lib

19、/net/dripinclude $(MAKERULES)4. 分發(fā)協(xié)議可視化組件程序編譯成功后,在Cygwin下輸入“make cc2530 docs”命令生成可視化組件關(guān)系圖,如圖6-2所示。圖6-2 分發(fā)協(xié)議可視化組件 5. 實(shí)驗(yàn)現(xiàn)象將程序燒寫至設(shè)備中(需要兩個(gè)設(shè)備),可以觀察有以下兩個(gè)現(xiàn)象:設(shè)備的LED1閃爍,說明數(shù)據(jù)發(fā)送成功。設(shè)備的LED1LED4逐個(gè)點(diǎn)亮,說明設(shè)備接收到不同的分發(fā)數(shù)據(jù)。6.3 匯聚型路由協(xié)議6.3.1 概述匯聚型路由協(xié)議是TinyOS中一種基于無線傳感器網(wǎng)絡(luò)應(yīng)用的數(shù)據(jù)匯聚協(xié)議,此協(xié)議需要將網(wǎng)絡(luò)中的數(shù)據(jù)匯聚到某個(gè)節(jié)點(diǎn)上,由此節(jié)點(diǎn)來處理這些數(shù)據(jù)。在匯聚型路由協(xié)議中網(wǎng)絡(luò)中

20、的節(jié)點(diǎn)分為三大類:根節(jié)點(diǎn)、虛擬根節(jié)點(diǎn)和采集節(jié)點(diǎn)。根節(jié)點(diǎn):網(wǎng)絡(luò)中的數(shù)據(jù)最終匯聚到的節(jié)點(diǎn),此節(jié)點(diǎn)負(fù)責(zé)處理整個(gè)網(wǎng)絡(luò)中的數(shù)據(jù)。虛擬根節(jié)點(diǎn):此節(jié)點(diǎn)除了采集數(shù)據(jù)之外還具有中繼傳輸功能,即當(dāng)其他節(jié)點(diǎn)與根節(jié)點(diǎn)的距離超過了通信范圍時(shí),其他節(jié)點(diǎn)將選擇在自己通信范圍內(nèi)的具有中繼功能的節(jié)點(diǎn)作為自己下一條節(jié)點(diǎn),并將此具有中繼功能的節(jié)點(diǎn)認(rèn)為是自己的虛擬根節(jié)點(diǎn)。采集節(jié)點(diǎn):此節(jié)點(diǎn)只負(fù)責(zé)采集數(shù)據(jù),并把采集的數(shù)據(jù)發(fā)往根節(jié)點(diǎn)或虛擬根節(jié)點(diǎn)。匯聚型路由協(xié)議的數(shù)據(jù)傳輸過程如圖6-3所示。其中0號(hào)節(jié)點(diǎn)為根節(jié)點(diǎn),1、3號(hào)節(jié)點(diǎn)為虛擬的根節(jié)點(diǎn),2、4、5、6號(hào)節(jié)點(diǎn)為采集節(jié)點(diǎn)。在圖6-3中,當(dāng)5號(hào)節(jié)點(diǎn)有數(shù)據(jù)需要被收集起來,它就把數(shù)據(jù)沿著樹向上發(fā)送

21、,經(jīng)過3號(hào)和1號(hào)虛擬的根節(jié)點(diǎn)將數(shù)據(jù)發(fā)送至網(wǎng)絡(luò)中的根節(jié)點(diǎn)。根節(jié)點(diǎn)既可以接收虛擬根節(jié)點(diǎn)的數(shù)據(jù)也可以接收采集節(jié)點(diǎn)的數(shù)據(jù);虛擬根節(jié)點(diǎn)既可以接收采集的節(jié)點(diǎn)的數(shù)據(jù)也可以接收其他虛擬根節(jié)點(diǎn)的數(shù)據(jù),且在匯聚協(xié)議中只有根節(jié)點(diǎn)和虛擬根節(jié)點(diǎn)具有接收數(shù)據(jù)的功能,采集節(jié)點(diǎn)是不具有數(shù)據(jù)接收功能的。圖6-3 匯聚型路由協(xié)議 6.3.2 相關(guān)接口和組件1. 匯聚服務(wù)的接口在TinyOS 2.x匯聚服務(wù)中,一個(gè)節(jié)點(diǎn)可以有四種存在方式:生產(chǎn)者、消費(fèi)者、偵聽者和網(wǎng)絡(luò)處理者。根據(jù)存在方式不同,使用不同的接口與匯聚服務(wù)的組件交互。在應(yīng)用程序中,通過匯聚標(biāo)識(shí)號(hào)可以將匯聚服務(wù)多元化,類似于無線通信中的AM標(biāo)識(shí)號(hào)。其中,四種存在方式說明如下

22、:生產(chǎn)者:產(chǎn)生數(shù)據(jù)并將數(shù)據(jù)發(fā)送至根節(jié)點(diǎn)或虛擬根節(jié)點(diǎn)的節(jié)點(diǎn)稱為生產(chǎn)者。生產(chǎn)者使用Send接口把數(shù)據(jù)發(fā)送到匯聚樹的根節(jié)點(diǎn)。匯聚標(biāo)識(shí)號(hào)作為實(shí)例化Send接口的參數(shù)。消費(fèi)者:接收數(shù)據(jù)的節(jié)點(diǎn)稱為消費(fèi)者,消費(fèi)者也是一種虛擬根節(jié)點(diǎn)。偵聽者:無意中收到消息的節(jié)點(diǎn)稱為偵聽者。偵聽者使用Receive接口接收偷聽到的消息,匯聚標(biāo)號(hào)作為實(shí)例化的Receive接口的參數(shù)。能夠處理正在傳遞過程中消息的節(jié)點(diǎn)稱為網(wǎng)絡(luò)處理者。這些網(wǎng)絡(luò)處理者使用Intercept接口接收并更新消息。匯聚標(biāo)識(shí)號(hào)也作為實(shí)例化Intercept接口的參數(shù)。在以上的描述中所用的接口有Send接口、Receive接口、Intercept接口,除去這三個(gè)

23、接口還有一個(gè)比較重要的接口RootControl接口。(1) Send.nc。Send接口的主要功能是發(fā)送數(shù)據(jù)以及獲得數(shù)據(jù)負(fù)載的長度,此接口有4個(gè)命令函數(shù),1個(gè)事件觸發(fā)函數(shù),其接口如代碼6-4所示?!敬a6-4】 Send.nc#include #include interface Send command error_t send(message_t* msg, uint8_t len);command error_t cancel(message_t* msg);event void sendDone(message_t* msg, error_t error);command uint8

24、_t maxPayloadLength();command void* getPayload(message_t* msg, uint8_t len);其中,各個(gè)函數(shù)功能描述如下:send()函數(shù)主要功能是發(fā)送數(shù)據(jù),它決定了發(fā)送數(shù)據(jù)的最大長度。cancel()函數(shù)主要功能是取消當(dāng)前要發(fā)送的數(shù)據(jù)命令。sendDone()函數(shù)為觸發(fā)發(fā)送事件函數(shù),如果發(fā)送成功則返回SUCCESS,失敗則返回FAIL。maxPayloadLength()函數(shù)主要功能是獲得負(fù)載數(shù)據(jù)的最大長度。getPayload()函數(shù)主要功能是獲得需要發(fā)送的數(shù)據(jù)以及發(fā)送數(shù)據(jù)的長度。(2) Receive.nc。Receive接口主要

25、功能是接收生產(chǎn)者的數(shù)據(jù),此接口中只有一個(gè)函數(shù),其具體代碼如代碼6-5所示。【代碼6-5】 Receive.ncinterface Receive event message_t* receive(message_t* msg, void* payload, uint8_t len);(3) Intercept.nc。Intercept接口主要功能是共網(wǎng)絡(luò)處理者接收并更新消息,此接口只有一個(gè)事件函數(shù),其具體代碼如代碼6-6所示?!敬a6-6】 Intercept.ncinterface Intercept event bool forward(message_t* msg, void* payl

26、oad, uint8_t len);Intercept.forward事件的主要功能是當(dāng)節(jié)點(diǎn)接收到一個(gè)要轉(zhuǎn)發(fā)的消息包時(shí),匯聚服務(wù)應(yīng)當(dāng)觸發(fā)這個(gè)事件。如果該事件的返回值為FASLE,那么匯聚服務(wù)就不能轉(zhuǎn)發(fā)這個(gè)包。此接口允許更高層的組件檢查消息包的內(nèi)部,如果這個(gè)消息包多余,或者消息包可以匯聚到已有消息包內(nèi),此時(shí)可以通過此接口事件對(duì)消息進(jìn)行相應(yīng)處理。(4) RootControl.nc。匯聚樹型路由協(xié)議的網(wǎng)絡(luò)是通過根節(jié)點(diǎn)以及到根節(jié)點(diǎn)的路徑構(gòu)成的,其中根節(jié)點(diǎn)的設(shè)定是通過RootControl接口來設(shè)定的,RootControl接口中有三個(gè)命令函數(shù),在此接口的具體代碼如代碼6-7所示。【代碼6-7】 Ro

27、otControl.ncinterface RootControl command error_t setRoot();command error_t unsetRoot();command bool isRoot();其中,setRoot命令和unsetRoot命令的調(diào)用必須返回SUCCESS,否則返回FAIL;而isRoot命令則是根據(jù)setRoot命令和unsetRoot命令的返回值來決定自己的返回值。具體使用如下:如果一個(gè)節(jié)點(diǎn)已經(jīng)是根節(jié)點(diǎn),并調(diào)用setRoot命令,則返回SUCCESS。如果setRoot命令返回SUCCESS,那么isRoot命令的調(diào)用必須返回TRUE。如果unset

28、Root命令的調(diào)用返回SUCCESS,那么isRoot命令必須返回FALSE。2. 匯聚服務(wù)組件匯聚服務(wù)主要通過CollectionC組件、CollectionSenderC組件和CollectionSenderP組件來進(jìn)行匯聚服務(wù)的,具體介紹如下。(1) CollectionC.nc。匯聚服務(wù)必須提供CollectionC組件,并且大多數(shù)的匯聚協(xié)議的接口是由Collection組件來提供的,CollectionC組件的具體實(shí)現(xiàn)如代碼6-8所示。【代碼6-8】 CollectionC.ncconfiguration CollectionC provides interface StdContr

29、ol; interface Senduint8_t client; interface Receivecollection_id_t id; interface Receive as Snoopcollection_id_t; interface Interceptcollection_id_t id; interface Packet; interface CollectionPacket; interface CtpPacket; interface CtpInfo; interface CtpCongestion; interface RootControl; uses interfac

30、e CollectionIduint8_t client; interface CollectionDebug; implementation components CtpP; StdControl = CtpP; Send = CtpP; Receive = CtpP.Receive; Snoop = CtpP.Snoop; Intercept = CtpP; Packet = CtpP; CollectionPacket = CtpP; CtpPacket = CtpP; CtpInfo = CtpP; CtpCongestion = CtpP; RootControl = CtpP; C

31、ollectionId = CtpP; CollectionDebug = CtpP;在使用CollectionC組件時(shí)需要注意以下幾個(gè)方面:CollectionC組件不能在非根節(jié)點(diǎn)或虛擬根節(jié)點(diǎn)上觸發(fā)Receive.Receive事件。當(dāng)一個(gè)數(shù)據(jù)包成功地到達(dá)根節(jié)點(diǎn)時(shí),此組件才可能會(huì)觸發(fā)此事件。如果CollectionC組件接收到一個(gè)需轉(zhuǎn)發(fā)的數(shù)據(jù)包,且當(dāng)前節(jié)點(diǎn)不是根節(jié)點(diǎn),就可能會(huì)觸發(fā)Intercept.forward事件。如果CollectionC組件接收到一個(gè)本該由其他節(jié)點(diǎn)轉(zhuǎn)發(fā)的消息包,就可能會(huì)觸發(fā)Snoop.receive事件。用戶使用RootControl接口可以使節(jié)點(diǎn)稱為匯聚樹協(xié)議的根節(jié)

32、點(diǎn)。(2) CollectionSenderC.nc。CollectionSendC組件是一個(gè)通用組件,它提供了Send接口和Packet接口,并且兩個(gè)接口是通過CollectionSenderP來實(shí)現(xiàn)的,CollectionSenderC組件具體代碼如代碼6-9所示?!敬a6-9】 CollectionSenderC.ncgeneric configuration CollectionSenderC(collection_id_t collectid) provides interface Send; interface Packet; implementation components n

33、ew CollectionSenderP(collectid, unique(UQ_CTP_CLIENT); Send = CollectionSenderP; Packet = CollectionSenderP;(3) CollectionSenderP.nc。CollectionSenderP組件提供了兩個(gè)接口:Send接口和Packet接口。CollectionSenderP組件通過綁定Send接口和Packet接口到CollectionC組件上實(shí)現(xiàn),CollectionSenderP組件的具體代碼如代碼6-10所示?!敬a6-10】 CollectionSenderP.ncgener

34、ic configuration CollectionSenderP(collection_id_t collectid, uint8_t clientid) provides interface Send; interface Packet; implementation components CollectionC as Collector; components new CollectionIdP(collectid); Send = Collector.Sendclientid; Packet = Collector.Packet; Collector.CollectionIdclie

35、ntid - CollectionIdP;6.4 CTP協(xié)議的實(shí)現(xiàn)6.4.1 CTP協(xié)議概述CTP協(xié)議是基于樹的匯聚協(xié)議,網(wǎng)絡(luò)中的某些節(jié)點(diǎn)將自己設(shè)置為根節(jié)點(diǎn),而其他節(jié)點(diǎn)形成以此根節(jié)點(diǎn)為中心的路由樹。CTP協(xié)議有以下兩個(gè)特點(diǎn):節(jié)點(diǎn)并不是向固定的根節(jié)點(diǎn)發(fā)送數(shù)據(jù)包,而是選擇虛擬根節(jié)點(diǎn)作為下一跳發(fā)送數(shù)據(jù)節(jié)點(diǎn)。虛擬根節(jié)點(diǎn)根據(jù)路由梯度形成到根節(jié)點(diǎn)的路由。CTP協(xié)議的總體架構(gòu)由三部分組成:鏈路估計(jì)器、路由引擎以及轉(zhuǎn)發(fā)引擎。其協(xié)議總體架構(gòu)如圖6-4所示。圖6-4 CTP總體架構(gòu) 其中,各個(gè)部分的功能如下:鏈路估計(jì)器:位于最底層,負(fù)責(zé)估計(jì)節(jié)點(diǎn)與鄰居節(jié)點(diǎn)之間的單跳鏈路質(zhì)量,并維護(hù)一個(gè)鄰居表。路由引擎:位于中間層,

36、使用鏈路估計(jì)器提供的信息,選擇到根節(jié)點(diǎn)傳輸代價(jià)最小的節(jié)點(diǎn)作為父節(jié)點(diǎn),并維護(hù)一個(gè)路由表。轉(zhuǎn)發(fā)引擎:維護(hù)本地包和轉(zhuǎn)發(fā)包的發(fā)送隊(duì)列,選擇適當(dāng)?shù)臅r(shí)機(jī)把隊(duì)頭的包送給父節(jié)點(diǎn)。1. 鏈路估計(jì)器CTP的鏈路估計(jì)器主要由鏈路估計(jì)交換子協(xié)議LEEP(Link Estimation Exchange Protocol)來完成,節(jié)點(diǎn)使用LEEP來估計(jì)和交換其與鄰居節(jié)點(diǎn)間的鏈路質(zhì)量信息。在TinyOS 2.x的CTP協(xié)議中,LEEP協(xié)議的實(shí)現(xiàn)是通過LinkEstimatorP組件來實(shí)現(xiàn)的。LinkEstimatorP組件的實(shí)現(xiàn)有兩種形式:一是標(biāo)準(zhǔn)的LE實(shí)現(xiàn),其實(shí)現(xiàn)代碼在“mytinyos/tos/lib/net/le”

37、中。一種是更精確的4BITLE實(shí)現(xiàn),其實(shí)現(xiàn)代碼在“mytinyos/tos/lib/net/4bitle”中。LE估計(jì)器和4BITLE估計(jì)器的實(shí)現(xiàn)在結(jié)構(gòu)上大體相同,不同的是4BITLE估計(jì)器提取的物理層、鏈路層以及網(wǎng)絡(luò)層的反饋信息能夠提高鏈路估計(jì)的精確值。因此本書中采用4BITLE的估計(jì)器。該組件的具體代碼如代碼6-11所示?!敬a6-11】 LinkEstimatorP.ncmodule LinkEstimatorP provides interface StdControl; interface AMSend as Send; interface Receive; interface Li

38、nkEstimator; interface Init; interface Packet; interface CompareBit; uses interface AMSend; interface AMPacket as SubAMPacket; interface Packet as SubPacket; interface Receive as SubReceive; interface LinkPacketMetadata; interface Random; LinkEstimatorP組件除了發(fā)送和接收消息外,還可以通過收到的消息計(jì)算雙向通信鏈路質(zhì)量,并通過判斷通信鏈路質(zhì)量添加

39、和刪除鄰居節(jié)點(diǎn)。(1) 判斷通信鏈路質(zhì)量。LinkEstimatorP組件通信鏈路質(zhì)量的獲得是通過LinkEstimator接口來進(jìn)行的。該接口提供了txAck( )、txNoAck( )和clearDLQ( )等命令,通過這些命令能根據(jù)到鄰居節(jié)點(diǎn)的數(shù)據(jù)傳輸成功與否來更新鏈路估計(jì)值。其中各個(gè)命令的作用如下。txAck:當(dāng)節(jié)點(diǎn)接收到一個(gè)數(shù)據(jù)的確認(rèn)幀后,表明接收一條數(shù)據(jù)成功,并且將更新此信息發(fā)送者和接收者之間的鏈路估計(jì)值。具體源碼如代碼6-12所示?!敬a6-12】 LinkEstimatorP.nccommand error_t LinkEstimator.txAck(am_addr_t nei

40、ghbor) neighbor_table_entry_t *ne;uint8_t nidx = findIdx(neighbor);if (nidx = INVALID_RVAL) return FAIL;ne = &NeighborTablenidx;ne-data_success+;ne-data_total+;if (ne-data_total = DLQ_PKT_WINDOW) updateDETX(ne); return SUCCESS; txNoAck:當(dāng)節(jié)點(diǎn)沒有接收到數(shù)據(jù)的確認(rèn)幀時(shí),同樣也更新發(fā)送節(jié)點(diǎn)與接收節(jié)點(diǎn)的鏈路估計(jì)值。具體源碼如代碼6-13所示。【代碼6-13】 Link

41、EstimatorP.nccommand error_t LinkEstimator.txNoAck(am_addr_t neighbor) neighbor_table_entry_t *ne;uint8_t nidx = findIdx(neighbor);if (nidx = INVALID_RVAL) return FAIL;ne = &NeighborTablenidx;ne-data_total+;if (ne-data_total = DLQ_PKT_WINDOW) updateDETX(ne);return SUCCESS;clearDLQ:當(dāng)參數(shù)改變時(shí),清除原來數(shù)據(jù)的鏈路估計(jì)

42、值。具體源碼如代碼6-14所示。【代碼6-14】 LinkEstimatorP.nccommand error_t LinkEstimator.clearDLQ(am_addr_t neighbor) neighbor_table_entry_t *ne;uint8_t nidx = findIdx(neighbor);if (nidx = INVALID_RVAL) return FAIL;ne = &NeighborTablenidx;ne-data_total = 0;ne-data_success = 0;return SUCCESS;(2) 鄰居節(jié)點(diǎn)的添加。鄰居節(jié)點(diǎn)的添加是通過Lin

43、kPacketMetadata接口來進(jìn)行的,通過此接口判斷信道是否具有較高的鏈路質(zhì)量,并把鄰居節(jié)點(diǎn)加入到鄰居表中,便于以后在選擇路徑時(shí)考慮該鄰居節(jié)點(diǎn)的鏈路。其實(shí)現(xiàn)代碼如代碼6-15所示?!敬a6-15】 LinkEstimatorP.ncif (call LinkPacketMetadata.highChannelQuality(msg) if (signal CompareBit.shouldInsert(msg, call Packet.getPayload(msg, call Packet.payloadLength(msg),call Packet.payloadLength(msg)

44、 nidx = findRandomNeighborIdx();if (nidx != INVALID_RVAL) signal LinkEstimator.evicted(NeighborTablenidx.ll_addr);initNeighborIdx(nidx, ll_addr);2. 路由引擎路由引擎負(fù)責(zé)計(jì)算到匯聚樹根節(jié)點(diǎn)的路由,即選擇數(shù)據(jù)傳輸?shù)南乱惶?。它記錄了由鏈路估?jì)表維護(hù)的一組節(jié)點(diǎn)路徑的期望傳輸值ETX(Expected Transmissions)。CTP是使用ETX作為路由梯度來表示雙向鏈路質(zhì)量的估計(jì)值。ETX值越小表示鏈路質(zhì)量越好。其中,根節(jié)點(diǎn)的路徑ETX為0,普通節(jié)點(diǎn)的

45、路徑ETX為其下一跳節(jié)點(diǎn)的路徑ETX加上他們之間鏈路的連接ETX,因此節(jié)點(diǎn)的路徑ETX是該節(jié)點(diǎn)到根節(jié)點(diǎn)之間整條路由的每跳連接ETX之和。路由引擎每隔一定事件就會(huì)根據(jù)更新的鏈路質(zhì)量估計(jì)重新進(jìn)行路由選擇,主要是計(jì)算路徑ETX和重選父節(jié)點(diǎn),然后廣播一個(gè)路由幀,包括當(dāng)前的父節(jié)點(diǎn)地址和路徑ETX。在TinyOS 2.x中CTP路由引擎的實(shí)現(xiàn)是通過CtpRoutingEngineP組件來實(shí)現(xiàn)的,其組件在“mytinyos/lib/net/ ctp/ CtpRoutingEngineP/”目錄下,具體實(shí)現(xiàn)代碼如代碼6-16所示?!敬a6-16】 CtpRoutingEngineP.ncgeneric mod

46、ule CtpRoutingEngineP(uint8_t routingTableSize,uint32_t minInterval,uint32_t maxInterval) provides interface UnicastNameFreeRouting as Routing;interface RootControl;interface CtpInfo;interface StdControl;interface CtpRoutingPacket;interface Init; uses interface AMSend as BeaconSend;interface Receive

47、 as BeaconReceive;interface LinkEstimator;interface AMPacket;interface SplitControl as RadioControl;interface Timer as BeaconTimer;interface Timer as RouteTimer;interface Random;interface CollectionDebug;interface CtpCongestion;interface CompareBit;在CtpRoutingEngineP組件中,通過LinkEstimator接口獲得鄰居表中的節(jié)點(diǎn)以及與

48、該鄰居節(jié)點(diǎn)的雙向鏈路質(zhì)量。鏈路估計(jì)器和路由引擎之間的交流是通過LinkEstimator接口和CompareBit接口來進(jìn)行的。在這兩個(gè)接口中,其命令函數(shù)返回的鏈路質(zhì)量值都是標(biāo)準(zhǔn)形式。其中,LinkEstimator.getQuality()的返回值越小,表示該通信鏈路的質(zhì)量越好。3. 轉(zhuǎn)發(fā)引擎轉(zhuǎn)發(fā)引擎主要負(fù)責(zé)以下5種功能:傳遞消息包到下一跳,在必要時(shí)重傳以及向鏈路估計(jì)器傳遞應(yīng)答信號(hào)。決定何時(shí)向下一跳節(jié)點(diǎn)傳輸。檢測(cè)路由中的不一致,并通知路由引擎。維護(hù)需要傳輸?shù)南?duì)列,該隊(duì)列混合了本地產(chǎn)生的消息包和需要轉(zhuǎn)發(fā)的消息包。檢測(cè)由應(yīng)答信號(hào)丟失導(dǎo)致的單跳重復(fù)傳輸。在TinyOS 2.x中CTP協(xié)議的轉(zhuǎn)

49、發(fā)引擎是通過CtpForwarding EngineP組件來實(shí)現(xiàn)的,其組件在“mytinyos/lib/net/ctp/Ctp ForwardingEngineP/”目錄下,具體實(shí)現(xiàn)代碼如代碼6-17所示?!敬a6-17】 CtpForwardingEngineP.ncgeneric module CtpForwardingEngineP() provides interface Init;interface StdControl;interface Senduint8_t client;interface Receivecollection_id_t id;interface Receive

50、 as Snoopcollection_id_t id;interface Interceptcollection_id_t id;interface Packet;interface CollectionPacket;interface CtpPacket;interface CtpCongestion;uses interface AMSend as SubSend;interface Receive as SubReceive;interface Receive as SubSnoop;interface Packet as SubPacket;interface UnicastName

51、FreeRouting;interface SplitControl as RadioControl;interface Queue as SendQueue;interface Pool as QEntryPool;interface Pool as MessagePool;interface Timer as RetxmitTimer;interface LinkEstimator;interface Timer as CongestionTimer;interface Cache as SentCache;interface CtpInfo;interface PacketAcknowl

52、edgements;interface Random;interface RootControl;interface CollectionIduint8_t client;interface AMPacket;interface CollectionDebug;interface Leds;轉(zhuǎn)發(fā)引擎的3個(gè)關(guān)鍵函數(shù)分別是:消息接收/轉(zhuǎn)發(fā)函數(shù)、傳輸消息的任務(wù)函數(shù)和傳輸完畢后的處理函數(shù)。(1) 消息接收/轉(zhuǎn)發(fā)函數(shù)。消息接收函數(shù)由CtpForwardingEngineP組件的SubReceive.receive函數(shù)實(shí)現(xiàn)的,receive函數(shù)決定節(jié)點(diǎn)是否應(yīng)當(dāng)轉(zhuǎn)發(fā)當(dāng)前接收的消息包。此函數(shù)有一個(gè)小的緩沖區(qū)保

53、存最近接收到的消息包,通過檢查這個(gè)緩沖區(qū)可以確定是否有重復(fù)的消息包,如果這個(gè)消息包有重復(fù)使用,就可以調(diào)用消息轉(zhuǎn)發(fā)forward函數(shù)。SubReceive.receive函數(shù)的具體實(shí)現(xiàn)如代碼6-18所示?!敬a6-18】 CtpForwardingEngineP.ncevent message_t* SubReceive.receive(message_t* msg, void* payload, uint8_t len) collection_id_t collectid;bool duplicate = FALSE;fe_queue_entry_t* qe;uint8_t i, thl;co

54、llectid = call CtpPacket.getType(msg);thl = call CtpPacket.getThl(msg);thl+;call CtpPacket.setThl(msg, thl);call CollectionDebug.logEventMsg(NET_C_FE_RCV_MSG, call CollectionPacket.getSequenceNumber(msg), call CollectionPacket.getOrigin(msg), thl-);if (len call SubSend.maxPayloadLength() return msg;

55、if (call SentCache.lookup(msg) call CollectionDebug.logEvent(NET_C_FE_DUPLICATE_CACHE);return msg;if (call SendQueue.size() 0) for (i = call SendQueue.size(); -i;) qe = call SendQueue.element(i);if (call CtpPacket.matchInstance(qe-msg, msg) duplicate = TRUE;break;if (duplicate) call CollectionDebug.

56、logEvent(NET_C_FE_DUPLICATE_QUEUE);return msg;else if (call RootControl.isRoot()return signal Receive.receivecollectid(msg,call Packet.getPayload(msg, call Packet.payloadLength(msg), call Packet.payloadLength(msg);else if (!signal Intercept.forwardcollectid(msg, call Packet.getPayload(msg,call Packe

57、t.payloadLength(msg), call Packet.payloadLength(msg)return msg;else dbg(Route, Forwarding packet from %hu.n, getHeader(msg)-origin); return forward(msg);(2) 傳輸消息的任務(wù)函數(shù)。傳輸消息的任務(wù)函數(shù)由CtpForwardingEngineP組件的sendTask函數(shù)實(shí)現(xiàn),sendTask函數(shù)會(huì)對(duì)需要轉(zhuǎn)發(fā)的消息包進(jìn)行格式化,即重新組織消息包的內(nèi)部結(jié)構(gòu)。通過檢查收到的消息包,它可以判斷傳輸過程中是否存在路由循環(huán),并檢查傳輸隊(duì)列是否有空缺,如果傳輸

58、隊(duì)列已滿,丟棄該消息包并置位擁塞標(biāo)識(shí)位;如果傳輸隊(duì)列為空,則提交sendTask任務(wù),即直接發(fā)送出去,無需排隊(duì)。sendTask函數(shù)檢查位于傳輸隊(duì)列頭部的消息包,為下一條傳輸做好準(zhǔn)備,即直接發(fā)送出去,無需排隊(duì)。(3) 消息處理完畢后的處理函數(shù)。消息處理完畢后的處理函數(shù)由CtpForwardingEngineP組件的sendDone函數(shù)實(shí)現(xiàn),當(dāng)傳輸完成后,sendDone函數(shù)檢查發(fā)送結(jié)果。有以下幾種情況:如果消息包發(fā)出后有收到應(yīng)答信號(hào),就從傳輸隊(duì)列中移除該消息包。如果消息包由本地節(jié)點(diǎn)產(chǎn)生,則把sendDone信號(hào)傳遞給上層組件。如果是轉(zhuǎn)發(fā)消息包,就把該消息包仍會(huì)到轉(zhuǎn)發(fā)消息的緩沖區(qū)。如果傳輸隊(duì)列中

59、還有剩余的消息包,例如已發(fā)送的消息包沒有得到應(yīng)答,就啟動(dòng)一個(gè)隨機(jī)定時(shí)器以重新提交sendTask任務(wù)。6.4.2 CTP協(xié)議實(shí)例以下內(nèi)容將實(shí)現(xiàn)任務(wù)描述6.D.2,使用CTP協(xié)議實(shí)現(xiàn)數(shù)據(jù)的傳輸。完成此任務(wù)描述需要以下幾個(gè)步驟:(1) 在“mytinyos/apps”目錄下創(chuàng)建MultihopOscilloscope文件夾。(2) 在MultihopOscilloscope文件夾下創(chuàng)建并編寫MultihopOscilloscopeApp.nc文件和MultihopOscilloscopeC.nc文件。其中MultihopOscilloscopeApp.nc是頂層配置組件。(3) 編寫Makefil

60、e文件。1. 創(chuàng)建MultihopOscilloscope文件夾打開cygwin,在“mytinyos/apps”目錄下,輸入mkdir MultihopOscilloscope,創(chuàng)建文件夾,具體操作如圖6-5所示。圖6-5 創(chuàng)建MultihopOscilloscope文件夾 2. 創(chuàng)建并編寫主要組件在MultihopOscilloscope文件夾下創(chuàng)建MultihopOscilloscopeApp.nc文件和Multihop OscilloscopeC.nc文件。(1) MultihopOscilloscopeAppC.nc。在MultihopOscilloscopeApp.nc文件中主要列

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論