本文讲的是使用ZCL,不使用ZCL参见:http://blog.csdn.net/zaoyuzang6112/article/details/76502215
以light和switch demo 为例子
1.在light 例子中可以参见profile 属性表注册
static zclGeneral_AppCallbacks_t zclSampleLight_CmdCallbacks =
{
zclSampleLight_BasicResetCB, // Basic Cluster Reset command
NULL, // Identify Trigger Effect command
zclSampleLight_OnOffCB, // On/Off cluster commands
NULL, // On/Off cluster enhanced command Off with Effect
NULL, // On/Off cluster enhanced command On with Recall Global Scene
NULL, // On/Off cluster enhanced command On with Timed Off
#ifdef ZCL_LEVEL_CTRL
zclSampleLight_LevelControlMoveToLevelCB, // Level Control Move to Level command
zclSampleLight_LevelControlMoveCB, // Level Control Move command
zclSampleLight_LevelControlStepCB, // Level Control Step command
zclSampleLight_LevelControlStopCB, // Level Control Stop command
#endif
#ifdef ZCL_GROUPS
NULL, // Group Response commands
#endif
#ifdef ZCL_SCENES
NULL, // Scene Store Request command
NULL, // Scene Recall Request command
NULL, // Scene Response command
#endif
#ifdef ZCL_ALARMS
NULL, // Alarm (Response) commands
#endif
#ifdef SE_UK_EXT
NULL, // Get Event Log command
NULL, // Publish Event Log command
#endif
NULL, // RSSI Location command
NULL // RSSI Location Response command
};
2.在 zclSampleLight_Init()中注册
void zclSampleLight_Init( byte task_id )
{
zclSampleLight_TaskID = task_id;
// Set destination address to indirect
zclSampleLight_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
zclSampleLight_DstAddr.endPoint = 0;
zclSampleLight_DstAddr.addr.shortAddr = 0;
// Register the Simple Descriptor for this application
bdb_RegisterSimpleDescriptor( &zclSampleLight_SimpleDesc );
// Register the ZCL General Cluster Library callback functions
zclGeneral_RegisterCmdCallbacks( SAMPLELIGHT_ENDPOINT, &zclSampleLight_CmdCallbacks );
// Register the application's attribute list
zclSampleLight_ResetAttributesToDefaultValues();
zcl_registerAttrList( SAMPLELIGHT_ENDPOINT, zclSampleLight_NumAttributes, zclSampleLight_Attrs );
#ifdef ZCL_LEVEL_CTRL
zclSampleLight_LevelLastLevel = zclSampleLight_LevelCurrentLevel;
#endif
// Register the Application to receive the unprocessed Foundation command/response messages
zcl_registerForMsg( zclSampleLight_TaskID );
#ifdef ZCL_DISCOVER
// Register the application's command list
zcl_registerCmdList( SAMPLELIGHT_ENDPOINT, zclCmdsArraySize, zclSampleLight_Cmds );
#endif
...
}
3.数据处理函数
uint16 zclSampleSw_event_loop( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
(void)task_id; // Intentionally unreferenced parameter
//Send toggle every 500ms
if( events & SAMPLESW_TOGGLE_TEST_EVT )
{
osal_start_timerEx(zclSampleSw_TaskID,SAMPLESW_TOGGLE_TEST_EVT,500);
zclGeneral_SendOnOff_CmdToggle( SAMPLESW_ENDPOINT, &zclSampleSw_DstAddr, FALSE, 0 );
// return unprocessed events
return (events ^ SAMPLESW_TOGGLE_TEST_EVT);
}
if ( events & SYS_EVENT_MSG )
{
while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( zclSampleSw_TaskID )) )
{
switch ( MSGpkt->hdr.event )
{
case ZCL_INCOMING_MSG:
// Incoming ZCL Foundation command/response messages
zclSampleSw_ProcessIncomingMsg( (zclIncomingMsg_t *)MSGpkt );
break;
....
}
4.switch 是如何控制light的,在switch中可以找到按键的这个code
void zclSampleSw_UiActionToggleLight(uint16 keys)
{
if (zclSampleSw_OnOffSwitchActions == ON_OFF_SWITCH_ACTIONS_TOGGLE)
{
if (keys & UI_KEY_SW_5_PRESSED)
{
zclGeneral_SendOnOff_CmdToggle( SAMPLESW_ENDPOINT, &zclSampleSw_DstAddr, FALSE, bdb_getZCLFrameCounter() );
}
}
else if (((keys & UI_KEY_SW_5_PRESSED) && (zclSampleSw_OnOffSwitchActions == ON_OFF_SWITCH_ACTIONS_ON))
|| ((keys & UI_KEY_SW_5_RELEASED) && (zclSampleSw_OnOffSwitchActions == ON_OFF_SWITCH_ACTIONS_OFF)))
{
zclGeneral_SendOnOff_CmdOn( SAMPLESW_ENDPOINT, &zclSampleSw_DstAddr, FALSE, bdb_getZCLFrameCounter() );
}
else
{
zclGeneral_SendOnOff_CmdOff( SAMPLESW_ENDPOINT, &zclSampleSw_DstAddr, FALSE, bdb_getZCLFrameCounter() );
}
}
配合上light的上profile回调中的on/off属性回调就可以完成switch对light控制。
5.如果发送自己的数据呢
在swicth中使用zcl_SendReportCmd函数
/*********************************************************************
* @fn zcl_SendReportCmd
*
* @brief Send a Report command
*
* @param dstAddr - destination address
* @param clusterID - cluster ID
* @param reportCmd - report command to be sent
* @param direction - direction of the command
* @param seqNum - transaction sequence number
*
* @return ZSuccess if OK
*/
ZStatus_t zcl_SendReportCmd( uint8 srcEP, afAddrType_t *dstAddr,
uint16 clusterID, zclReportCmd_t *reportCmd,
uint8 direction, uint8 disableDefaultRsp, uint8 seqNum )
{
uint16 dataLen = 0;
uint8 *buf;
ZStatus_t status;
uint8 i;
// calculate the size of the command
for ( i = 0; i < reportCmd->numAttr; i++ )
{
zclReport_t *reportRec = &(reportCmd->attrList[i]);
dataLen += 2 + 1; // Attribute ID + data type
// Attribute Data
dataLen += zclGetAttrDataLength( reportRec->dataType, reportRec->attrData );
}
buf = zcl_mem_alloc( dataLen );
if ( buf != NULL )
{
// Load the buffer - serially
uint8 *pBuf = buf;
for ( i = 0; i < reportCmd->numAttr; i++ )
{
zclReport_t *reportRec = &(reportCmd->attrList[i]);
*pBuf++ = LO_UINT16( reportRec->attrID );
*pBuf++ = HI_UINT16( reportRec->attrID );
*pBuf++ = reportRec->dataType;
pBuf = zclSerializeData( reportRec->dataType, reportRec->attrData, pBuf );
}
status = zcl_SendCommand( srcEP, dstAddr, clusterID, ZCL_CMD_REPORT, FALSE,
direction, disableDefaultRsp, 0, seqNum, dataLen, buf );
zcl_mem_free( buf );
}
else
{
status = ZMemError;
}
return ( status );
}
#endif
在light中case ZCL_CMD_REPORT: // zclSampleLight_ProcessInReportCmd( pInMsg );中解析
static void zclSampleLight_ProcessIncomingMsg( zclIncomingMsg_t *pInMsg )
{
switch ( pInMsg->zclHdr.commandID )
{
#ifdef ZCL_READ
case ZCL_CMD_READ_RSP:
zclSampleLight_ProcessInReadRspCmd( pInMsg );
break;
#endif
#ifdef ZCL_WRITE
case ZCL_CMD_WRITE_RSP:
zclSampleLight_ProcessInWriteRspCmd( pInMsg );
break;
#endif
case ZCL_CMD_CONFIG_REPORT:
case ZCL_CMD_CONFIG_REPORT_RSP:
case ZCL_CMD_READ_REPORT_CFG:
case ZCL_CMD_READ_REPORT_CFG_RSP:
case ZCL_CMD_REPORT:
//bdb_ProcessIncomingReportingMsg( pInMsg );
break;
case ZCL_CMD_DEFAULT_RSP:
zclSampleLight_ProcessInDefaultRspCmd( pInMsg );
break;
#ifdef ZCL_DISCOVER
case ZCL_CMD_DISCOVER_CMDS_RECEIVED_RSP:
zclSampleLight_ProcessInDiscCmdsRspCmd( pInMsg );
break;
case ZCL_CMD_DISCOVER_CMDS_GEN_RSP:
zclSampleLight_ProcessInDiscCmdsRspCmd( pInMsg );
break;
case ZCL_CMD_DISCOVER_ATTRS_RSP:
zclSampleLight_ProcessInDiscAttrsRspCmd( pInMsg );
break;
case ZCL_CMD_DISCOVER_ATTRS_EXT_RSP:
zclSampleLight_ProcessInDiscAttrsExtRspCmd( pInMsg );
break;
#endif
default:
break;
}
if ( pInMsg->attrCmd )
osal_mem_free( pInMsg->attrCmd );
}
6.举例说明
swicth 发送
zclReportCmd_t reportCmd;
reportCmd.numAttr = 1;
reportCmd.attrList[0].attrID = ATTRID_MS_CMD;
reportCmd.attrList[0].dataType = ZCL_DATATYPE_UINT8;
reportCmd.attrList[0].attrData = &data;
zcl_SendReportCmd(ENDPOINT,
&DstAddr,
ZCL_CLUSTER_ID_LIGHT,
&reportCmd,TRUE,FALSE,TRUE);
light接收:
if (pInMsg->clusterId == ZCL_CLUSTER_ID_LIGHT)
{
rpt_cmd= (zclReportCmd_t *)pInMsg->attrCmd;;