您的位置:首页 > 其它

zigbee协议栈OSAL之广播、组播、单播(第四天)

2017-07-26 17:49 302 查看
注:今天总结三个实验的步骤,并验证。从其中再深入某些细节。第一广播,第二组播,第三点对点

一:广播

        1.1 主机端

         首先前三天的分析,已经有深度,也有大概轮廓,发端至少要保证可以被执行发的函数吧
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{ ...................
// Send a message out - This event is generated by a timer
//  (setup in SampleApp_Init()).
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
{
// Send the periodic message
SampleApp_SendPeriodicMessage();

// Setup to send message again in normal period (+ a little jitter)
osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );

// return unprocessed events
return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
}

// Discard unknown events
return 0;
}
        AF_DataRequest的使用,几个参数注意下
     
void SampleApp_SendPeriodicMessage( void )
{ char temp[]="ehugdoi\n";
if ( AF_DataRequest( &SampleApp_Periodic_DstAddr,//第一个参数目的地址加端口,这里为20
&SampleApp_epDesc,//第二个参数描述本节点的端口信息
SAMPLEAPP_PERIODIC_CLUSTERID,//可以浅显的理解,但是后期必须深入理解
sizeof(temp),//len
(uint8*)temp,//buffer
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
else
{
// Error occurred in request to send.
}
}


       需要看参数,所以必须找初始化的地方
void SampleApp_Init( uint8 task_id )
{
SampleApp_TaskID = task_id;
SampleApp_NwkState = DEV_INIT;
SampleApp_TransID = 0;

MT_UartInit();
MT_UartRegisterTaskID(task_id);

// Setup for the periodic message's destination address
// Broadcast to everyone
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;//广播
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;//20
SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;//广播地址
.....................
// Fill out the endpoint description.
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;//20
SampleApp_epDesc.task_id = &SampleApp_TaskID;//本任务id
SampleApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;//又是另一个描述结构体
SampleApp_epDesc.latencyReq = noLatencyReqs;//无延迟

...
eaeb
....................
}
    然后看
// These constants are only for example and should be changed to the
// device's needs
#define SAMPLEAPP_ENDPOINT           20

#define SAMPLEAPP_PROFID             0x0F08
#define SAMPLEAPP_DEVICEID           0x0001
#define SAMPLEAPP_DEVICE_VERSION     0
#define SAMPLEAPP_FLAGS              0

#define SAMPLEAPP_MAX_CLUSTERS       2
#define SAMPLEAPP_PERIODIC_CLUSTERID 1
#define SAMPLEAPP_FLASH_CLUSTERID    2
#define SAMPLEAPP_COM_CLUSTERID      3

// Send Message Timeout
#define SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT   5000     // Every 5 seconds

// Application Events (OSAL) - These are bit weighted definitions.
#define SAMPLEAPP_SEND_PERIODIC_MSG_EVT       0x0001

// Group ID for Flash Command
#define SAMPLEAPP_FLASH_GROUP                  0x0001

// Flash Command Duration - in milliseconds
#define SAMPLEAPP_FLASH_DURATION               1000
        发端的信息就弄好了,发端周期发送信息差不多5s,但是但是但是还是要提一个小问题:
        第一次发信息的请求是怎么进去的呢?

        
        

       1.2 接受端

       因为是广播,所以关于地址和端口可以不用太过于细究,在下载的时候选择enddevice,甚至用和上面一样的配置
然后只需要更改一个地方
      
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
uint16 flashTime;
uint8 i,len;

switch ( pkt->clusterId )
{
case SAMPLEAPP_PERIODIC_CLUSTERID:
len=pkt->cmd.Datalength;
for(i=0;i<len;i++)
HalUARTWrite(0,&pkt->cmd.Data[i],1);
break;

case SAMPLEAPP_FLASH_CLUSTERID:
flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] );
HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) );
break;
}
}
       这样编译下载,看现象。
       


       这里面还有几个问题,没有仔细讨论,稍等回过头来分析。
       
       

       1.3 伪点对点通信,即广播对广播实现双向通信

             此时比较简单,只需要改变下
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
uint16 flashTime;
uint8 i,len;

switch ( pkt->clusterId )
{
case SAMPLEAPP_PERIODIC_CLUSTERID:
len=pkt->cmd.DataLength;
for(i=0;i<len;i++)
HalUARTWrite(0,&pkt->cmd.Data[i],1);
AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_PERIODIC_CLUSTERID,
11,
(uint8*)"i get data\n",
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS );
break;

case SAMPLEAPP_FLASH_CLUSTERID:
flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] );
HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) );
break;
}
}
            发端发送信息,收端会回复i get data,实现双向通信
      

        1.4 伪点对点通信,即广播对单播实现双向通信

             也是简单修改

void SampleApp_Init( uint8 task_id )
{
...............

// Setup for the periodic message's destination address
// Broadcast to everyone
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr = 0x0;
           此时就是广对点了,注意我endpoint中
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
...............
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (SampleApp_NwkState == DEV_ZB_COORD)
|| (SampleApp_NwkState == DEV_ROUTER))
// || (SampleApp_NwkState == DEV_END_DEVICE) )//这里就是关键的证明我已经关了广播的地方
            
          

         1.5 遗留问题

                1.主机端发送广播的触发方式我并没有说明白,我是说第一次!
                2.终端机的加入网络的及获得的ID信息,我没有说明
                3. IAR左上角coordinater和enddevice的切换所带来的变化,我简单的假设为宏定义的区别。

二:组播

       
void SampleApp_Init( uint8 task_id )
{

..............
// By default, all devices start out in Group 1
SampleApp_Group.ID = 0x0001;
osal_memcpy( SampleApp_Group.name, "Group 1", 7  );
aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );
...............
}
            我只需要修改这里就可以了,第二个组我为ID=0x0002 name=Group 2

            使用一个coodinater,2个enddevice,其中主机和一个中断属于一组,另外一个终端属于2组。
            主机使用广播,两个中断受到消息都会给主机点对点回复,且回复内容不同。
            开始我的实验:
           

            2.1 主机端

void SampleApp_Init( uint8 task_id )
{
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrGroup;
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr = 0x0002;

..............
// By default, all devices start out in Group 1
SampleApp_Group.ID = 0x0002;
osal_memcpy( SampleApp_Group.name, "Group 1", 7  );
aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );
...............
}


  
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
uint16 flashTime;
uint8 i,len;

switch ( pkt->clusterId )
{
case SAMPLEAPP_PERIODIC_CLUSTERID:
len=pkt->cmd.DataLength;
for(i=0;i<len;i++)
HalUARTWrite(0,&pkt->cmd.Data[i],1);
if(SampleApp_NwkState == DEV_ROUTER)
AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_PERIODIC_CLUSTERID,
9,
(uint8*)"number:1\n",
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS );
break;
          下载到板子上,之后
          

          2.2 接受端

void SampleApp_Init( uint8 task_id )
{
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr = 0x0000;

..............
// By default, all devices start out in Group 1
SampleApp_Group.ID = 0x0002;
osal_memcpy( SampleApp_Group.name, "Group 2", 7  );
aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );
...............
}
       之后只要改变下组ID,和名字就可以进行实验了。

       成功!就不截图贴出来了
 

        2.3 遗留问题

        实际上我接收端必须是下载路由,如果是ENDDEVICE,接收不到数据,这点有点疑惑,难道群组消息,接收端必须是
路由?

三:单播

          点对点开始前,我觉得必须明白地址,否则你和谁点对点啊
          


         就是很简单的拓扑结构,参考原文档:
Also, the distributed nature of the addressing algorithm
ensures that a device only has to communicate with its parent device to receive a unique network-wide address.
The MAX_DEPTH determines the maximum depth of the network. The coordinator is at depth 0 and its child nodes
are at depth 1 and their child nodes are at depth 2 and so on.
The MAX_CHILDREN parameter determines the maximum number of child nodes that a router (or coordinator) node
can possess.
The MAX_ROUTERS parameter determines the maximum number of router-capable child nodes that a router (or
coordinator) node can possess. This parameter is a subset of the MAX_CHILDREN parameter and the remaining
(MAX_CHILDREN – MAX_ROUTERS) entries are for end devices.
        图片为<zigbee无线传感器网络设计与实现>节选       
 




      
       由上面的公式,单播最左边的enddevice的地址为0x0001。右边的为0x0002。
       我想不能每次计算都这么算下地址吧 ,看看已经提供的API
       
3.4.2.1.1 NLME_GetExtAddr()
This function will return a pointer to the device's IEEE 64 bit address.
Prototype
byte *NLME_GetExtAddr( void );
Parameter Details
none.
Return
Pointer to the 64-bit extended address.
3.4.2.1.2 NLME_GetShortAddr()
This function will return the device's network (short - 16 bit) address.
Prototype
uint16 NLME_GetShortAddr( void );
Parameter Details
none.
Return
16-bit network (short) address.


    目前来说有这两个函数就够了,那么开始一个简单的实验吧:
    1.由coordinator发送广播信息,信息为hello world,enddevice接收到之后会以点播形式返回自身网络地址。
    2.coordinator收到返回信息,并确认所有节点的信息都收到之后停止广播,并以一定数据结构链表存储这一信息
    3.由上位机串口发送节点信息,建立coordinator和该节点的双向单播通信,类似于qq等即时聊天工具。
    注:该实验并非比较简单,我自己想象的小实验,我觉得还是有点难度,对于刚开始接触zigbee的人来说。
    
    该源码会上传github,毕竟是学生自己娱乐的,但是链表我会使用双向循环链表。
    

     为了不增加篇幅,单播的实验单独开帖子。

     新帖子链接戳这里:戳这里

     
      

          
        
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: