大神们好,我想实现这样一个场景:手机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 lengthprintf("numAttr is %d\n", cfgReportCmd->numAttr);for ( i = 0; i < cfgReportCmd->numAttr; i++ ){zclCfgReportRec_t *reportRec = &(cfgReportCmd->attrList[i]);dataLen += 1 + 2; // Direction + Attribute IDif ( 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 - seriallyprintf("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 loopstatus = 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 Codeif ( manuCode != 0 ){hdr.control.manuspecific = 1;hdr.manucode = manuCode;}// Set the Command Directionif ( direction ){hdr.control.direction = ZCL_FRAME_SERVER_CLIENT_DIR;}else{hdr.control.direction = ZCL_FRAME_CLIENT_SERVER_DIR;}// Set the Disable Default Response fieldif ( disableDefaultRsp ){hdr.control.disabledefaultrsp = 1;}else{hdr.control.disabledefaultrsp = 0;}// Fill in the Transaction Sequence Numberhdr.transseqnum = seqNum;// Fill in the commandhdr.commandid = cmd;// calculate the needed buffer sizemsgLen = zclCalcHdrSize( &hdr );msgLen += cmdFormatLen;// Allocate the buffer neededmsgBuf = (unsigned char *)malloc( msgLen );memset(msgBuf, 0, msgLen);if ( msgBuf != NULL ){// Fill in the ZCL HeaderpBuf = zclBuildHdr( &hdr, msgBuf );// Fill in the command framememcpy( 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 ); }
VV:
开关面板有没有断点调试过,在接收configuration command的时候?
chi chan:
回复 VV:
没有,开关控制面板是购买的成熟的过检的产品,不能拆开调试