协调器发送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的时候?
没有,开关控制面板是购买的成熟的过检的产品,不能拆开调试