协调器发送configure reporting command的问题
时间:10-02
整理:3721RD
点击:
大神们好,我想实现这样一个场景:手机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 );
}
开关面板有没有断点调试过,在接收configuration command的时候?
没有,开关控制面板是购买的成熟的过检的产品,不能拆开调试
