14 在ZStack里的网络广播传输

来源:互联网 发布:linux 卸载 工具 编辑:程序博客网 时间:2024/06/10 17:30

  ZStack里的网络传输功能比较像系统上的udp socket编程. 它可以支持广播,组播,及点到点的单播传输方式。
  网络传输的功能所用的主要数据类型及函数在工程的”profile/AF.h”里.
  

typedef enum{  afAddrNotPresent = AddrNotPresent,  //表示地址不存在  afAddr16Bit      = Addr16Bit,      //表示目的地址是一个16位地址  afAddr64Bit      = Addr64Bit,      //表示目的地址是一个64位地址  afAddrGroup      = AddrGroup,      //表示目的地址是组播的  afAddrBroadcast  = AddrBroadcast   //表示目的地址是广播的} afAddrMode_t; //地址模式类型, 相应相当于socket里指定IP地址是IPV4地址还是IPV6地址typedef struct{  union  {    uint16      shortAddr;  //16位地址, 广播地址就是0xffff    ZLongAddr_t extAddr;    //64位地址  } addr;  afAddrMode_t addrMode;    //指定使用的地址模式类型  uint8 endPoint;           //指定目的端点, 也就是相当于目的端口号  uint16 panId;  //由网络层自动设置此成员} afAddrType_t; //地址类型. 不管是要发出广播,组播或单播网络数据都是使用此类型的对象来指定, 其它完全一样。typedef uint16  cId_t;typedef struct{  uint8          EndPoint; //端口号(1 ~ 240)  uint16         AppProfId;  // app profile id  uint16         AppDeviceId; // app device id  uint8          AppDevVer:4; // app device version  // AppProfId, AppDeviceId, AppDevVer这三项可以随便设置,只要收发两方一致即可  uint8          Reserved:4;             // AF_V1_SUPPORT uses for AppFlags:4. // Cluster(簇,群)表示在收发一个endPoint端口号上的数据时再进一步的分类,发出数据时需指定Cluster的值是多少  uint8          AppNumInClusters; //指定本端口号支持多少个输入的Cluster个数.    cId_t         *pAppInClusterList; //指向支持输入的具体Cluster值的数组首地址  uint8          AppNumOutClusters; //指定本端口支持多少个输出的Cluster个  cId_t         *pAppOutClusterList; //指定支持输入的具体Cluster值的数组首地址} SimpleDescriptionFormat_t; //此类型用于描述一个端口号里的具体设置typedef struct{  uint8 endPoint; //使用的端口号  uint8 *task_id;  // 指向任务的id  SimpleDescriptionFormat_t *simpleDesc; //描述一个端口号里的具体设置  afNetworkLatencyReq_t latencyReq; //收发网络数据后的延时策略,通常设noLatencyReqs} endPointDesc_t; //描述在任务里绑定使用的endPoint端口号的相关配置.---------- extern afStatus_t afRegister( endPointDesc_t *epDesc ); //此函数用于任务里绑定端口号使用,当网络协议本里接收此端口号的数据后,会设置绑定任务里的事件(SYS_EVENT_MSG), 并把接收到的网络数据通过发消息(消息事件类型为AF_INCOMING_MSG_CMD)到任务里。 任务里通过接收消息的方式就可以获取到接收到网络数据了。//发出风络数据的函数  afStatus_t AF_DataRequest( afAddrType_t *dstAddr, endPointDesc_t *srcEP,  uint16 cID, uint16 len, uint8 *buf, uint8 *transID,        uint8 options, uint8 radius );   // dstAddr指定目的地址及目的端口号,  srcEP指定源端口号的配置,  cID指定使用具体哪一个Cluster, len表示发出数据长度, buf指向要发出的数据缓冲区, transID用于存放返回的网络数据包的序号, options表示发出时的使用的选项, radius通常设为AF_DEFAULT_RADIUS// options有:#define AF_PREPROCESS                      0x04   // Will force APS to callback to preprocess before calling NWK layer#define AF_LIMIT_CONCENTRATOR              0x08#define AF_ACK_REQUEST                     0x10#define AF_DISCV_ROUTE                     0x20   #define AF_EN_SECURITY                     0x40#define AF_SKIP_ROUTING                    0x80


//当任务调用afRegister函数绑定端口号后,网络协议栈里接收到此端口号的数据时,会设置任务有SYS_EVENT_MSG事件并把接收的网络数据通过发消息的方式传到任务。 在任务事件处理函数里通过接收消息来获取到接收的网络数据.typedef struct{  osal_event_hdr_t hdr;   //hdr的event为 AF_INCOMING_MSG_CMD  uint16 groupId;           /* Message's group ID - 0 if not set */  uint16 clusterId;         /* Message's cluster ID */  afAddrType_t srcAddr;     /* Source Address, if endpoint is 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 a 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 */  uint8 nwkSeqNum;          /* network header frame sequence number */  afMSGCommandFormat_t cmd; //cmd里的Data成员指向接收到数据缓冲区首地址, cmd里的DataLength为接收到数据长度.} afIncomingMSGPacket_t; //接收到网络数据的消息类型----------//当网络状态发生变化时(如网络掉线,加入网络等), 网络协议栈会设置任务的SYS_EVENT_MSG事件, 并发出消息到任务里。消息类型为ZDO_STATE_CHANGE. 如:     afIncomingMSGPacket_t  *MSGpkt;     MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(mytask_id);          if (MSGpkt->hdr.event == ZDO_STATE_CHANGE)     {         int status = (devStates_t)(MSGpkt->hdr.status);     }----------//状态有typedef enum{  DEV_HOLD,               // Initialized - not started automatically  DEV_INIT,               // Initialized - not connected to anything  DEV_NWK_DISC,           // Discovering PAN's to join  DEV_NWK_JOINING,        // Joining a PAN  DEV_NWK_REJOIN,         // ReJoining a PAN, only for end devices  DEV_END_DEVICE_UNAUTH,  // Joined but not yet authenticated by trust center  DEV_END_DEVICE,         // Started as device after authentication  DEV_ROUTER,             // Device joined, 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;


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
实现定时网络广播功能的代码:

MyApp.h

#ifndef __MYAPP_H#define __MYAPP_H#include "hal_key.h"#include "OnBoard.h"#include "MT_UART.h"#include "AF.h"#define TIME_OUT   0x0010   //time out event;extern void MyApp_Init(uint8 task_id );extern uint16 MyApp_ProcessEvent(uint8 task_id, uint16 event );extern void Handle_keys(keyChange_t * key_evt);extern void Handle_uart(mtOSALSerialData_t *pmsg);extern void myprintf(char *str);extern void Handle_status(uint8 status);extern void Handle_msg( afIncomingMSGPacket_t *pkt );#endif 

MyApp.c

#include "hal_led.h"#include "hal_key.h"#include "MyApp.h"#include "OnBoard.h"#include "AF.h"#include "MT_UART.h"#include "hal_key.h"#include "hal_uart.h"#include "MT.h"#include <stdio.h>#include <string.h>#include "ZDApp.h"#include "AF.h"uint8  mytask_id; //用于记录任务号uint8  transId;#define  TIMER_LEN   5000    // 5s#define  MYPOINT     20#define ARRAY_SIZE(a)  ((sizeof(a))/sizeof(a[0]))#define CID_BCAST  1#define CID_GROUP  2afAddrType_t  Bcast_addr;endPointDesc_t  mypoint_desc;cId_t cids[] = {   CID_BCAST,   CID_GROUP,};const SimpleDescriptionFormat_t simpleDesc = {    MYPOINT,    0x1234, //AppProfId    0x0001, //AppDeviceId    0,    0,    ARRAY_SIZE(cids),    cids,    ARRAY_SIZE(cids),    cids, };void MyApp_Init(uint8 task_id ){   mytask_id = task_id; //   transId = 0;//   HalLedSet(HAL_LED_ALL, HAL_LED_MODE_TOGGLE);   RegisterForKeys(mytask_id);   MT_UartRegisterTaskID(mytask_id);   // Bcast_addr 初始化,用于指定发出是广播用   Bcast_addr.addrMode = (afAddrMode_t)AddrBroadcast;   Bcast_addr.addr.shortAddr = 0xffff;    Bcast_addr.endPoint = MYPOINT;   mypoint_desc.endPoint = MYPOINT;   mypoint_desc.task_id = &mytask_id;   mypoint_desc.simpleDesc = (SimpleDescriptionFormat_t *)&simpleDesc;   mypoint_desc.latencyReq = noLatencyReqs;   afRegister(&mypoint_desc);   osal_start_timerEx(mytask_id, TIME_OUT, TIMER_LEN); }void Handle_keys(keyChange_t * key_evt){     if (key_evt->keys  &  HAL_KEY_SW_1)     {         HalLedSet(HAL_LED_1, HAL_LED_MODE_TOGGLE);         HalUARTWrite(0, "s1\n\r", 4);     }     if (key_evt->keys  &  HAL_KEY_SW_2)     {         HalLedSet(HAL_LED_2, HAL_LED_MODE_TOGGLE);          HalUARTWrite(0, "s2\n\r", 4);     }}void myprintf(char *str){   HalUARTWrite(0, str, strlen(str)); }void Handle_uart(mtOSALSerialData_t *pmsg){    uint8 len = pmsg->msg[0];    HalUARTWrite(0, &(pmsg->msg[1]), len);}void Handle_status(uint8 status){  switch(status)  {  case DEV_ZB_COORD:      myprintf("work as coordinator\n\r");      break;  case DEV_END_DEVICE:      myprintf("work as end_device\n\r");      break;  }}void Handle_msg( afIncomingMSGPacket_t *pkt ){   HalUARTWrite(0, pkt->cmd.Data, pkt->cmd.DataLength); //接收到网络数据后,通过uart输出}uint16 MyApp_ProcessEvent(uint8 task_id, uint16 events ){  afIncomingMSGPacket_t *MSGpkt;  if ( events & SYS_EVENT_MSG ) //系统消息的处理, 也就是调用osal_msg_send产生的事件  {    //接收系统消息    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(mytask_id);    while ( MSGpkt )    {         if (MSGpkt->hdr.event == KEY_CHANGE) //按键事件处理            Handle_keys((keyChange_t *)MSGpkt);         if (MSGpkt->hdr.event == CMD_SERIAL_MSG)  //串口事件处理                Handle_uart((mtOSALSerialData_t*)MSGpkt);         if (MSGpkt->hdr.event == AF_INCOMING_MSG_CMD) // zigbee网络数据的接收事件处理             Handle_msg(MSGpkt);         if (MSGpkt->hdr.event == ZDO_STATE_CHANGE) //zigbee网络状态事件处理             Handle_status(MSGpkt->hdr.status);               osal_msg_deallocate( (uint8 *)MSGpkt ); // free            MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(mytask_id);    }    return events ^ SYS_EVENT_MSG;      }  if (events & TIME_OUT)    {    //定时发出网络广播数据    static int num = 0;    char buf[30];    sprintf(buf, "bcast: %d\n\r", num++);    if (AF_DataRequest(&Bcast_addr, &mypoint_desc, CID_BCAST, strlen(buf),                       buf,  &transId, AF_DISCV_ROUTE,                        AF_DEFAULT_RADIUS) != afStatus_SUCCESS)    {      myprintf("send failed\n\r");    }    osal_start_timerEx(mytask_id, TIME_OUT, TIMER_LEN);   }   return 0;}