第一种方法,利用NLME.h里面定义的专门API
获取设备自身IEEE地址
extern byte *NLME_GetExtAddr( void );
获取设备自身网络地址
extern uint16 NLME_GetShortAddr( void );
获取父设备网络地址
extern uint16 NLME_GetCoordShortAddr( void );
获取父设备IEEE地址
extern void NLME_GetCoordExtAddr( byte * );
第二种方法:
利用zb_GetDeviceInfo()函数
查看该函数定义即可知用法:
void zb_GetDeviceInfo ( uint8 param, void *pValue )
{
switch(param)
{
case ZB_INFO_DEV_STATE:
osal_memcpy(pValue, &devState, sizeof(uint8));
break;
case ZB_INFO_IEEE_ADDR:
osal_memcpy(pValue, &aExtendedAddress, Z_EXTADDR_LEN);
break;
case ZB_INFO_SHORT_ADDR:
osal_memcpy(pValue, &_NIB.nwkDevAddress, sizeof(uint16));
break;
case ZB_INFO_PARENT_SHORT_ADDR:
osal_memcpy(pValue, &_NIB.nwkCoordAddress, sizeof(uint16));
break;
case ZB_INFO_PARENT_IEEE_ADDR:
osal_memcpy(pValue, &_NIB.nwkCoordExtAddress, Z_EXTADDR_LEN);
break;
case ZB_INFO_CHANNEL:
osal_memcpy(pValue, &_NIB.nwkLogicalChannel, sizeof(uint8));
break;
case ZB_INFO_PAN_ID:
osal_memcpy(pValue, &_NIB.nwkPanId, sizeof(uint16));
break;
case ZB_INFO_EXT_PAN_ID:
osal_memcpy(pValue, &_NIB.extendedPANID, Z_EXTADDR_LEN);
break;
}
}
例如要获取设备短地址,可以这样:
uint16 my_short_addr;
zb_GetDeviceInfo(ZB_INFO_SHORT_ADDR,my_short_addr);
第三种方法:利用上述zb_GetDeviceInfo()函数的定义,同样可知,通过读取_NIB的值也可以获取地址信息,如下调用即可
uint16 my_short_addr = _NIB.nwkDevAddress;
第四种方法:直接读NV,方法如下:
uint8 pValue[8];
osal_nv_read(ZCD_NV_EXTADDR , Z_EXTADDR_LEN, size, pValue);
pValue里保存的即是设备扩展地址
第五种方法,利用OnBoard.c里定义的全局变量aExtendedAddress获取IEEE地址,如下:
uint8 * pValue[Z_EXTADDR_LEN];
osal_memcpy(pValue, &aExtendedAddress, Z_EXTADDR_LEN);
第六种方法,利用ZMacGetReq()函数,如下:
uint8 * pValue[Z_EXTADDR_LEN];
ZMacGetReq(ZMacExtAddr,pValue);
Zigbee2006通过分布式寻址方案来分配网络地址的,保证网络内地址的唯一性。这个寻址算法本身的分布特性保证设备只能与其父辈设备通讯来接受一个网络地址。不需要整个网络范围内通讯的地址分配,有助于网络的可测量性。
在04协议栈里有这样一个公式,A=A(parent)+Cskip(d)*Rm+n,Cskip(d)是不同深度的父设备分配地址时的偏移量,Rm是可以携带的最大路由数,n是第n个设备。其中如果Cskip(d)=0x5a6,Rm=4,则协调器的第一个RFD的地址为A=0+0x5a6*4+1=0x1699.
在06协议里看到这样一个描述:对于一个地址为A、深度为d的路由器,如果下式成立,则具有地址为D的目的地址设备为子设备:A
若Rm=1,Cskip(d)= 1+Cm*(Lm-d-1);
若Rm不为1,则Cskip(d)=(1+Cm-Rm-Cm*( Rm)^(Lm-d-1))/(1-Rm).
后来在另一本资料上见到一份资料:
子节点为父设备的第n个子路由器的短地址分配:
Achild =Aparent +(n-1)*Cskip(d)+1,n=1
Achild =Aparen +(n-1)*Cskip(d),n>1
子节点为父设备的第n个子终端设备的短地址分配:
Achild = Aparent + Rm*Cskip(d)+ n
下图为Lm=3,Cm=6,Rm=4的网络地址分配示例。
几个有用的关于物理地址和网络地址的函数:
得到父节点的网络地址:uint16 NLME_GetCoordShortAddr( void );
得到父节点的物理地址:void NLME_GetCoordExtAddr( byte * );
得到自己的网络地址:uint16 NLME_GetShortAddr( void );
得到自己的物理地址:byte *NLME_GetExtAddr( void );
根据已知物理地址查询远程设备网络地址,作为一个广播信息发送给网络中的所有设备:
afStatus_t ZDP_NwkAddrReq( byte *IEEEAddress, byte ReqType,
byte StartIndex, byte SecurityEnable )
根据已知网络地址查询远程设备物理地址,作为一个广播信息发送给网络中的所有设备:
afStatus_t ZDP_IEEEAddrReq( uint16 shortAddr, byte ReqType,
byte StartIndex, byte SecurityEnable )
快速查询(不启动无线查询,而是根据已存储于地址管理器中的网络(物理)地址查询物理(网络)地址):
查找基于网络地址的物理地址:
uint8 APSME_LookupExtAddr( uint16 nwkAddr, uint8* extAddr );
查找基于物理地址的网络地址:
uint8 APSME_LookupNwkAddr( uint8* extAddr, uint16* nwkAddr );
一般发送消息,使用物理地址和网络地址都可以发送,但最好用网络地址,使用物理地址可能会出现问题。
采用16bit网络地址可以降低功耗问题。如果采用64bit IEEE地址发送数据,首先其数据发送的最佳路径难以求得,势必会增加多次发送的功耗 其二 如果该数据接收设备离开网络(当机),发送之时也就不知道。 采用网络地址发送数据,可以采用路由算法 找到最佳路径 减其功耗。