ZigBee中的绑定
ZigBee中的绑定与端点EndPoint息息相关,其实EndPoint就像是TCP/IP中的端口,每个端口对应于不同的应用层。由于采用一个字节来表示EndPoint,可以具有0~255个端点,但是0端点被预留用于ZDO与ZigBee协议栈的其它层通信,实现各个层的初始化和配置。端点255用于向所有端点广播。此外,端点241到254也是保留端点,具有特殊用途,通常用户不要使用这个范围的端点。因此用户可使用的端点为1~240,也就是可以有240个端点,即240个应用。
所有端点都是使用APS提供的服务,透过NWK和安全服务提供层与端点相连接,提供数据传送服务,因此能够失配各种兼容的设备。
typedef struct
{
byte endPoint; //端点号,也就是端口号
byte *task_id; //对应端口的任务ID号
SimpleDescriptionFormat_t *simpleDesc; //设备的简单描述,说明本端点可以提供哪些命令
afNetworkLatencyReq_t latencyReq; //枚举类型
} endPointDesc_t;
//设备的简单描述结构
typedef struct
{
byte EndPoint; //端点号
uint16 AppProfId; // Profile ID,是由ZigBee联盟分配的,用于描述设备的应用场景,比如家庭自动化或者是无线传感器网络,它定义了设备之间信息交换的规范后者说规约
uint16 AppDeviceId; // 设备ID号
byte AppDevVer:4; // 设备版本
byte Reserved:4; //AF_V1_SUPPORT uses for AppFlags:4. Reserved
byte AppNumInClusters; //输入命令个数
cId_t *pAppInClusterList; //输入命令列表
byte AppNumOutClusters; //输出命令个数
cId_t *pAppOutClusterList; //输出命令列表
} SimpleDescriptionFormat_t;
在SimpleSensorEB中简单描述符为
const SimpleDescriptionFormat_t zb_SimpleDesc =
{
MY_ENDPOINT_ID, // Endpoint
MY_PROFILE_ID, // Profile ID
DEV_ID_SENSOR, // Device ID
DEVICE_VERSION_SENSOR, // Device Version
0, // Reserved
NUM_IN_CMD_SENSOR, // Number of Input Commands
(cId_t *) NULL, // Input Command List
NUM_OUT_CMD_SENSOR, // Number of Output Commands
(cId_t *) zb_OutCmdList // Output Command List只有一个输出命令ID
};
其中在SAPI_Init(byte task_id)中对endPointDesc_t结构赋值如下:
sapi_epDesc.task_id = &sapi_TaskID;//任务号
sapi_epDesc.endPoint = zb_SimpleDesc.EndPoint;//端点号
sapi_epDesc.latencyReq = noLatencyReqs;//无延迟
由于在本例子中只有一个应用,即采集温度,因此只需要一个端点描述符。假如有多个应用则需要多个端点描述符,同时占用三个端点号,在不同应用中发送数据时采用不同的端点描述符。
比如在本例中发送数据的语句为
status = AF_DataRequest(&dstAddr, &sapi_epDesc, commandId, len,
pData, &handle, txOptions, radius);
该语句利用AF层的AF_Datarequest函数来发送数据,需要传入的参数包括目标地址,端点描述符,命令ID,长度,实际数据指针,处理方式(比如需不需要确认),发送选项,半径。
假如描述符匹配成功,则
case Match_Desc_rsp:
{
zAddrType_t dstAddr;
ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
if ( sapi_bindInProgress != 0xffff )
{
// Create a binding table entry
dstAddr.addrMode = Addr16Bit;
dstAddr.addr.shortAddr = pRsp->nwkAddr;
if ( APSME_BindRequest( sapi_epDesc.simpleDesc->EndPoint,
sapi_bindInProgress, &dstAddr, pRsp->epList[0] ) == ZSuccess )
{
osal_stop_timerEx(sapi_TaskID, ZB_BIND_TIMER);
osal_start_timerEx( ZDAppTaskID, ZDO_NWK_UPDATE_NV, 250 );
// Find IEEE addr
ZDP_IEEEAddrReq( pRsp->nwkAddr, ZDP_ADDR_REQTYPE_SINGLE, 0, 0 );
#if defined ( MT_SAPI_CB_FUNC )
zb_MTCallbackBindConfirm( sapi_bindInProgress, ZB_SUCCESS );
#endif
// Send bind confirm callback to application
#if ( SAPI_CB_FUNC )
zb_BindConfirm( sapi_bindInProgress, ZB_SUCCESS );
#endif
sapi_bindInProgress = 0xffff;
}
}
}
break;