Beispiel #1
0
/*********************************************************************
 * @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;
}
Beispiel #3
0
/*********************************************************************
 * @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 );
}
Beispiel #5
0
/*********************************************************************
 * @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 );
}
Beispiel #6
0
/*********************************************************************
 * @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 );
}
Beispiel #9
0
/*********************************************************************
 * @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 );
}
Beispiel #10
0
/*********************************************************************
 * @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 );
}
Beispiel #14
0
/*********************************************************************
 * @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 );
}
Beispiel #15
0
/*********************************************************************
 * @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;
}