zigbee zcl规范及其协议栈实现2
对通用命令的处理:
对zcl的通用命令的响应,zcl自己已经实现,比如读取某个clusterid的某个属性值,应用只需将这个属性设置好即可,
通用命令包括,zcl.h
1.比如在发送端(客户端),发出一个个命令是ZCL_CMD_READ,hdr.fc.type=ZCL_FRAME_TYPE_PROFILE_CMD的请求,目的端点是SAMPLELIGHT_ENDPOINT(13)
2.服务端将端点SAMPLELIGHT_ENDPOINT使用zclHA_Init( &zclSampleLight_SimpleDesc )注册在zcl任务,af层从空中接到消息后会转发给SAMPLELIGHT_ENDPOINT所在的任务zcl,然后
zcl_event_loop->zclProcessMessageMSG,
发现hdr.fc.type=ZCL_FRAME_TYPE_PROFILE_CMD,就直接调用zclCmdTable[ZCL_CMD_READ]的那个函数,就是zclProcessInReadCmd,
此函数就在zcl的全局属性链表头部attrList开始寻找对应端点的节点元素的属性指针,返回。。。
if ( zclFindAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, readCmd->attrID[i], &attrRec ) )
{
statusRec->data = attrRec.attr.dataPtr;
statusRec->status = ZCL_STATUS_SUCCESS;
statusRec->dataType = attrRec.attr.dataType;
}
3.所以,服务器端需要先将支持的clusterid的各个属性注册一下,比如zcl_samplelight.c
zcl_registerAttrList( SAMPLELIGHT_ENDPOINT, SAMPLELIGHT_MAX_ATTRIBUTES, zclSampleLight_Attrs );
这个端点注册了n个属性值,放在全局属性链表头部attrList所指向的链表的最后(attrList总是指向链表的头部,zclAttrRecsList attrList)
对zcl不同领域的不同clusterid的不同command的处理:
例如服务器端接收到如下的clusterid(通用领域的).和命令号是COMMAND_TOGGLE怎么处理的呢?
首先要了解general领域的clusterid onoff 的属性和命令各有哪些
2.服务器端将端点号SAMPLELIGHT_ENDPOINT使用zclHA_Init( &zclSampleLight_SimpleDesc )注册在zcl任务,af层从空中接到消息后会转发给SAMPLELIGHT_ENDPOINT所在的任务zcl,然后
zcl_event_loop->zclProcessMessageMSG,
发现hdr.fc.type=ZCL_FRAME_TYPE_SPECIFIC_CMD,就调用zclGeneral_HdlIncoming->zclGeneral_HdlInSpecificCommands,如下
static zclGeneral_AppCallbacks_t *zclGeneral_FindCallbacks( uint8 endpoint )
{
zclGenCBRec_t *pCBs;
pCBs = zclGenCBs;
while ( pCBs )
{
if ( pCBs->endpoint == endpoint )
return ( pCBs->CBs );
pCBs = pCBs->next;
}
return ( (zclGeneral_AppCallbacks_t *)NULL );
}
case下的各个函数,看似有点多余,直接调用回调函数数组中的对应函数不就行了-----那些函数里面有判断条件。
3.所以,服务器端需要先将支持的clusterid的处理函数注册一下,比如zcl_samplelight.c
zclGeneral_RegisterCmdCallbacks( SAMPLELIGHT_ENDPOINT, &zclSampleLight_CmdCallbacks );
这个端点注册了回调函数数组zclSampleLight_CmdCallbacks,放在全局回调函数数组链表头部zclGenCBs所指向的链表的最后(zclGenCBs总是指向链表的头部,zclGenCBRec_t zclGenCBs)
4.在具体的clusterid处理函数中在根据command进行不同处理,比如zclSampleLight_OnOffCB
综上,
inMsg.hdr.fc.type=ZCL_FRAME_TYPE_PROFILE_CMD的时候(表示是zcl通用命令):会根据inMsg.hdr.commandID直接调用zcl.c中预定义的函数数组指针zclCmdTable处理之,根据不同的commandid,调用不同的处理函数。如果处理函数是zclSendMsg则会将这个消息以ZCL_INCOMING_MSG事件发给上层任务去处理
从发送函数可以看出
ZStatus_t zcl_SendCommand( uint8 srcEP, afAddrType_t *destAddr,
uint16 clusterID, uint8 cmd, uint8specific, uint8 direction,
uint8 disableDefaultRsp, uint16 manuCode, uint8 seqNum,
uint16 cmdFormatLen, uint8 *cmdFormat )
inMsg.hdr.fc.type=ZCL_FRAME_TYPE_SPECIFIC_CMD的时候(zcl的功能领域专用命令):会使用 用zclGeneral_RegisterCmdCallbacks( SAMPLELIGHT_ENDPOINT, &zclSampleLight_CmdCallbacks )注册了的函数数组指针zclSampleLight_CmdCallbacks 处理之,根据不同的 inMsg.msg->clusterId会调用不同的处理函数,然后在处理函数中会根据commandid进一步操作
对zcl的通用命令的响应,zcl自己已经实现,比如读取某个clusterid的某个属性值,应用只需将这个属性设置好即可,
通用命令包括,zcl.h
/*** Foundation Command IDs ***/ #define ZCL_CMD_READ 0x00 #define ZCL_CMD_READ_RSP 0x01 #define ZCL_CMD_WRITE 0x02 #define ZCL_CMD_WRITE_UNDIVIDED 0x03 #define ZCL_CMD_WRITE_RSP 0x04 #define ZCL_CMD_WRITE_NO_RSP 0x05 #define ZCL_CMD_CONFIG_REPORT 0x06 #define ZCL_CMD_CONFIG_REPORT_RSP 0x07 #define ZCL_CMD_READ_REPORT_CFG 0x08 #define ZCL_CMD_READ_REPORT_CFG_RSP 0x09 #define ZCL_CMD_REPORT 0x0a #define ZCL_CMD_DEFAULT_RSP 0x0b #define ZCL_CMD_DISCOVER 0x0c #define ZCL_CMD_DISCOVER_RSP 0x0d而zcl.c中默认的处理函数数组是
static CONST zclCmdItems_t zclCmdTable[] = { #ifdef ZCL_READ /* ZCL_CMD_READ */ { zclParseInReadCmd, zclProcessInReadCmd }, /* ZCL_CMD_READ_RSP */ { zclParseInReadRspCmd, zclSendMsg }, #else /* ZCL_CMD_READ */ { NULL, NULL }, /* ZCL_CMD_READ_RSP */ { NULL, NULL }, #endif // ZCL_READ #ifdef ZCL_WRITE /* ZCL_CMD_WRITE */ { zclParseInWriteCmd, zclProcessInWriteCmd }, /* ZCL_CMD_WRITE_UNDIVIDED */ { zclParseInWriteCmd, zclProcessInWriteUndividedCmd }, /* ZCL_CMD_WRITE_RSP */ { zclParseInWriteRspCmd, zclSendMsg }, /* ZCL_CMD_WRITE_NO_RSP */ { zclParseInWriteCmd, zclProcessInWriteCmd }, #else /* ZCL_CMD_WRITE */ { NULL, NULL }, /* ZCL_CMD_WRITE_UNDIVIDED */ { NULL, NULL }, /* ZCL_CMD_WRITE_RSP */ { NULL, NULL }, /* ZCL_CMD_WRITE_NO_RSP */ { NULL, NULL }, #endif // ZCL_WRITE #ifdef ZCL_REPORT /* ZCL_CMD_CONFIG_REPORT */ { zclParseInConfigReportCmd, zclSendMsg }, /* ZCL_CMD_CONFIG_REPORT_RSP */ { zclParseInConfigReportRspCmd, zclSendMsg }, /* ZCL_CMD_READ_REPORT_CFG */ { zclParseInReadReportCfgCmd, zclSendMsg }, /* ZCL_CMD_READ_REPORT_CFG_RSP */ { zclParseInReadReportCfgRspCmd, zclSendMsg }, /* ZCL_CMD_REPORT */ { zclParseInReportCmd, zclSendMsg }, #else /* ZCL_CMD_CONFIG_REPORT */ { NULL, NULL }, /* ZCL_CMD_CONFIG_REPORT_RSP */ { NULL, NULL }, /* ZCL_CMD_READ_REPORT_CFG */ { NULL, NULL }, /* ZCL_CMD_READ_REPORT_CFG_RSP */ { NULL, NULL }, /* ZCL_CMD_REPORT */ { NULL, NULL }, #endif // ZCL_REPORT /* ZCL_CMD_DEFAULT_RSP */ { zclParseInDefaultRspCmd, zclSendMsg }, #ifdef ZCL_DISCOVER /* ZCL_CMD_DISCOVER */ { zclParseInDiscCmd, zclProcessInDiscCmd }, /* ZCL_CMD_DISCOVER_RSP */ { zclParseInDiscRspCmd, zclSendMsg } #else /* ZCL_CMD_DISCOVER */ { NULL, NULL }, /* ZCL_CMD_DISCOVER_RSP */ { NULL, NULL } #endif // ZCL_DISCOVER };
1.比如在发送端(客户端),发出一个个命令是ZCL_CMD_READ,hdr.fc.type=ZCL_FRAME_TYPE_PROFILE_CMD的请求,目的端点是SAMPLELIGHT_ENDPOINT(13)
2.服务端将端点SAMPLELIGHT_ENDPOINT使用zclHA_Init( &zclSampleLight_SimpleDesc )注册在zcl任务,af层从空中接到消息后会转发给SAMPLELIGHT_ENDPOINT所在的任务zcl,然后
zcl_event_loop->zclProcessMessageMSG,
发现hdr.fc.type=ZCL_FRAME_TYPE_PROFILE_CMD,就直接调用zclCmdTable[ZCL_CMD_READ]的那个函数,就是zclProcessInReadCmd,
此函数就在zcl的全局属性链表头部attrList开始寻找对应端点的节点元素的属性指针,返回。。。
if ( zclFindAttrRec( pInMsg->msg->endPoint, pInMsg->msg->clusterId, readCmd->attrID[i], &attrRec ) )
{
statusRec->data = attrRec.attr.dataPtr;
statusRec->status = ZCL_STATUS_SUCCESS;
statusRec->dataType = attrRec.attr.dataType;
}
3.所以,服务器端需要先将支持的clusterid的各个属性注册一下,比如zcl_samplelight.c
zcl_registerAttrList( SAMPLELIGHT_ENDPOINT, SAMPLELIGHT_MAX_ATTRIBUTES, zclSampleLight_Attrs );
这个端点注册了n个属性值,放在全局属性链表头部attrList所指向的链表的最后(attrList总是指向链表的头部,zclAttrRecsList attrList)
typedef struct zclAttrRecsList { struct zclAttrRecsList *next; uint8 endpoint; // Used to link it into the endpoint descriptor uint8 numAttributes; // Number of the following records CONST zclAttrRec_t *attrs; // attribute records } zclAttrRecsList; // Attribute record typedef struct { uint16 attrId; // Attribute ID uint8 dataType; // Data Type - defined in AF.h uint8 accessControl; // Read/write - bit field void *dataPtr; // Pointer to data field } zclAttribute_t; typedef struct { uint16 clusterID; // Real cluster ID zclAttribute_t attr; } zclAttrRec_t; CONST zclAttrRec_t zclSampleLight_Attrs[SAMPLELIGHT_MAX_ATTRIBUTES] = { // *** General Basic Cluster Attributes *** { ZCL_CLUSTER_ID_GEN_BASIC, // Cluster IDs - defined in the foundation (ie. zcl.h) { // Attribute record ATTRID_BASIC_HW_VERSION, // Attribute ID - Found in Cluster Library header (ie. zcl_general.h) ZCL_DATATYPE_UINT8, // Data Type - found in zcl.h ACCESS_CONTROL_READ, // Variable access control - found in zcl.h (void *)&zclSampleLight_HWRevision // Pointer to attribute variable } }, { ZCL_CLUSTER_ID_GEN_BASIC, { // Attribute record ATTRID_BASIC_ZCL_VERSION, ZCL_DATATYPE_UINT8, ACCESS_CONTROL_READ, (void *)&zclSampleLight_ZCLVersion } }, { ZCL_CLUSTER_ID_GEN_BASIC, { // Attribute record ATTRID_BASIC_MANUFACTURER_NAME, ZCL_DATATYPE_CHAR_STR, ACCESS_CONTROL_READ, (void *)zclSampleLight_ManufacturerName } }, { ZCL_CLUSTER_ID_GEN_BASIC, { // Attribute record ATTRID_BASIC_MODEL_ID, ZCL_DATATYPE_CHAR_STR, ACCESS_CONTROL_READ, (void *)zclSampleLight_ModelId } }, { ZCL_CLUSTER_ID_GEN_BASIC, { // Attribute record ATTRID_BASIC_DATE_CODE, ZCL_DATATYPE_CHAR_STR, ACCESS_CONTROL_READ, (void *)zclSampleLight_DateCode } }, { ZCL_CLUSTER_ID_GEN_BASIC, { // Attribute record ATTRID_BASIC_POWER_SOURCE, ZCL_DATATYPE_UINT8, ACCESS_CONTROL_READ, (void *)&zclSampleLight_PowerSource } }, { ZCL_CLUSTER_ID_GEN_BASIC, { // Attribute record ATTRID_BASIC_LOCATION_DESC, ZCL_DATATYPE_CHAR_STR, (ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE), (void *)zclSampleLight_LocationDescription } }, { ZCL_CLUSTER_ID_GEN_BASIC, { // Attribute record ATTRID_BASIC_PHYSICAL_ENV, ZCL_DATATYPE_UINT8, (ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE), (void *)&zclSampleLight_PhysicalEnvironment } }, { ZCL_CLUSTER_ID_GEN_BASIC, { // Attribute record ATTRID_BASIC_DEVICE_ENABLED, ZCL_DATATYPE_BOOLEAN, (ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE), (void *)&zclSampleLight_DeviceEnable } }, // *** Identify Cluster Attribute *** { ZCL_CLUSTER_ID_GEN_IDENTIFY, { // Attribute record ATTRID_IDENTIFY_TIME, ZCL_DATATYPE_UINT16, (ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE), (void *)&zclSampleLight_IdentifyTime } }, // *** On/Off Cluster Attributes *** { ZCL_CLUSTER_ID_GEN_ON_OFF, { // Attribute record ATTRID_ON_OFF, ZCL_DATATYPE_UINT8, ACCESS_CONTROL_READ, (void *)&zclSampleLight_OnOff } }, };4.如果zclCmdTable[ZCL_CMD_READ]对应的处理函数是zclSendMsg,则会将这个消息以ZCL_INCOMING_MSG事件发给上层任务去处理,前提是上层任务使用zcl_registerForMsg注册过。
对zcl不同领域的不同clusterid的不同command的处理:
例如服务器端接收到如下的clusterid(通用领域的).和命令号是COMMAND_TOGGLE怎么处理的呢?
// General Clusters #define ZCL_CLUSTER_ID_GEN_BASIC 0x0000 #define ZCL_CLUSTER_ID_GEN_POWER_CFG 0x0001 #define ZCL_CLUSTER_ID_GEN_DEVICE_TEMP_CONFIG 0x0002 #define ZCL_CLUSTER_ID_GEN_IDENTIFY 0x0003 #define ZCL_CLUSTER_ID_GEN_GROUPS 0x0004 #define ZCL_CLUSTER_ID_GEN_SCENES 0x0005 #define ZCL_CLUSTER_ID_GEN_ON_OFF 0x0006//this #define ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG 0x0007 #define ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL 0x0008 #define ZCL_CLUSTER_ID_GEN_ALARMS 0x0009 #define ZCL_CLUSTER_ID_GEN_TIME 0x000A #define ZCL_CLUSTER_ID_GEN_LOCATION 0x000B #define ZCL_CLUSTER_ID_GEN_KEY_ESTABLISHMENT 0x0800
首先要了解general领域的clusterid onoff 的属性和命令各有哪些
/*********************************/ /*** On/Off Cluster Attributes ***/ /*********************************/ #define ATTRID_ON_OFF 0x0000 /*******************************/ /*** On/Off Cluster Commands ***/ /*******************************/ #define COMMAND_OFF 0x00 #define COMMAND_ON 0x01 #define COMMAND_TOGGLE 0x021.比如在发送端(客户端),发出一个个clusterid是ZCL_CLUSTER_ID_GEN_ON_OFF ,命令是COMMAND_TOGGLE,hdr.fc.type=ZCL_FRAME_TYPE_SPECIFIC_CMD的请求,目的端点是SAMPLELIGHT_ENDPOINT(13)
2.服务器端将端点号SAMPLELIGHT_ENDPOINT使用zclHA_Init( &zclSampleLight_SimpleDesc )注册在zcl任务,af层从空中接到消息后会转发给SAMPLELIGHT_ENDPOINT所在的任务zcl,然后
zcl_event_loop->zclProcessMessageMSG,
发现hdr.fc.type=ZCL_FRAME_TYPE_SPECIFIC_CMD,就调用zclGeneral_HdlIncoming->zclGeneral_HdlInSpecificCommands,如下
static ZStatus_t zclGeneral_HdlInSpecificCommands( zclIncoming_t *pInMsg ) { ZStatus_t stat; zclGeneral_AppCallbacks_t *pCBs; // make sure endpoint exists pCBs = zclGeneral_FindCallbacks( pInMsg->msg->endPoint ); if ( pCBs == NULL ) return ( ZFailure ); switch ( pInMsg->msg->clusterId ) { #ifdef ZCL_BASIC case ZCL_CLUSTER_ID_GEN_BASIC: stat = zclGeneral_ProcessInBasic( pInMsg, pCBs ); break; #endif // ZCL_BASIC #ifdef ZCL_IDENTIFY case ZCL_CLUSTER_ID_GEN_IDENTIFY: stat = zclGeneral_ProcessInIdentity( pInMsg, pCBs ); break; #endif // ZCL_IDENTIFY #ifdef ZCL_GROUPS case ZCL_CLUSTER_ID_GEN_GROUPS: if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) ) stat = zclGeneral_ProcessInGroupsServer( pInMsg ); else stat = zclGeneral_ProcessInGroupsClient( pInMsg, pCBs ); break; #endif // ZCL_GROUPS #ifdef ZCL_SCENES case ZCL_CLUSTER_ID_GEN_SCENES: if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) ) stat = zclGeneral_ProcessInScenesServer( pInMsg, pCBs ); else stat = zclGeneral_ProcessInScenesClient( pInMsg, pCBs ); break; #endif // ZCL_SCENES #ifdef ZCL_ON_OFF case ZCL_CLUSTER_ID_GEN_ON_OFF: stat = zclGeneral_ProcessInOnOff( pInMsg, pCBs ); break; #endif // ZCL_ON_OFF #ifdef ZCL_LEVEL_CTRL case ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL: stat = zclGeneral_ProcessInLevelControl( pInMsg, pCBs ); break; #endif // ZCL_LEVEL_CTRL #ifdef ZCL_ALARMS case ZCL_CLUSTER_ID_GEN_ALARMS: if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) ) stat = zclGeneral_ProcessInAlarmsServer( pInMsg, pCBs ); else stat = zclGeneral_ProcessInAlarmsClient( pInMsg, pCBs ); break; #endif // ZCL_ALARMS #ifdef ZCL_LOCATION case ZCL_CLUSTER_ID_GEN_LOCATION: if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) ) stat = zclGeneral_ProcessInLocationServer( pInMsg, pCBs ); else stat = zclGeneral_ProcessInLocationClient( pInMsg, pCBs ); break; #endif // ZCL_LOCATION case ZCL_CLUSTER_ID_GEN_POWER_CFG: case ZCL_CLUSTER_ID_GEN_DEVICE_TEMP_CONFIG: case ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG: case ZCL_CLUSTER_ID_GEN_TIME: default: stat = ZFailure; break; } return ( stat ); }此函数会在zcl_general的全局处理函数数组链表头部zclGenCBs开始寻找对应端点的节点元素的数组指针
static zclGeneral_AppCallbacks_t *zclGeneral_FindCallbacks( uint8 endpoint )
{
zclGenCBRec_t *pCBs;
pCBs = zclGenCBs;
while ( pCBs )
{
if ( pCBs->endpoint == endpoint )
return ( pCBs->CBs );
pCBs = pCBs->next;
}
return ( (zclGeneral_AppCallbacks_t *)NULL );
}
case下的各个函数,看似有点多余,直接调用回调函数数组中的对应函数不就行了-----那些函数里面有判断条件。
3.所以,服务器端需要先将支持的clusterid的处理函数注册一下,比如zcl_samplelight.c
zclGeneral_RegisterCmdCallbacks( SAMPLELIGHT_ENDPOINT, &zclSampleLight_CmdCallbacks );
这个端点注册了回调函数数组zclSampleLight_CmdCallbacks,放在全局回调函数数组链表头部zclGenCBs所指向的链表的最后(zclGenCBs总是指向链表的头部,zclGenCBRec_t zclGenCBs)
typedef struct zclGenCBRec { struct zclGenCBRec *next; uint8 endpoint; // Used to link it into the endpoint descriptor zclGeneral_AppCallbacks_t *CBs; // Pointer to Callback function } zclGenCBRec_t; typedef struct { zclGCB_BasicReset_t pfnBasicReset; // Basic Cluster Reset command zclGCB_Identify_t pfnIdentify; // Identify command zclGCB_IdentifyQueryRsp_t pfnIdentifyQueryRsp; // Identify Query Response command zclGCB_OnOff_t pfnOnOff; // On/Off cluster commands zclGCB_LevelControlMoveToLevel_t pfnLevelControlMoveToLevel; // Level Control Move to Level command zclGCB_LevelControlMove_t pfnLevelControlMove; // Level Control Move command zclGCB_LevelControlStep_t pfnLevelControlStep; // Level Control Step command zclGCB_LevelControlStop_t pfnLevelControlStop; // Level Control Stop command zclGCB_GroupRsp_t pfnGroupRsp; // Group Response commands zclGCB_SceneStoreReq_t pfnSceneStoreReq; // Scene Store Request command zclGCB_SceneRecallReq_t pfnSceneRecallReq; // Scene Recall Request command zclGCB_SceneRsp_t pfnSceneRsp; // Scene Response command zclGCB_Alarm_t pfnAlarm; // Alarm (Response) commands zclGCB_Location_t pfnLocation; // RSSI Location command zclGCB_LocationRsp_t pfnLocationRsp; // RSSI Location Response command } zclGeneral_AppCallbacks_t; // static zclGeneral_AppCallbacks_t zclSampleLight_CmdCallbacks = { zclSampleLight_BasicResetCB, // Basic Cluster Reset command zclSampleLight_IdentifyCB, // Identify command zclSampleLight_IdentifyQueryRspCB, // Identify Query Response command zclSampleLight_OnOffCB, // On/Off cluster command NULL, // Level Control Move to Level command NULL, // Level Control Move command NULL, // Level Control Step command NULL, // Group Response commands NULL, // Scene Store Request command NULL, // Scene Recall Request command NULL, // Scene Response command NULL, // Alarm (Response) command NULL, // RSSI Location commands NULL, // RSSI Location Response commands };
4.在具体的clusterid处理函数中在根据command进行不同处理,比如zclSampleLight_OnOffCB
static void zclSampleLight_OnOffCB( uint8 cmd ) { // Turn on the light if ( cmd == COMMAND_ON ) zclSampleLight_OnOff = LIGHT_ON; // Turn off the light else if ( cmd == COMMAND_OFF ) zclSampleLight_OnOff = LIGHT_OFF; // Toggle the light else { if ( zclSampleLight_OnOff == LIGHT_OFF ) zclSampleLight_OnOff = LIGHT_ON; else zclSampleLight_OnOff = LIGHT_OFF; } // In this sample app, we use LED4 to simulate the Light if ( zclSampleLight_OnOff == LIGHT_ON ) HalLedSet( HAL_LED_4, HAL_LED_MODE_ON ); else HalLedSet( HAL_LED_4, HAL_LED_MODE_OFF ); }
综上,
inMsg.hdr.fc.type=ZCL_FRAME_TYPE_PROFILE_CMD的时候(表示是zcl通用命令):会根据inMsg.hdr.commandID直接调用zcl.c中预定义的函数数组指针zclCmdTable处理之,根据不同的commandid,调用不同的处理函数。如果处理函数是zclSendMsg则会将这个消息以ZCL_INCOMING_MSG事件发给上层任务去处理
从发送函数可以看出
ZStatus_t zcl_SendCommand( uint8 srcEP, afAddrType_t *destAddr,
uint16 clusterID, uint8 cmd, uint8specific, uint8 direction,
uint8 disableDefaultRsp, uint16 manuCode, uint8 seqNum,
uint16 cmdFormatLen, uint8 *cmdFormat )
inMsg.hdr.fc.type=ZCL_FRAME_TYPE_SPECIFIC_CMD的时候(zcl的功能领域专用命令):会使用 用zclGeneral_RegisterCmdCallbacks( SAMPLELIGHT_ENDPOINT, &zclSampleLight_CmdCallbacks )注册了的函数数组指针zclSampleLight_CmdCallbacks 处理之,根据不同的 inMsg.msg->clusterId会调用不同的处理函数,然后在处理函数中会根据commandid进一步操作