14 在ZStack里的网络广播传输

  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, 
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  2

afAddrType_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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值