zigbee协议栈OSAL之广播、组播、单播(第四天)
2017-07-26 17:49
302 查看
注:今天总结三个实验的步骤,并验证。从其中再深入某些细节。第一广播,第二组播,第三点对点
需要看参数,所以必须找初始化的地方
第一次发信息的请求是怎么进去的呢?
然后只需要更改一个地方
这里面还有几个问题,没有仔细讨论,稍等回过头来分析。
2.终端机的加入网络的及获得的ID信息,我没有说明
3. IAR左上角coordinater和enddevice的切换所带来的变化,我简单的假设为宏定义的区别。
使用一个coodinater,2个enddevice,其中主机和一个中断属于一组,另外一个终端属于2组。
主机使用广播,两个中断受到消息都会给主机点对点回复,且回复内容不同。
开始我的实验:
成功!就不截图贴出来了
路由?
就是很简单的拓扑结构,参考原文档:
由上面的公式,单播最左边的enddevice的地址为0x0001。右边的为0x0002。
我想不能每次计算都这么算下地址吧 ,看看已经提供的API
目前来说有这两个函数就够了,那么开始一个简单的实验吧:
1.由coordinator发送广播信息,信息为hello world,enddevice接收到之后会以点播形式返回自身网络地址。
2.coordinator收到返回信息,并确认所有节点的信息都收到之后停止广播,并以一定数据结构链表存储这一信息
3.由上位机串口发送节点信息,建立coordinator和该节点的双向单播通信,类似于qq等即时聊天工具。
注:该实验并非比较简单,我自己想象的小实验,我觉得还是有点难度,对于刚开始接触zigbee的人来说。
该源码会上传github,毕竟是学生自己娱乐的,但是链表我会使用双向循环链表。
为了不增加篇幅,单播的实验单独开帖子。
新帖子链接戳这里:戳这里
一:广播
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,毕竟是学生自己娱乐的,但是链表我会使用双向循环链表。
为了不增加篇幅,单播的实验单独开帖子。
新帖子链接戳这里:戳这里