This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
大神们好,我想实现这样一个场景:手机app可以控制开关面板的打开和关闭,而手动打开和关闭控制面板,app又可收到反馈,及时更新app上的显示。这时就用到了zcl的configure reporting command的指令。
我的平台是这样的:终端节点用的是标准的ZHA协议的设备。协调器用的是TI的cc2530,协调器上的程序是TI的znp,主控程序为TI的am335xsII,上面跑的是Linux开源的znp host framework(做了一点修改)。
问题是这样的:我发送了configure reporting command,收到的回应是 0x08 0x1F 0x07 0x00 与zcl 规定的 Configure Reporting Response Command Frame Format不符(少了direction和Attribute identifier字段),急求大神们解决。谢谢。
主控程序的实现是这样的:
1.绑定onoff cluster,代码如下:
int zcl_register_cluster_ss(){ unsigned char in_cluster_count = 12; unsigned short in_cluster[MAX_CLUSTER_COUNT]; memset(in_cluster, 0, MAX_CLUSTER_COUNT * sizeof(unsigned short)); in_cluster[0] = ZCL_CLUSTER_ID_GEN_BASIC; in_cluster[1] = ZCL_CLUSTER_ID_GEN_POWER_CFG; in_cluster[2] = ZCL_CLUSTER_ID_GEN_IDENTIFY; in_cluster[3] = ZCL_CLUSTER_ID_GEN_ON_OFF; in_cluster[4] = ZCL_CLUSTER_ID_GEN_COMMISSIONING; in_cluster[5] = ZCL_CLUSTER_ID_GEN_POLL_CONTROL; in_cluster[6] = ZCL_CLUSTER_ID_HA_DIAGNOSTIC; in_cluster[7] = ZCL_CLUSTER_ID_SS_IAS_ZONE; in_cluster[8] = ZCL_CLUSTER_ID_SS_IAS_ACE; in_cluster[9] = ZCL_CLUSTER_ID_SS_IAS_WD; in_cluster[10] = ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG; in_cluster[11] = ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT; unsigned char out_cluster_count = 13; unsigned short out_cluster[MAX_CLUSTER_COUNT]; memset(out_cluster, 0, MAX_CLUSTER_COUNT * sizeof(unsigned short)); out_cluster[0] = ZCL_CLUSTER_ID_GEN_BASIC; out_cluster[1] = ZCL_CLUSTER_ID_GEN_POWER_CFG; out_cluster[2] = ZCL_CLUSTER_ID_GEN_IDENTIFY; out_cluster[3] = ZCL_CLUSTER_ID_GEN_ON_OFF; out_cluster[4] = ZCL_CLUSTER_ID_GEN_COMMISSIONING; out_cluster[5] = ZCL_CLUSTER_ID_GEN_POLL_CONTROL; out_cluster[6] = ZCL_CLUSTER_ID_HA_DIAGNOSTIC; out_cluster[7] = ZCL_CLUSTER_ID_SS_IAS_ZONE; out_cluster[8] = ZCL_CLUSTER_ID_SS_IAS_ACE; out_cluster[9] = ZCL_CLUSTER_ID_SS_IAS_WD; out_cluster[10] = ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT; out_cluster[11] = ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG; out_cluster[12] = ZCL_CLUSTER_ID_GEN_SCENES; zcl_register_cluster(in_cluster_count, in_cluster, out_cluster_count, out_cluster, APP_DEVICETYPEID_SS_ENDPOINT, APP_DEVICETYPEID_SS); return APP_DEVICETYPEID_SS_ENDPOINT; }
2. zcl_register_cluster的实现如下:
int zcl_register_cluster(unsigned char in_cluster_count, unsigned short * in_cluster,unsigned char out_cluster_count, unsigned short * out_cluster, unsigned char endpoint, unsigned short appdevicetypeid){
if(in_cluster_count > MAX_CLUSTER_COUNT || out_cluster_count > MAX_CLUSTER_COUNT){
return 1;
}
RegisterFormat_t req;
memset(&req, 0, sizeof(RegisterFormat_t));
req.EndPoint= endpoint;
req.AppProfId = 0x0104;
req.AppDeviceId = appdevicetypeid;
req.AppNumInClusters = in_cluster_count;
memcpy(req.AppInClusterList, in_cluster, sizeof(unsigned short)*in_cluster_count);
req.AppNumOutClusters = out_cluster_count;
memcpy(req.AppOutClusterList, out_cluster, sizeof(unsigned short)*out_cluster_count);
sendcmd((unsigned char *)&req, AF_REGISTER);
return 0;
}
3.调用zcl_SendConfigReportCmd函数,配置onoff report命令:
CfgReportCmd.numAttr = 1;
CfgReportCmd.attrList[0].direction = 0;
CfgReportCmd.attrList[0].attrID = 0x0000;
CfgReportCmd.attrList[0].dataType = 0x10;
CfgReportCmd.attrList[0].minReportInt = 0;
CfgReportCmd.attrList[0].maxReportInt = 30;
CfgReportCmd.attrList[0].timeoutPeriod = 0;
CfgReportCmd.attrList[0].reportableChange = NULL;
struct device *d = gateway_getdevice(getgateway(), test.ieee);
if(d) {
printf("gateway_get_endpoint\n");
zcl_SendConfigReportCmd(1, 1, d->shortaddr, 0x0006, &CfgReportCmd, 0, 1, get_sequence());
}
4.zcl_SendConfigReportCmd的实现如下:
ZStatus_t zcl_SendConfigReportCmd( uint8 srcEP, uint8 dstEp, uint16 dstAddr, uint16 clusterID, zclCfgReportCmd_t *cfgReportCmd, uint8 direction, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 *buf; uint16 dataLen = 0; ZStatus_t status; uint8 i; // Find out the data length printf("numAttr is %d\n", cfgReportCmd->numAttr); for ( i = 0; i < cfgReportCmd->numAttr; i++ ) { zclCfgReportRec_t *reportRec = &(cfgReportCmd->attrList[i]); dataLen += 1 + 2; // Direction + Attribute ID if ( reportRec->direction == ZCL_SEND_ATTR_REPORTS ) { printf("ZCL_SEND_ATTR_REPORTS\n"); dataLen += 1 + 2 + 2; // Data Type + Min + Max Reporting Intervals // Find out the size of the Reportable Change field (for Analog data types) if ( zclAnalogDataType( reportRec->dataType ) ) { dataLen += zclGetDataTypeLength( reportRec->dataType ); } } else { dataLen += 2; // Timeout Period } } buf = zcl_mem_alloc( dataLen ); if ( buf != NULL ) { // Load the buffer - serially printf("load buffer\n"); uint8 *pBuf = buf; for ( i = 0; i < cfgReportCmd->numAttr; i++ ) { zclCfgReportRec_t *reportRec = &(cfgReportCmd->attrList[i]); *pBuf++ = reportRec->direction; *pBuf++ = LO_UINT16( reportRec->attrID ); *pBuf++ = HI_UINT16( reportRec->attrID ); if ( reportRec->direction == ZCL_SEND_ATTR_REPORTS ) { *pBuf++ = reportRec->dataType; *pBuf++ = LO_UINT16( reportRec->minReportInt ); *pBuf++ = HI_UINT16( reportRec->minReportInt ); *pBuf++ = LO_UINT16( reportRec->maxReportInt ); *pBuf++ = HI_UINT16( reportRec->maxReportInt ); if ( zclAnalogDataType( reportRec->dataType ) ) { pBuf = zclSerializeData( reportRec->dataType, reportRec->reportableChange, pBuf ); } } else { *pBuf++ = LO_UINT16( reportRec->timeoutPeriod ); *pBuf++ = HI_UINT16( reportRec->timeoutPeriod ); } } // for loop status = zcl_sendcommand( srcEP, dstEp, dstAddr, clusterID, ZCL_CMD_CONFIG_REPORT, FALSE, direction, disableDefaultRsp, 0, seqNum, dataLen, buf ); zcl_mem_free( buf ); } else { status = ZMemError; } return ( status ); }
5.zcl_send_command函数如下:
ZStatus_t zcl_sendcommand( uint8 srcEP, uint8 dstEp, uint16 dstaddr,
uint16 clusterID, uint8 cmd, uint8 specific, uint8 direction,
uint8 disableDefaultRsp, uint16 manuCode, uint8 seqNum,
uint16 cmdFormatLen, uint8 *cmdFormat )
{
//endPointDesc_t *epDesc;
struct zclframehdr hdr;
unsigned char * msgBuf;
uint16 msgLen;
uint8 *pBuf;
//uint8 options;
ZStatus_t status;
// epDesc = afFindEndPointDesc( srcEP );
// if ( epDesc == NULL )
// {
// return ( ZInvalidParameter ); // EMBEDDED RETURN
// }
//
//#if defined ( INTER_PAN )
// if ( StubAPS_InterPan( destAddr->panId, destAddr->endPoint ) )
// {
// options = AF_TX_OPTIONS_NONE;
// }
// else
//#endif
// {
// options = zclGetClusterOption( srcEP, clusterID );
//
// // The cluster might not have been defined to use security but if this message
// // is in response to another message that was using APS security this message
// // will be sent with APS security
// if ( !( options & AF_EN_SECURITY ) )
// {
// afIncomingMSGPacket_t *origPkt = zcl_getRawAFMsg();
//
// if ( ( origPkt != NULL ) && ( origPkt->SecurityUse == TRUE ) )
// {
// options |= AF_EN_SECURITY;
// }
// }
// }
memset( &hdr, 0, sizeof( struct zclframehdr ) );
// Not Profile wide command (like READ, WRITE)
if ( specific )
{
hdr.control.type = ZCL_FRAME_TYPE_SPECIFIC_CMD;
}
else
{
hdr.control.type = ZCL_FRAME_TYPE_PROFILE_CMD;
}
// if ( ( epDesc->simpleDesc == NULL ) ||
// ( zcl_DeviceOperational( srcEP, clusterID, hdr.fc.type,
// cmd, epDesc->simpleDesc->AppProfId ) == FALSE ) )
// {
// return ( ZFailure ); // EMBEDDED RETURN
// }
// Fill in the Maufacturer Code
if ( manuCode != 0 )
{
hdr.control.manuspecific = 1;
hdr.manucode = manuCode;
}
// Set the Command Direction
if ( direction )
{
hdr.control.direction = ZCL_FRAME_SERVER_CLIENT_DIR;
}
else
{
hdr.control.direction = ZCL_FRAME_CLIENT_SERVER_DIR;
}
// Set the Disable Default Response field
if ( disableDefaultRsp )
{
hdr.control.disabledefaultrsp = 1;
}
else
{
hdr.control.disabledefaultrsp = 0;
}
// Fill in the Transaction Sequence Number
hdr.transseqnum = seqNum;
// Fill in the command
hdr.commandid = cmd;
// calculate the needed buffer size
msgLen = zclCalcHdrSize( &hdr );
msgLen += cmdFormatLen;
// Allocate the buffer needed
msgBuf = (unsigned char *)malloc( msgLen );
memset(msgBuf, 0, msgLen);
if ( msgBuf != NULL )
{
// Fill in the ZCL Header
pBuf = zclBuildHdr( &hdr, msgBuf );
// Fill in the command frame
memcpy( pBuf, cmdFormat, cmdFormatLen );
DataRequestFormat_t req;
memset(&req, 0, sizeof(DataRequestFormat_t));
req.DstAddr = dstaddr;
req.DstEndpoint = dstEp;
req.SrcEndpoint = srcEP;
req.ClusterID = clusterID;
// uint8_t TransID;
// uint8_t Options;
// uint8_t Radius;
req.Len = msgLen;
memcpy(req.Data, msgBuf, msgLen);
free(msgBuf);
sendcmd((unsigned char *)&req, AF_DATA_REQUEST);
}
else
{
status = ZMemError;
}
return ( status );
}