获取网络拓扑
1、实验内容:PC端串口调试助手向协调器发送命名“topology”,协调器接受到命令后,将网络拓扑信息发送到PC机串口调试助手上。
2、知识点:在1-11 实验9 网络管理实验1 获取自身和父节点的网络地址、MAC地址 中,我们知道每个节点都获取自身和父节点的网络地址,然后发送到协调器节点,然后再通过串口写到串口的调试助手上。这样就可以获得整个网络的拓扑结构啦。
3、程序设计
协调器程序设计
//NewCoordinator.h文件中添加如下结构体。
typedef struct rftx{
uint8 type[3];
uint8 myNWK[4];
uint8 pNWK[4];
}RFTX;
NewCoordinator.c文件如下:
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"
#include "NewCoordinator.h"
//#include "GenericApp.h"
#include "DebugTrace.h"
#if !defined( WIN32 )
#include "OnBoard.h"
#endif
/* HAL */
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#include "hal_uart.h"
/*********************************************************************
* MACROS
*/
/*********************************************************************
* CONSTANTS
*/
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
// This list should be filled with Application specific Cluster IDs.
const cId_t GenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS] =
{
GENERICAPP_CLUSTERID
};
const SimpleDescriptionFormat_t GenericApp_SimpleDesc =
{
GENERICAPP_ENDPOINT, // int Endpoint;
GENERICAPP_PROFID, // uint16 AppProfId[2];
GENERICAPP_DEVICEID, // uint16 AppDeviceId[2];
GENERICAPP_DEVICE_VERSION, // int AppDevVer:4;
GENERICAPP_FLAGS, // int AppFlags:4;
//下面的初始化 二选一!!!!!!!!
GENERICAPP_MAX_CLUSTERS, // byte AppNumInClusters;
(cId_t *)GenericApp_ClusterList, // byte *pAppInClusterList;
// GENERICAPP_MAX_CLUSTERS, // byte AppNumInClusters;
// (cId_t *)GenericApp_ClusterList // byte *pAppInClusterList;
0,
(cId_t *)NULL
};
// This is the Endpoint/Interface description. It is defined here, but
// filled-in in GenericApp_Init(). Another way to go would be to fill
// in the structure here and make it a "const" (in code space). The
// way it's defined in this sample app it is define in RAM.
endPointDesc_t GenericApp_epDesc;
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
byte GenericApp_TaskID; // Task ID for internal task/event processing
// This variable will be received when
// GenericApp_Init() is called.
devStates_t GenericApp_NwkState;
byte GenericApp_TransID; // This is the unique message ID (counter)
//afAddrType_t GenericApp_DstAddr;
/*********************************************************************
* LOCAL FUNCTIONS
*/
//void GenericApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg );
//void GenericApp_HandleKeys( byte shift, byte keys );
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );//处理事件
//void GenericApp_SendTheMessage( void );//发送数据
static void rxCB(uint8 port,uint8 envent);
/*********************************************************************
* NETWORK LAYER CALLBACKS
*/
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn GenericApp_Init
*
* @brief Initialization function for the Generic App Task.
* This is called during initialization and should contain
* any application specific initialization (ie. hardware
* initialization/setup, table initialization, power up
* notificaiton ... ).
*
* @param task_id - the ID assigned by OSAL. This ID should be
* used to send messages and set timers.
*
* @return none
*/
void GenericApp_Init( byte task_id )
{
GenericApp_TaskID = task_id;
// GenericApp_NwkState = DEV_INIT;
GenericApp_TransID = 0;
// Device hardware initialization can be added here or in main() (Zmain.c).
// If the hardware is application specific - add it here.
// If the hardware is other parts of the device add it in main().
// GenericApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
// GenericApp_DstAddr.endPoint = 0;
// GenericApp_DstAddr.addr.shortAddr = 0;
// Fill out the endpoint description.
GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;
GenericApp_epDesc.task_id = &GenericApp_TaskID;
GenericApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;
GenericApp_epDesc.latencyReq = noLatencyReqs;
// Register the endpoint description with the AF
afRegister( &GenericApp_epDesc );
//串口的设置,并打开串口
halUARTCfg_t uartConfig;
uartConfig.configured =TRUE;
uartConfig.baudRate =HAL_UART_BR_115200;
uartConfig.flowControl=FALSE;
// uartConfig.callBackFunc=NULL;//???????????????????????????????????
uartConfig.callBackFunc=rxCB;
HalUARTOpen(0,&uartConfig); //打开串口
}
/*********************************************************************
* @fn GenericApp_ProcessEvent
*
* @brief Generic Application Task event processor. This function
* is called to process all events for the task. Events
* include timers, messages and any other user defined events.
*
* @param task_id - The OSAL assigned task ID.
* @param events - events to process. This is a bit map and can
* contain more than one event.
*
* @return none
*/
UINT16 GenericApp_ProcessEvent( byte task_id, UINT16 events )
{
afIncomingMSGPacket_t *MSGpkt;
HalLedBlink(HAL_LED_1,0,50,500);
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
case AF_INCOMING_MSG_CMD: //天线接收到数据
HalLedBlink(HAL_LED_2,0,50,500);
GenericApp_MessageMSGCB( MSGpkt ); //接收数据并把数据发送到UART
break;
default:
break;
}
// Release the memory
osal_msg_deallocate( (uint8 *)MSGpkt );
// Next
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
return 0;
}
/*********************************************************************
* LOCAL FUNCTIONS
*/
/*********************************************************************
* @fn GenericApp_MessageMSGCB
*
* @brief Data message processor callback. This function processes
* any incoming data - probably from other devices. So, based
* on cluster ID, perform the intended action.
*
* @param none
*
* @return none
*/
RFTX rftx;
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
switch ( pkt->clusterId )
{
case GENERICAPP_CLUSTERID:
osal_memcpy(&rftx,pkt->cmd.Data,sizeof(rftx));
//不使用rxCB时,放在这里,尽然只输出一行结果
/* uint8 changeline[2]={0x0A,0x0D};
HalUARTWrite(0,"Type: ",osal_strlen("Type:"));
HalUARTWrite(0,rftx.type,3);
HalUARTWrite(0," NWK:",osal_strlen(" NWK:")); //刚才用了sizeof(" NWK:")
HalUARTWrite(0,rftx.myNWK,sizeof(rftx.myNWK)); 刚才用了sizeof(rftx.myNWk),是不能正确显示的
HalUARTWrite(0," pNWK:",osal_strlen(" pNWK:"));
HalUARTWrite(0,rftx.pNWK,sizeof(rftx.pNWK));
HalUARTWrite(0,changeline,2);*/
break;
}
}
static void rxCB(uint8 port,uint8 envent)
{
uint8 changeline[2]={0x0A,0x0D};
uint8 buf[8];
HalUARTRead(0,buf,8);
if(osal_memcmp(buf,"topology",8))
{
HalUARTWrite(0,"Type: ",osal_strlen("Type:"));
HalUARTWrite(0,rftx.type,3);
HalUARTWrite(0," NWK:",osal_strlen(" NWK:")); //刚才用了sizeof(" NWK:")
HalUARTWrite(0,rftx.myNWK,sizeof(rftx.myNWK)); 刚才用了sizeof(rftx.myNWk),是不能正确显示的
HalUARTWrite(0," pNWK:",osal_strlen(" pNWK:"));
HalUARTWrite(0,rftx.pNWK,sizeof(rftx.pNWK));
HalUARTWrite(0,changeline,2);
}
}
路由器节点或终端节点(共用的Enddevice.c文件)
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"
#include "NewCoordinator.h"
//#include "GenericApp.h"
#include "DebugTrace.h"
#if !defined( WIN32 )
#include "OnBoard.h"
#endif
/* HAL */
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#include "hal_uart.h"
#define SEND_DATA_EVENT 0x01
/*********************************************************************
* MACROS
*/
/*********************************************************************
* CONSTANTS
*/
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
// This list should be filled with Application specific Cluster IDs.
const cId_t GenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS] =
{
GENERICAPP_CLUSTERID
};
const SimpleDescriptionFormat_t GenericApp_SimpleDesc =
{
GENERICAPP_ENDPOINT, // int Endpoint;
GENERICAPP_PROFID, // uint16 AppProfId[2];
GENERICAPP_DEVICEID, // uint16 AppDeviceId[2];
GENERICAPP_DEVICE_VERSION, // int AppDevVer:4;
GENERICAPP_FLAGS, // int AppFlags:4;
//下面是二选一
0,
(cId_t*)0,
//GENERICAPP_MAX_CLUSTERS, // byte AppNumInClusters;
// (cId_t *)GenericApp_ClusterList, // byte *pAppInClusterList;
GENERICAPP_MAX_CLUSTERS, // byte AppNumInClusters;
(cId_t *)GenericApp_ClusterList // byte *pAppInClusterList;
};
// This is the Endpoint/Interface description. It is defined here, but
// filled-in in GenericApp_Init(). Another way to go would be to fill
// in the structure here and make it a "const" (in code space). The
// way it's defined in this sample app it is define in RAM.
endPointDesc_t GenericApp_epDesc;
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
byte GenericApp_TaskID; // Task ID for internal task/event processing
// This variable will be received when
// GenericApp_Init() is called.
devStates_t GenericApp_NwkState;
byte GenericApp_TransID; // This is the unique message ID (counter)
//afAddrType_t GenericApp_DstAddr; //???????????????
/*********************************************************************
* LOCAL FUNCTIONS
*/
//void GenericApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg );
//void GenericApp_HandleKeys( byte shift, byte keys );
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );
void GenericApp_SendTheMessage( void );
void To_string(uint8 *dest,char* src,uint8 length);//二进制书转化为十六进制数
//static void rxCB(uint8 port,uint8 envent);
/*********************************************************************
* NETWORK LAYER CALLBACKS
*/
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn GenericApp_Init
*
* @brief Initialization function for the Generic App Task.
* This is called during initialization and should contain
* any application specific initialization (ie. hardware
* initialization/setup, table initialization, power up
* notificaiton ... ).
*
* @param task_id - the ID assigned by OSAL. This ID should be
* used to send messages and set timers.
*
* @return none
*/
void GenericApp_Init( byte task_id )
{
GenericApp_TaskID = task_id;
GenericApp_NwkState = DEV_INIT;
GenericApp_TransID = 0;
// Fill out the endpoint description.
GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;
GenericApp_epDesc.task_id = &GenericApp_TaskID;
GenericApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;
GenericApp_epDesc.latencyReq = noLatencyReqs;
// Register the endpoint description with the AF
afRegister( &GenericApp_epDesc );
//串口的设置,并打开串口
halUARTCfg_t uartConfig;
uartConfig.configured =TRUE;
uartConfig.baudRate =HAL_UART_BR_115200;
uartConfig.flowControl=FALSE;
uartConfig.callBackFunc=NULL;//???????????????????????????????????
// uartConfig.callBackFunc=rxCB;
HalUARTOpen(0,&uartConfig); //打开串口
//这里就不用添加事件了!!!倒回去看什么时候要添加事件 ???????
// Register for all key events - This app will handle all key events
//RegisterForKeys( GenericApp_TaskID );
}
/*********************************************************************
* @fn GenericApp_ProcessEvent
*
* @brief Generic Application Task event processor. This function
* is called to process all events for the task. Events
* include timers, messages and any other user defined events.
*
* @param task_id - The OSAL assigned task ID.
* @param events - events to process. This is a bit map and can
* contain more than one event.
*
* @return none
*/
UINT16 GenericApp_ProcessEvent( byte task_id, UINT16 events )
{
afIncomingMSGPacket_t *MSGpkt;
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
case ZDO_STATE_CHANGE:
GenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (GenericApp_NwkState == DEV_ROUTER)
|| (GenericApp_NwkState == DEV_END_DEVICE) )
{
osal_set_event(GenericApp_TaskID,SEND_DATA_EVENT);
}
break;
default:
break;
}
// Release the memory
osal_msg_deallocate( (uint8 *)MSGpkt );
// Next
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
if ( events & SEND_DATA_EVENT )
{
//这里添加获取自己和父节点的NWK地址
HalLedBlink(HAL_LED_2,0,50,500);
// Send "the" message
GenericApp_SendTheMessage(); //AF发送
osal_start_timerEx( GenericApp_TaskID,
SEND_DATA_EVENT, //事件
GENERICAPP_SEND_MSG_TIMEOUT );//定时时间
return (events ^ SEND_DATA_EVENT);
}
// Discard unknown events
return 0;
}
/*********************************************************************
* @fn GenericApp_SendTheMessage
*
* @brief Send "the" message.
*
* @param none
*
* @return none
*/
RFTX rftx;
void GenericApp_SendTheMessage( void )//AF发送
{
uint16 nwk;
if (GenericApp_NwkState == DEV_ROUTER)
osal_memcpy(rftx.type,"ROU",3);
else if(GenericApp_NwkState == DEV_END_DEVICE)
osal_memcpy(rftx.type,"DEV",3);
nwk=NLME_GetShortAddr();
To_string(rftx.myNWK,(uint8*)&nwk,2);
nwk=NLME_GetCoordShortAddr();
To_string(rftx.pNWK,(uint8*)&nwk,2);
//下面是串口输出,尽然不管用,不是没有配置串口和打开串口的原因。到底是哪里出了问题呢???
uint8 changeline[2]={0x0A,0x0D};
HalUARTWrite(0,"Type: ",osal_strlen("Type:"));
HalUARTWrite(0,rftx.type,3);
HalUARTWrite(0," NWK:",osal_strlen(" NWK:")); //刚才用了sizeof(" NWK:")
HalUARTWrite(0,rftx.myNWK,sizeof(rftx.myNWK)); 刚才用了sizeof(rftx.myNWk),是不能正确显示的
HalUARTWrite(0," pNWK:",osal_strlen(" pNWK:"));
HalUARTWrite(0,rftx.pNWK,sizeof(rftx.pNWK));
HalUARTWrite(0,changeline,2);
afAddrType_t my_DstAddr; //
my_DstAddr.addrMode=(afAddrMode_t)Addr16Bit;
my_DstAddr.endPoint=GENERICAPP_ENDPOINT;
my_DstAddr.addr.shortAddr=0x0000;
if ( AF_DataRequest(&my_DstAddr, &GenericApp_epDesc,
GENERICAPP_CLUSTERID,
11,// sizeof(rftx),
(uint8 *)&rftx,
&GenericApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
HalLedBlink(HAL_LED_1,0,50,500);
}
}
/*static void rxCB(uint8 port,uint8 envent)
{
uint8 changeline[2]={0x0A,0x0D};
HalUARTWrite(0,"Type: ",osal_strlen("Type:"));
HalUARTWrite(0,rftx.type,3);
HalUARTWrite(0," NWK:",osal_strlen(" NWK:")); //刚才用了sizeof(" NWK:")
HalUARTWrite(0,rftx.myNWK,sizeof(rftx.myNWK)); 刚才用了sizeof(rftx.myNWk),是不能正确显示的
HalUARTWrite(0," pNWK:",osal_strlen(" pNWK:"));
HalUARTWrite(0,rftx.pNWK,sizeof(rftx.pNWK));
HalUARTWrite(0,changeline,2);
}*/
void To_string(uint8 *dest,char* src,uint8 length)//二进制书转化为十六进制数
{
uint8* xad;
uint8 i=0;
uint8 ch;
xad=src+length-1;
for(i=0;i<length;i++,xad--)
{
ch=(*xad>>4)&0x0F; //除以十六
dest[i<<1]=ch+((ch<10)?'0':'7');
ch=*xad&0x0F;
dest[(i<<1)+1]=ch+((ch<10)?'0':'7');
}
}
4、实验结果(只有两块板子,一个做协调器,另一个只能做路由节点或终端节点,所以看不到拓扑的结果)
5、注意:(因为下面一条语句,又花我一个下午,搞残了哥!!!)
HalUARTWrite(0," NWK:",osal_strlen(" NWK:")); //osal_strlen(" NWK:")用了sizeof(" NWK:")