/********************************************************************* * @fn zclPartition_ProcessInCmd_ReadHandshakeParam * * @brief Process in the received Poll Control CheckIn cmd (sent to ZC/ZR) * * @param pInMsg - pointer to the incoming message * @param pCBs - pointer to the application callbacks * * @return ZStatus_t */ static ZStatus_t zclPartition_ProcessInCmd_ReadHandshakeParam( zclIncoming_t *pInMsg, zclPartition_AppCallbacks_t *pCBs ) { afAddrType_t * pSrcAddr; zclCmdReadHandshakeParam_t cmd; ZStatus_t status; uint8 msglen; if ( pCBs->pfnPartition_ReadHandshakeParam ) { // the app callback will send response pSrcAddr = &(pInMsg->msg->srcAddr); // convert from OTA endian to native form msglen = (uint8)(pInMsg->pDataLen); // pDataLen is a misnomer should be iDataLen (it's a 16-bit length of the data field). status = zclPartition_ConvertOtaToNative_ReadHandshakeParam( &cmd, pInMsg->pData, msglen ); if ( status != ZSuccess ) { return ( status ); } // also need the seq # for reply cmd.seqNum = pInMsg->hdr.transSeqNum; // send to the app. status = ( pCBs->pfnPartition_ReadHandshakeParam( pSrcAddr, &cmd ) ); // done with temporary memory, free it. zcl_mem_free( cmd.pAttrID ); return ( status ); } return ( ZFailure ); }
/********************************************************************* * @fn zclApplianceStatistics_Send_LogNotification * * @brief Request sent to client for Log Notification. * * @param srcEP - Sending application's endpoint * @param dstAddr - where you want the message to go * @param pPayload: * timeStamp - timestamp of the notification * logID - identifies uniquely the log information contained in log payload * logLength - indicates the length in bytes of log payload * logPayload - variable length payload * @param disableDefaultRsp - whether to disable the Default Response command * @param seqNum - sequence number * * @return ZStatus_t */ ZStatus_t zclApplianceStatistics_Send_LogNotification( uint8 srcEP, afAddrType_t *dstAddr, zclCmdApplianceStatisticsLogNotificationPayload_t *pPayload, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 *pZclPayload; // OTA ZCL Payload uint16 zclPayloadLen; ZStatus_t status; // convert from Native to OTA format pZclPayload = zclApplianceStatistics_LogNotification_NativeToOta( pPayload , &zclPayloadLen ); if( !pZclPayload ) { return ZFailure; // no memory } // sent over the air status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_HA_APPLIANCE_STATISTICS, COMMAND_APPLIANCE_STATISTICS_LOG_NOTIFICATION, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, zclPayloadLen, pZclPayload ); // done with packet zcl_mem_free( pZclPayload ); return status; }
/********************************************************************* * @fn zclPartition_Send_MultipleAck * * @brief Call to send out Poll Control CheckIn command from ZED to ZR/ZC. The Rsp * will indicate whether to stay awake or go back to sleep. * * @param srcEP - Sending application's endpoint * @param dstAddr - where you want the message to go * @param pCmd - multi ack response * @param disableDefaultRsp - whether to disable the Default Response command * @param seqNum - sequence number * * @return ZStatus_t */ ZStatus_t zclPartition_Send_MultipleAck( uint8 srcEP, afAddrType_t *dstAddr, zclCmdMultipleAck_t *pCmd, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 buflen; uint8 NAckSize; uint8 offset; uint8 i; uint8 *buf; ZStatus_t status; // determine if NACKs are 1 or 2 bytes if ( pCmd->options & ZCL_PARTITION_OPTIONS_NACK_16BIT ) { NAckSize = 2; } else { NAckSize = 1; } // create buffer large enough for multiple ACKs command // ACKOptions is 1 byte, FirstFrameID and NACKIds are 1 or 2 bytes depending on options // [ACKOptions][FirstFrameID][NACKId]...[NACKId] buflen = 1 + NAckSize * ( 1 + pCmd->numNAcks ); buf = zcl_mem_alloc( buflen ); if ( !buf ) { return ( ZMemError ); // memory error } // fill in the buffer buf[0] = pCmd->options; offset = 1; buf[offset++] = LO_UINT16( pCmd->firstFrameID ); if ( NAckSize == 2 ) { buf[offset++] = HI_UINT16( pCmd->firstFrameID ); } for ( i = 0; i < pCmd->numNAcks ; ++i ) { buf[offset++] = LO_UINT16( pCmd->pNAckID[i] ); if ( NAckSize == 2 ) { buf[offset++] = HI_UINT16( pCmd->pNAckID[i] ); } } // send, with payload status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_PARTITION, COMMAND_PARTITION_MULTIPLE_ACK, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, offset, buf); // done, free the memory zcl_mem_free( buf ); return ( status ); }
/********************************************************************* * @fn zclElectricalMeasurement_Send_GetMeasurementProfileRsp * * @brief Call to send out Electrical Measurement Get Measurement Profile Response. This will * tell the client the appropriate parameters of the measurement profile. * * @param srcEP - Sending application's endpoint * @param dstAddr - where you want the message to go * @param pPayload: * startTime - represents the end time of the most chronologically recent interval being requested * status - table status enumeration lists the valid values returned in status field * profileIntervalPeriod - time frame used to capture parameter for profiling purposes * numberOfIntervalsDelivered - number of intervals the device is returning * attributeID - attribute that has been profiled by the application * intervals - array of intervals that depend on numberOfIntervalsDelivered, type based on attributeID * @param disableDefaultRsp - whether to disable the Default Response command * @param seqNum - sequence number * * @return ZStatus_t */ ZStatus_t zclElectricalMeasurement_Send_GetMeasurementProfileRsp( uint8 srcEP, afAddrType_t *dstAddr, zclElectricalMeasurementGetMeasurementProfileRsp_t *pPayload, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 i; uint8 offset; uint8 *pBuf; // variable length payload uint8 attrRtn; uint8 calculatedAttrLen; uint16 calculatedIntervalSize; uint16 calculatedBufLen; ZStatus_t status; zclAttrRec_t attrRec; // determine if attribute ID is found per EP and cluster ID attrRtn = zclFindAttrRec( dstAddr->endPoint, ZCL_CLUSTER_ID_HA_ELECTRICAL_MEASUREMENT, pPayload->attributeID, &attrRec ); if ( attrRtn == TRUE ) { // if found, determine length of attribute based on given type calculatedAttrLen = zclGetDataTypeLength( attrRec.attr.dataType ); } calculatedIntervalSize = calculatedAttrLen * pPayload->numberOfIntervalsDelivered; // get a buffer large enough to hold the whole packet, including size of variable array calculatedBufLen = ( 9 + calculatedIntervalSize ); pBuf = zcl_mem_alloc( calculatedBufLen ); if ( !pBuf ) { return ( ZMemError ); // no memory, return failure } pBuf[0] = BREAK_UINT32(pPayload->startTime, 0); pBuf[1] = BREAK_UINT32(pPayload->startTime, 1); pBuf[2] = BREAK_UINT32(pPayload->startTime, 2); pBuf[3] = BREAK_UINT32(pPayload->startTime, 3); pBuf[4] = pPayload->status; pBuf[5] = pPayload->profileIntervalPeriod; pBuf[6] = pPayload->numberOfIntervalsDelivered; pBuf[7] = LO_UINT16(pPayload->attributeID); pBuf[8] = HI_UINT16(pPayload->attributeID); offset = 9; for ( i = 0; i < calculatedIntervalSize; i++ ) { pBuf[offset++] = pPayload->pIntervals[i]; } status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_HA_ELECTRICAL_MEASUREMENT, COMMAND_ELECTRICAL_MEASUREMENT_GET_MEASUREMENT_PROFILE_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, calculatedBufLen, pBuf ); zcl_mem_free( pBuf ); return ( status ); }
/********************************************************************* * @fn zclPartition_Send_ReadHandshakeParamRsp * * @brief Call to send out Poll Control CheckIn command from ZED to ZR/ZC. The Rsp * will indicate whether to stay awake or go back to sleep. * * @param srcEP - Sending application's endpoint * @param dstAddr - where you want the message to go * @param pCmd - read multi-attribues response * @param disableDefaultRsp - whether to disable the Default Response command * @param seqNum - sequence number * * @return ZStatus_t */ ZStatus_t zclPartition_Send_ReadHandshakeParamRsp( uint8 srcEP, afAddrType_t *dstAddr, zclCmdReadHandshakeParamRsp_t *pCmd, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 buflen; uint8 offset; uint8 i; uint8 *buf; ZStatus_t status; // allocate enough memory for all records. some may end up being short, so we may not use all this buffer. buflen = sizeof( uint16 ) + ( pCmd->numRecords * sizeof ( zclPartitionReadRec_t ) ); buf = zcl_mem_alloc( buflen ); if ( !buf ) { return ( ZMemError ); // memory error } // fill in the buffer buf[0] = LO_UINT16( pCmd->clusterID ); buf[1] = HI_UINT16( pCmd->clusterID ); offset = 2; for ( i = 0; i < pCmd->numRecords; ++i ) { buf[offset++] = LO_UINT16( pCmd->pReadRecord[i].attrID ); buf[offset++] = HI_UINT16( pCmd->pReadRecord[i].attrID ); buf[offset++] = pCmd->pReadRecord[i].status; if ( pCmd->pReadRecord[i].status == ZCL_STATUS_SUCCESS ) { buf[offset++] = pCmd->pReadRecord[i].dataType; // this only works for Partition Cluster because it's attributes are either uint8 or uint16 buf[offset++] = LO_UINT16( pCmd->pReadRecord[i].attr ); if ( pCmd->pReadRecord[i].dataType == ZCL_DATATYPE_UINT16 ) { buf[offset++] = LO_UINT16( pCmd->pReadRecord[i].attr ); } } } buflen = offset; // send, with payload status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_PARTITION, COMMAND_PARTITION_READ_HANDSHAKE_PARAM_RSP, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, buflen, buf); // done, free the memory zcl_mem_free( buf ); return ( status ); }
/********************************************************************* * @fn zclPartition_Send_WriteHandshakeParam * * @brief Call to send out Poll Control CheckIn command from ZED to ZR/ZC. The Rsp * will indicate whether to stay awake or go back to sleep. * * @param srcEP - Sending application's endpoint * @param dstAddr - where you want the message to go * @param pCmd - what parameters to write * @param disableDefaultRsp - whether to disable the Default Response command * @param seqNum - sequence number * * @return ZStatus_t */ ZStatus_t zclPartition_Send_WriteHandshakeParam( uint8 srcEP, afAddrType_t *dstAddr, zclCmdWriteHandshakeParam_t *pCmd, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 buflen; uint8 offset; uint8 i; uint8 *buf; uint16 clusterID; ZStatus_t status; // allocate the memory. write records are assumed to be either uint8 or uint16 // WriteRecord: [AttrID][AttrType][AttrData] = max 5 bytes per record, if attrType is uint16 or uint8 buflen = PAYLOAD_LEN_WRITE_HANDSHAKE_PARAM + ( pCmd->numRecords * PAYLOAD_LEN_WRITE_REC ); buf = zcl_mem_alloc( buflen ); if ( !buf ) { return ( ZMemError ); // memory error } // fill in the buffer clusterID = pCmd->clusterID; buf[0] = LO_UINT16( clusterID ); buf[1] = HI_UINT16( clusterID ); offset = 2; for ( i = 0; i < pCmd->numRecords; ++i ) { // copy write record to output buffer buf[offset++] = LO_UINT16( pCmd->pWriteRecord[i].attrID ); buf[offset++] = HI_UINT16( pCmd->pWriteRecord[i].attrID ); buf[offset++] = pCmd->pWriteRecord[i].dataType; // all writeable Partition attributes are either uint8 or uint16 buf[offset++] = LO_UINT16( pCmd->pWriteRecord[i].attr ); if ( pCmd->pWriteRecord[i].dataType == ZCL_DATATYPE_UINT16 ) { buf[offset++] = HI_UINT16( pCmd->pWriteRecord[i].attr ); } } // send, with payload status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_PARTITION, COMMAND_PARTITION_WRITE_HANDSHAKE_PARAM, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, offset, buf); // done, free the memory zcl_mem_free( buf ); return ( status ); }
/********************************************************************* * @fn zclApplianceStatistics_Send_LogQueueRsp * * @brief Response sent to client from LogQueueReq cmd. * * @param srcEP - Sending application's endpoint * @param dstAddr - where you want the message to go * @param pPayload: * logQueueSize - defines the # of logID records * logID - variable length list of logIDs * @param disableDefaultRsp - whether to disable the Default Response command * @param seqNum - sequence number * * @return ZStatus_t */ ZStatus_t zclApplianceStatistics_Send_LogQueueRsp( uint8 srcEP, afAddrType_t *dstAddr, zclCmdApplianceStatisticsLogQueueRspPayload_t *pPayload, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 *pZclPayload; // OTA ZCL Payload uint16 zclPayloadLen; ZStatus_t status; // convert from native to OTA format pZclPayload = zclApplianceStatistics_LogQueueRsp_NativeToOta( pPayload , &zclPayloadLen ); // send over the air status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_HA_APPLIANCE_STATISTICS, COMMAND_APPLIANCE_STATISTICS_LOG_QUEUE_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, zclPayloadLen, pZclPayload ); zcl_mem_free( pZclPayload ); return status; }
/********************************************************************* * @fn zclApplianceStatistics_ProcessInCmd_LogQueueRsp * * @brief Process in the received Appliance Statistics Log Queue Response cmd * * @param pInMsg - pointer to the incoming message * @param pCBs - pointer to the application callback * * @return ZStatus_t */ static ZStatus_t zclApplianceStatistics_ProcessInCmd_LogQueueRsp( zclIncoming_t *pInMsg, zclApplianceStatistics_AppCallbacks_t *pCBs ) { zclCmdApplianceStatisticsLogQueueRspPayload_t cmd; ZStatus_t status = ZFailure; if ( pCBs->pfnApplianceStatistics_LogQueueRsp ) { // convert from OTA format to native format status = zclApplianceStatistics_LogQueueRsp_OtaToNative( &cmd, &pInMsg->pData[0] ); // successfully converted (and log allocated) if( status == ZSuccess ) { // call user callback status = pCBs->pfnApplianceStatistics_LogQueueRsp( &cmd ); zcl_mem_free( cmd.pLogID ); } } return ( status ); }
/********************************************************************* * @fn zclPartition_Send_ReadHandshakeParam * * @brief Call to send out Poll Control CheckIn command from ZED to ZR/ZC. The Rsp * will indicate whether to stay awake or go back to sleep. * * @param srcEP - Sending application's endpoint * @param dstAddr - where you want the message to go * @param pCmd - what parameters to read * @param disableDefaultRsp - whether to disable the Default Response command * @param seqNum - sequence number * * @return ZStatus_t */ ZStatus_t zclPartition_Send_ReadHandshakeParam( uint8 srcEP, afAddrType_t *dstAddr, zclCmdReadHandshakeParam_t *pCmd, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 buflen; uint8 offset; uint8 *buf; uint8 i; uint16 clusterID; uint16 attrID; ZStatus_t status; // allocate the memory buflen = sizeof( uint16 ) + pCmd->numAttrs * sizeof( uint16 ); buf = zcl_mem_alloc( buflen ); if ( !buf ) { return ( ZMemError ); // memory error } // fill in the buffer clusterID = pCmd->clusterID; buf[0] = LO_UINT16( clusterID ); buf[1] = HI_UINT16( clusterID ); for ( i = 0; i < pCmd->numAttrs; ++i ) { attrID = pCmd->pAttrID[i]; buf[offset++] = LO_UINT16( attrID ); buf[offset++] = HI_UINT16( attrID ); } // send, with payload status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_PARTITION, COMMAND_PARTITION_READ_HANDSHAKE_PARAM, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, buflen, buf); // done, free the memory zcl_mem_free( buf ); return ( status ); }
/********************************************************************* * @fn zclPartition_Send_TransferPartitionedFrame * * @brief send a single block (partitioned frame) to a remote receiver * * @param srcEP - Sending application's endpoint * @param dstAddr - where you want the message to go * @param pCmd - the partitioned frame * @param disableDefaultRsp - whether to disable the Default Response command * @param seqNum - sequence number * * @return ZStatus_t or ZCL_STATUS_INSUFFICIENT_SPACE */ ZStatus_t zclPartition_Send_TransferPartitionedFrame( uint8 srcEP, afAddrType_t *dstAddr, zclCmdTransferPartitionedFrame_t *pCmd, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 buflen; uint8 offset; uint8 *buf; uint16 indicator; ZStatus_t status; // allocate the memory large enough to hold the OTA frame with a 2-byte indicator buflen = PAYLOAD_LEN_TRANSFER_PARTITIONED_FRAME + pCmd->frameLen; buf = zcl_mem_alloc( buflen ); if ( !buf ) { return ( ZMemError ); // memory error } // fill in the OTA frame buffer buf[0] = pCmd->fragmentationOptions; indicator = pCmd->partitionIndicator; buf[1] = LO_UINT16(indicator); offset = 2; if ( pCmd->fragmentationOptions & ZCL_PARTITION_OPTIONS_INDICATOR_16BIT ) { buf[offset++] = HI_UINT16(indicator); } buf[offset++] = pCmd->frameLen; // octet string begins with length zcl_memcpy( &buf[offset], pCmd->pFrame, pCmd->frameLen ); offset += pCmd->frameLen; // send, with payload status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_GEN_PARTITION, COMMAND_PARTITION_TRANSFER_PARTITIONED_FRAME, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, offset, buf ); // done, free the memory zcl_mem_free( buf ); return ( status ); }
/********************************************************************* * @fn zclElectricalMeasurement_ProcessInCmd_GetMeasurementProfileRsp * * @brief Process in the received Electrical Measurement Get Measurement Profile Response cmd * * @param pInMsg - pointer to the incoming message * @param pCBs - pointer to the application callbacks * * @return ZStatus_t */ static ZStatus_t zclElectricalMeasurement_ProcessInCmd_GetMeasurementProfileRsp( zclIncoming_t *pInMsg, zclElectricalMeasurement_AppCallbacks_t *pCBs ) { uint8 i; uint8 offset; uint16 calculatedIntervalSize; zclElectricalMeasurementGetMeasurementProfileRsp_t cmd; ZStatus_t status; if ( pCBs->pfnElectricalMeasurement_GetMeasurementProfileRsp ) { // determine size of intervals by subtracting size of startTime, status, // profileIntervalPeriod, numberOfIntervalsDelivered, and attributeID from message length calculatedIntervalSize = pInMsg->pDataLen - 9; cmd.pIntervals = zcl_mem_alloc( calculatedIntervalSize ); if ( !cmd.pIntervals ) { return ( ZMemError ); // no memory, return failure } cmd.startTime = BUILD_UINT32( pInMsg->pData[0], pInMsg->pData[1], pInMsg->pData[2], pInMsg->pData[3] ); cmd.status = pInMsg->pData[4]; cmd.profileIntervalPeriod = pInMsg->pData[5]; cmd.numberOfIntervalsDelivered = pInMsg->pData[6]; cmd.attributeID = BUILD_UINT16( pInMsg->pData[7], pInMsg->pData[8] ); offset = 9; for ( i = 0; i < calculatedIntervalSize; i++ ) { cmd.pIntervals[i] = pInMsg->pData[offset++]; } status = ( pCBs->pfnElectricalMeasurement_GetMeasurementProfileRsp( &cmd ) ); zcl_mem_free( cmd.pIntervals ); return status; } return ( ZFailure ); }
/********************************************************************* * @fn zclElectricalMeasurement_ProcessInCmd_GetProfileInfoRsp * * @brief Process in the received Electrical Measurement Get Profile Info Response cmd * * @param pInMsg - pointer to the incoming message * @param pCBs - pointer to the application callbacks * * @return ZStatus_t */ static ZStatus_t zclElectricalMeasurement_ProcessInCmd_GetProfileInfoRsp( zclIncoming_t *pInMsg, zclElectricalMeasurement_AppCallbacks_t *pCBs ) { uint8 i; uint8 offset; uint16 calculatedArraySize; zclElectricalMeasurementGetProfileInfoRsp_t cmd; ZStatus_t status; if ( pCBs->pfnElectricalMeasurement_GetProfileInfoRsp ) { // calculate size of variable array calculatedArraySize = pInMsg->pDataLen - 3; // variable array - 3 bytes of fixed variables cmd.pListOfAttributes = zcl_mem_alloc( calculatedArraySize ); if ( !cmd.pListOfAttributes ) { return ( ZMemError ); // no memory, return failure } cmd.profileCount = pInMsg->pData[0]; cmd.profileIntervalPeriod = pInMsg->pData[1]; cmd.maxNumberOfIntervals = pInMsg->pData[2]; cmd.numberOfAttributes = calculatedArraySize / sizeof( uint16 ); offset = 3; for ( i = 0; i < cmd.numberOfAttributes; i++ ) { cmd.pListOfAttributes[i] = BUILD_UINT16( pInMsg->pData[offset], pInMsg->pData[offset + 1] ); offset += 2; } status = ( pCBs->pfnElectricalMeasurement_GetProfileInfoRsp( &cmd ) ); zcl_mem_free( cmd.pListOfAttributes ); return status; } return ( ZFailure ); }
/********************************************************************* * @fn zclElectricalMeasurement_Send_GetProfileInfoRsp * * @brief Call to send out Electrical Measurement Get Profile Info Response. This will tell * the client the appropriate parameters of the measurement profile. * * @param srcEP - Sending application's endpoint * @param dstAddr - where you want the message to go * @param pPayload: * profileCount - total number of supported profiles * profileIntervalPeriod - indicates the time frame of capture for profiling purposes * maxNumberOfIntervals - maximum number of intervals allowed for the response * pListOfAttributes - represents list of attributes being profiled * @param disableDefaultRsp - whether to disable the Default Response command * @param seqNum - sequence number * * @return ZStatus_t */ ZStatus_t zclElectricalMeasurement_Send_GetProfileInfoRsp( uint8 srcEP, afAddrType_t *dstAddr, zclElectricalMeasurementGetProfileInfoRsp_t *pPayload, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 i; uint8 *pBuf; // variable length payload uint8 offset; uint16 calculatedBufSize; ZStatus_t status; // get a buffer large enough to hold the whole packet calculatedBufSize = ( 3 + ( pPayload->numberOfAttributes * sizeof( uint16 ) ) ); // size of fixed variables plus variable array pBuf = zcl_mem_alloc( calculatedBufSize ); if ( !pBuf ) { return ( ZMemError ); // no memory } pBuf[0] = pPayload->profileCount; pBuf[1] = pPayload->profileIntervalPeriod; pBuf[2] = pPayload->maxNumberOfIntervals; offset = 3; for ( i = 0; i < pPayload->numberOfAttributes; i++ ) { pBuf[offset++] = LO_UINT16(pPayload->pListOfAttributes[i]); pBuf[offset++] = HI_UINT16(pPayload->pListOfAttributes[i]); } status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_HA_ELECTRICAL_MEASUREMENT, COMMAND_ELECTRICAL_MEASUREMENT_GET_PROFILE_INFO_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, calculatedBufSize, pBuf ); zcl_mem_free( pBuf ); return ( status ); }
/********************************************************************* * @fn zclThermostat_ProcessInCmd_GetWeeklyScheduleRsp * * @brief Process in the received Get Weekly Schedule Response cmd * * @param pInMsg - pointer to the incoming message * @param pCBs - pointer to the application callbacks * * @return ZStatus_t */ static ZStatus_t zclThermostat_ProcessInCmd_GetWeeklyScheduleRsp( zclIncoming_t *pInMsg, zclHVAC_AppCallbacks_t *pCBs ) { uint8 i; uint8 offset; uint8 modeBuff; // buffer to determine how to incorporate heat/cool set points uint8 numTransitions; // buffer for number of transitions for sequence uint16 arrayRecordSize; zclThermostatWeeklySchedule_t cmd; ZStatus_t status; if ( pCBs->pfnHVAC_GetWeeklyScheduleRsp ) { numTransitions = pInMsg->pData[0]; modeBuff = pInMsg->pData[2]; // store the modeForSequence in buffer // if either the heat or cool set points if( ( modeBuff == HVAC_THERMOSTAT_MODE_HEAT ) || ( modeBuff == HVAC_THERMOSTAT_MODE_COOL ) ) { // calculate the number of transitions multiplied by size of transitionTime and heatSetPoint/coolSetPoint arrayRecordSize = ( numTransitions * 4 ); } // if both cool and heat set points else if( modeBuff == HVAC_THERMOSTAT_MODE_BOTH ) { // calculate the number of transitions multiplied by size of transitionTime, heatSetPoint, and coolSetPoint arrayRecordSize = ( numTransitions * 6 ); } else { return ( ZFailure ); // invalid mode field } // allocate memory cmd.sThermostateSequenceMode.psThermostatModeBoth = zcl_mem_alloc( arrayRecordSize ); if( !cmd.sThermostateSequenceMode.psThermostatModeBoth ) { return ( ZMemError ); // no memory } cmd.numberOfTransitionsForSequence = numTransitions; cmd.dayOfWeekForSequence = pInMsg->pData[1]; cmd.modeForSequence = modeBuff; offset = 3; for( i = 0; i < numTransitions; i++ ) { if( modeBuff == HVAC_THERMOSTAT_MODE_HEAT ) // heat set point { cmd.sThermostateSequenceMode.psThermostatModeHeat[i].transitionTime = BUILD_UINT16( pInMsg->pData[offset], pInMsg->pData[offset + 1] ); cmd.sThermostateSequenceMode.psThermostatModeHeat[i].heatSetPoint = BUILD_UINT16( pInMsg->pData[offset + 2], pInMsg->pData[offset + 3] ); offset += 4; } else if( modeBuff == HVAC_THERMOSTAT_MODE_COOL ) // cool set point { cmd.sThermostateSequenceMode.psThermostatModeCool[i].transitionTime = BUILD_UINT16( pInMsg->pData[offset], pInMsg->pData[offset + 1] ); cmd.sThermostateSequenceMode.psThermostatModeCool[i].coolSetPoint = BUILD_UINT16( pInMsg->pData[offset + 2], pInMsg->pData[offset + 3] ); offset += 4; } else if( modeBuff == HVAC_THERMOSTAT_MODE_BOTH ) // both cool and heat set points { cmd.sThermostateSequenceMode.psThermostatModeBoth[i].transitionTime = BUILD_UINT16( pInMsg->pData[offset], pInMsg->pData[offset + 1] ); cmd.sThermostateSequenceMode.psThermostatModeBoth[i].heatSetPoint = BUILD_UINT16( pInMsg->pData[offset + 2], pInMsg->pData[offset + 3] ); cmd.sThermostateSequenceMode.psThermostatModeBoth[i].coolSetPoint = BUILD_UINT16( pInMsg->pData[offset + 4], pInMsg->pData[offset + 5] ); offset += 6; } else { return ( ZFailure ); // unsupported mode } } status = ( pCBs->pfnHVAC_GetWeeklyScheduleRsp( &cmd ) ); zcl_mem_free( cmd.sThermostateSequenceMode.psThermostatModeBoth ); return status; } return ( ZFailure ); }
/********************************************************************* * @fn zclHVAC_SendGetWeeklyScheduleRsp * * @brief Call to send out a Get Weekly Schedule Response Command * * @param srcEP - Sending application's endpoint * @param dstAddr - where you want the message to go * @param pPayload - payload for Get Weekly Schedule rsp * @param seqNum - transaction sequence number * * @return ZStatus_t */ ZStatus_t zclHVAC_SendGetWeeklyScheduleRsp( uint8 srcEP, afAddrType_t *dstAddr, zclThermostatWeeklySchedule_t *pPayload, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 i; uint8 modeBuff; // buffer to determine how to incorporate heat/cool set points uint8 *pBuf; // variable length payload uint8 offset; uint16 arrayRecordSize; // number of bytes in record array uint16 calculatedBufSize; ZStatus_t status; modeBuff = pPayload->modeForSequence; // store the modeForSequence in buffer // if either the heat or cool set points if( ( modeBuff == HVAC_THERMOSTAT_MODE_HEAT ) || ( modeBuff == HVAC_THERMOSTAT_MODE_COOL ) ) { // calculate the number of transitions multiplied by size of transitionTime and heatSetPoint/coolSetPoint arrayRecordSize = ( pPayload->numberOfTransitionsForSequence * PAYLOAD_LEN_WEEKLY_SCHEDULE_COOL_HEAT_MODE ); } // if both cool and heat set points else if( modeBuff == HVAC_THERMOSTAT_MODE_BOTH ) { // calculate the number of transitions multiplied by size of transitionTime, heatSetPoint, and coolSetPoint arrayRecordSize = ( pPayload->numberOfTransitionsForSequence * PAYLOAD_LEN_WEEKLY_SCHEDULE_BOTH_MODES ); } else { return ( ZFailure ); // invalid data } // get a buffer large enough to hold the whole packet calculatedBufSize = ( PAYLOAD_LEN_WEEKLY_SCHEDULE + arrayRecordSize ); pBuf = zcl_mem_alloc( calculatedBufSize ); if( !pBuf ) { return ( ZFailure ); // no memory } // over-the-air is always little endian. Break into a byte stream. pBuf[0] = pPayload->numberOfTransitionsForSequence; pBuf[1] = pPayload->dayOfWeekForSequence; pBuf[2] = pPayload->modeForSequence; offset = 3; for( i = 0; i < ( pPayload->numberOfTransitionsForSequence ); i++ ) { if( modeBuff == HVAC_THERMOSTAT_MODE_HEAT ) // heat set point { pBuf[offset++] = LO_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeHeat[i].transitionTime ); pBuf[offset++] = HI_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeHeat[i].transitionTime ); pBuf[offset++] = LO_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeHeat[i].heatSetPoint ); pBuf[offset++] = HI_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeHeat[i].heatSetPoint ); } else if( modeBuff == HVAC_THERMOSTAT_MODE_COOL ) // cool set point { pBuf[offset++] = LO_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeCool[i].transitionTime ); pBuf[offset++] = HI_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeCool[i].transitionTime ); pBuf[offset++] = LO_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeCool[i].coolSetPoint ); pBuf[offset++] = HI_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeCool[i].coolSetPoint ); } else if( modeBuff == HVAC_THERMOSTAT_MODE_BOTH ) // both cool and heat set points { pBuf[offset++] = LO_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeBoth[i].transitionTime ); pBuf[offset++] = HI_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeBoth[i].transitionTime ); pBuf[offset++] = LO_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeBoth[i].heatSetPoint ); pBuf[offset++] = HI_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeBoth[i].heatSetPoint ); pBuf[offset++] = LO_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeBoth[i].coolSetPoint ); pBuf[offset++] = HI_UINT16( pPayload->sThermostateSequenceMode.psThermostatModeBoth[i].coolSetPoint ); } else { return ( ZFailure ); // unsupported mode } } status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_HVAC_THERMOSTAT, COMMAND_THERMOSTAT_GET_WEEKLY_SCHEDULE_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, calculatedBufSize, pBuf ); zcl_mem_free( pBuf ); return status; }