Z-stackプロトコルスタック受信データプロセスの探究
7116 ワード
TI社が発表したZ-stackプロトコルスタックはZigBeeプロトコルの具体的な実装である.
2018-12-27 Ø
コーディネータ側で端末からのデータの解析処理を受信し,ペイロードデータをシリアルポートを介してPC機に送信し,ここでプログラムフロー全体を解析する.まず、通信ノードがパケットを受信すると、イベント処理関数GenericApp_へのアクセスがトリガーされます.ProcessEvent(); ステップ2では、データイベント処理関数に入ってafIncomingMSGPacket_を定義します.t構造体タイプのポインタ変数MSGpktは、メッセージキュー内のパケットを指すために使用される.afIncomingMSGPacket_t *MSGpkt;第3歩、*osal_を通過msg_receive(GenericApp_TaskID)関数は、メッセージキューからデータを読み出す.ここでGenericApp_TaskIDは、タスク優先度IDのグローバル変数であり、タスク初期化関数GenericAppを実行するInit()は付与されます!MSGpkt=(afIncomingMSGPacket_t)*osal_msg_receive(GenericApp_TaskID); 第4ステップif文によりイベントが強制イベントSYSに属するか否かを判定するEVENT_MSG、はい、次の文を実行します. 第5ステップは、イベントのヘッダを読み取ることによってイベントのタイプを判断する.afIncomingMSGPacket_tは、AF.hファイルにおいて、AF_を受信するために使用される到来するパケット構造体タイプを以下に定義する.DataRequest関数からのデータおよびその他の様々なタイプのデータtypedef struct{osal_event_hdr_t hdr;/OSAL Message header/uint16 groupId;/Message’s group ID - 0 if not set/uint16 clusterId;/Message’s cluster ID/afAddrType_t srcAddr;/Source Address, if endpointis STUBAPS_INTER_PAN_EP, it’s an InterPAN message/uint16 macDestAddr;/MAC header destination short address/uint8 endPoint;/destination endpoint/uint8 wasBroadcast;/TRUE if network destination was broadcast address/uint8 LinkQuality;/The link quality of the received data frame/uint8 correlation;/The raw correlation value of the received data frame/int8 rssi;/The received RF power in units dBm/uint8 SecurityUse;/deprecated/uint32 timestamp;/receipt timestamp from MAC/afMSGCommandFormat_t cmd;/Application Data */} afIncomingMSGPacket_t; 1、 afIncomingMSGPacket_t構造体タイプのメンバー変数hdrはosal_event_hdr_t構造体タイプの変数、osal_event_hdr_tイベントヘッダ構造体タイプはOSAL.hではtypedef struct{uint 8 event;//この変数でイベントタイプuint 8 statusを取得できます;//ルータかターミナルノードか}osal_event_hdr_t; 1)したがって、switch(MSGpkt->hdr.event)文によってイベントのタイプを判断することができる.強制イベントSYS_EVENT_MSGのタイプは主にAF_DATA_CONFIRM_CMD AF_INCOMING_MSG_CMDは新しい無線パケットKEY_を受信するCHANGEはキー押下の指示がありZDO_STATE_CHANGEネットワーク状態変化ZDO_CB_MSGは、登録されたZDO応答メッセージがZComDefにあることを示す.hファイルには、ZigBeeプロトコルスタック内の各メッセージに対応するイベントのIDが定義されている.define AF_DATA_CONFIRM_CMD 0xFD//Data confirmation #define AF_INCOMING_MSG_CMD 0 x 1 A//Incoming MSG type message 2)デバイス状態statusは列挙型のデータ型である.定義は次のとおりです:typedef enum{DEV_HOLD,//Initialized-not started automatically DEV_INIT,//初期化、任意のデバイスDEV_NWK_DISCに接続されていない//Discovering PAN’s to join DEV_NWK_JOING、//Joining a PAN DEV_NWK_REJOIN、//ReJoining a PAN,only for end devices DEV_END_DEVICE_UNAUT、///Joined but not yet authenticated by truscent cent cent cent cent cent ter DEV_END_DEVICE,//Started as device after authentication DEV_ROUTER,//Devicejoined, authenticated and is a router DEV_COORD_STARTING,//Started as Zigbee Coordinator DEV_ZB_COORD,//Started as Zigbee Coordinator DEV_NWK_ORPHAN//Device has lost information about its parent…} devStates_t; 2、afAddrType_tアドレスタイプ構造体タイプAF.hファイルでの定義は、typedef struct{union{uint 16 shortAddr;ZLongAddr_t extAddr;}addr; afAddrMode_t addrMode; uint8 endPoint; uint16 panId;//used for the INTER_PAN feature } afAddrType_t;
ステップ6、読み出したイベントのタイプがAF_であればINCOMING_MSG_CMDは、受信データ処理関数を呼び出す.case AF_INCOMING_MSG_CMD: GenericApp_MessageMSGCB( MSGpkt ); break; 受信データ処理関数のプロトタイプは以下の通りである:void GenericApp_MSGCB(afIncomingMSGPacket_t*pkt){unsigned char buffer[10];switch(pkt->clusterId)//パケットのクラスタIDの値を読み取ることによって、このパケットのタイプがどのようなタスクを遂行したいのかを判断する{case GENERICAPP_CLUSTERD://Put your code here to process the incoming data osal_memcpy(buffer,pkt->cmd.Data,10);HalUARRTWrite(0,buffer,10);break;break k k(buffer,10);break;break;break;}}関数では、パケットのクラスタIDの値を読み取ることによって、このパケットのタイプがどのようなタスクを完了したいのかを判断するが、1つのノードから送信されるパケットのクラスタIDのタイプ数は、送信ノード単純記述子で定義された出力クラスタIDの個数および出力クラスタIDのリストに依存する.例えば、送信ノードの簡単な記述子は、コーディネータノードconst SimpleDescriptionFormat_を記述する.t GenericApp_SimpleDesc={GENERICAPP_ENDPOINT,////GENERICAPP_PROFID、スマートホームのProfile IDは0 x 04104 GENERICAPP_DEVICEID、//uint 16 AppDeviceId[2];GENERICAPP_DEVICE_VERSION、////int AppDeVer:4;GENERICAPP_FLAGS、//////GENERICAPP_MAX_CLUSTERS、//////////////byteAppNumInClusters;(cId_t*)Generic_ClusterList、///byte*pInClususters;///byte*AppInInClusters;;;//*AppInClterList;0,//(cId_t*)NULL//};単純記述子構造体タイプの定義は、typedef struct{int Endpoint;//ポート番号uint 16 AppProfId[2];//アプリケーション仕様ID uint 16 AppDeviceId[2];;//アプリケーションID int AppDevVer:4;//アプリケーションバージョン番号int AppFlags:4;//byte AppNumInClustersを保持します.//クラスタIDの個数byte*pAppInClusterList;クラスタIDのリストbyte AppNumInClusters;//出力クラスタIDの個数byte*pAppInClusterList;//出力クラスタIDのリスト}SimpleDescriptionFormat_t; 出力クラスタIDのリストの定義は以下のconst cId_t GenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS] = { GENERICAPP_CLUSTERID}; つまり出力クラスタIDの個数が1つしかない、GENERICAPP_CLUSTERID、あるクラスタIDは、あるアプリケーション領域の特定のオブジェクトを制御するために使用されると理解することができ、例えば、このクラスタIDは、ライトのスイッチを制御するために使用される.収集された温度を伝送するなど、アプリケーション分野の他の特定のオブジェクトを制御する必要がある場合、クラスタIDを別途設定する必要があります.これにより、出力クラスタIDが1つ追加され、出力クラスタIDリスト配列にクラスタIDが1つ追加されます.本例ではクラスタIDはGENERICAPP_CLUSTERIDは、受信したデータをシリアルポートを介してPC機に転送することを意味するので、関数osal_を先に通過するmemcpy(void*dst,const void GENERIC*src,unsigned int len)パケットに格納されているsrcが指すデータをdstが指す配列のafMSGcommandFormat_にコピーするt構造体タイプ定義は、typedef struct{uint 8 TransSeqNumber;//送信側の送信シリアル番号uint 16 DataLength;//送信データの長さ情報uint 8*Data;//受信データバッファのポインタ}afMSGcommandFormat_t; 従って、受信メッセージデータは、pkt->cmdのメッセージコマンドフォーマット構造体にカプセル化される.Dataとは、受信したペイロードデータのポインタを指し、関数uint 16 HalUARTWrite(uint 8 port,uint 8*buf,uint 16 length)を介して;受信したデータをCC 2530のシリアルポート0を介してPC機に送信した.HalUARTWrite(0,buffer,10);//シリアルポート0を介してbufferが指す配列の10バイトを7ステップ目に発行し、受信パケットイベントを処理すると、メッセージポインタが占有するメモリを解放し、メッセージポインタが次のメッセージを指すのを容易にすることができる.メッセージポインタを解放するために使用されるメモリ関数は、次のosal_msg_deallocate( (uint8 *)MSGpkt ); ステップ8では、次の受信したバッファに置かれた処理対象イベントにポインタを向け、バッファが処理イベントを待たないまでwhile(MSGpkt)に戻ってイベントを再処理する.MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(GenericApp_TaskID);
ステップ9では、処理済みのイベントを消去して戻り値として返し、異或の演算ロジックを採用し、処理されていないイベントは影響を受けません.return(events ^ SYS_EVENT_MSG); Ø完全な手順は以下の通りである:
2018-12-27 Ø
コーディネータ側で端末からのデータの解析処理を受信し,ペイロードデータをシリアルポートを介してPC機に送信し,ここでプログラムフロー全体を解析する.まず、通信ノードがパケットを受信すると、イベント処理関数GenericApp_へのアクセスがトリガーされます.ProcessEvent(); ステップ2では、データイベント処理関数に入ってafIncomingMSGPacket_を定義します.t構造体タイプのポインタ変数MSGpktは、メッセージキュー内のパケットを指すために使用される.afIncomingMSGPacket_t *MSGpkt;
ステップ6、読み出したイベントのタイプがAF_であればINCOMING_MSG_CMDは、受信データ処理関数を呼び出す.case AF_INCOMING_MSG_CMD: GenericApp_MessageMSGCB( MSGpkt ); break; 受信データ処理関数のプロトタイプは以下の通りである:void GenericApp_MSGCB(afIncomingMSGPacket_t*pkt){unsigned char buffer[10];switch(pkt->clusterId)//パケットのクラスタIDの値を読み取ることによって、このパケットのタイプがどのようなタスクを遂行したいのかを判断する{case GENERICAPP_CLUSTERD://Put your code here to process the incoming data osal_memcpy(buffer,pkt->cmd.Data,10);HalUARRTWrite(0,buffer,10);break;break k k(buffer,10);break;break;break;}}関数では、パケットのクラスタIDの値を読み取ることによって、このパケットのタイプがどのようなタスクを完了したいのかを判断するが、1つのノードから送信されるパケットのクラスタIDのタイプ数は、送信ノード単純記述子で定義された出力クラスタIDの個数および出力クラスタIDのリストに依存する.例えば、送信ノードの簡単な記述子は、コーディネータノードconst SimpleDescriptionFormat_を記述する.t GenericApp_SimpleDesc={GENERICAPP_ENDPOINT,////GENERICAPP_PROFID、スマートホームのProfile IDは0 x 04104 GENERICAPP_DEVICEID、//uint 16 AppDeviceId[2];GENERICAPP_DEVICE_VERSION、////int AppDeVer:4;GENERICAPP_FLAGS、//////GENERICAPP_MAX_CLUSTERS、//////////////byteAppNumInClusters;(cId_t*)Generic_ClusterList、///byte*pInClususters;///byte*AppInInClusters;;;//*AppInClterList;0,//(cId_t*)NULL//};単純記述子構造体タイプの定義は、typedef struct{int Endpoint;//ポート番号uint 16 AppProfId[2];//アプリケーション仕様ID uint 16 AppDeviceId[2];;//アプリケーションID int AppDevVer:4;//アプリケーションバージョン番号int AppFlags:4;//byte AppNumInClustersを保持します.//クラスタIDの個数byte*pAppInClusterList;クラスタIDのリストbyte AppNumInClusters;//出力クラスタIDの個数byte*pAppInClusterList;//出力クラスタIDのリスト}SimpleDescriptionFormat_t; 出力クラスタIDのリストの定義は以下のconst cId_t GenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS] = { GENERICAPP_CLUSTERID}; つまり出力クラスタIDの個数が1つしかない、GENERICAPP_CLUSTERID、あるクラスタIDは、あるアプリケーション領域の特定のオブジェクトを制御するために使用されると理解することができ、例えば、このクラスタIDは、ライトのスイッチを制御するために使用される.収集された温度を伝送するなど、アプリケーション分野の他の特定のオブジェクトを制御する必要がある場合、クラスタIDを別途設定する必要があります.これにより、出力クラスタIDが1つ追加され、出力クラスタIDリスト配列にクラスタIDが1つ追加されます.本例ではクラスタIDはGENERICAPP_CLUSTERIDは、受信したデータをシリアルポートを介してPC機に転送することを意味するので、関数osal_を先に通過するmemcpy(void*dst,const void GENERIC*src,unsigned int len)パケットに格納されているsrcが指すデータをdstが指す配列のafMSGcommandFormat_にコピーするt構造体タイプ定義は、typedef struct{uint 8 TransSeqNumber;//送信側の送信シリアル番号uint 16 DataLength;//送信データの長さ情報uint 8*Data;//受信データバッファのポインタ}afMSGcommandFormat_t; 従って、受信メッセージデータは、pkt->cmdのメッセージコマンドフォーマット構造体にカプセル化される.Dataとは、受信したペイロードデータのポインタを指し、関数uint 16 HalUARTWrite(uint 8 port,uint 8*buf,uint 16 length)を介して;受信したデータをCC 2530のシリアルポート0を介してPC機に送信した.HalUARTWrite(0,buffer,10);//シリアルポート0を介してbufferが指す配列の10バイトを7ステップ目に発行し、受信パケットイベントを処理すると、メッセージポインタが占有するメモリを解放し、メッセージポインタが次のメッセージを指すのを容易にすることができる.メッセージポインタを解放するために使用されるメモリ関数は、次のosal_msg_deallocate( (uint8 *)MSGpkt ); ステップ8では、次の受信したバッファに置かれた処理対象イベントにポインタを向け、バッファが処理イベントを待たないまでwhile(MSGpkt)に戻ってイベントを再処理する.MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(GenericApp_TaskID);
ステップ9では、処理済みのイベントを消去して戻り値として返し、異或の演算ロジックを採用し、処理されていないイベントは影響を受けません.return(events ^ SYS_EVENT_MSG); Ø完全な手順は以下の通りである:
uint16 GenericApp_ProcessEvent( uint8 task_id, uint16 events )
1{ afIncomingMSGPacket_t *MSGpkt;
if ( events & SYS_EVENT_MSG )
2{ MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
while( MSGpkt )//
3{ switch ( MSGpkt->hdr.event )
4{ case AF_INCOMING_MSG_CMD:
GenericApp_MessageMSGCB( MSGpkt );
break;
default: break;
}4 // ,
osal_msg_deallocate( (uint8 *)MSGpkt );
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(GenericApp_TaskID);
}3 return(events ^ SYS_EVENT_MSG);// return unprocessed events
}2 return 0;
}1
static void GenericApp_MessageMSGCB(afIncomingMSGPacket_t *pkt )
{
unsigned char buffer[10]; switch ( pkt->clusterId )
{
case GENERICAPP_CLUSTERID:
osal_memcpy(buffer,pkt->cmd.Data,10);// buffer
HalUARTWrite(0,buffer,10);
break;
}
}