예제 #1
0
/*********************************************************************
 * @fn      zclApplianceStatistics_LogNotification_NativeToOta
 *
 * @brief   Converts from native to OTA format.
 *
 * @param   disableDefaultRsp - whether to disable the Default Response command
 * @param   pZclPayloadLen - returns zcl payload len
 *
 * @return  pointer to zcl payload
*/
uint8 *zclApplianceStatistics_LogNotification_NativeToOta( zclCmdApplianceStatisticsLogNotificationPayload_t *pPayload , uint16 * pZclPayloadLen )
{
  uint8 *pZclPayload;      // OTA ZCL payload
  uint16 zclPayloadLen;    // OTA ZCL payload length
  uint16 i;

  // get a buffer large enough to hold the whole packet
  zclPayloadLen = 12 + (uint16)( pPayload->logLength );   // 12=sizeof(TimeStamp) + sizeof(LogID) + sizeof(LogLength)
  pZclPayload = zcl_mem_alloc( zclPayloadLen );
  if( !pZclPayload )
    return NULL;  // no memory

  // convert from Native to OTA format
  pZclPayload[0] = BREAK_UINT32(pPayload->timeStamp, 0);
  pZclPayload[1] = BREAK_UINT32(pPayload->timeStamp, 1);
  pZclPayload[2] = BREAK_UINT32(pPayload->timeStamp, 2);
  pZclPayload[3] = BREAK_UINT32(pPayload->timeStamp, 3);
  pZclPayload[4] = BREAK_UINT32(pPayload->logID, 0);
  pZclPayload[5] = BREAK_UINT32(pPayload->logID, 1);
  pZclPayload[6] = BREAK_UINT32(pPayload->logID, 2);
  pZclPayload[7] = BREAK_UINT32(pPayload->logID, 3);
  pZclPayload[8] = BREAK_UINT32(pPayload->logLength, 0);
  pZclPayload[9] = BREAK_UINT32(pPayload->logLength, 1);
  pZclPayload[10] = BREAK_UINT32(pPayload->logLength, 2);
  pZclPayload[11] = BREAK_UINT32(pPayload->logLength, 3);
  for( i = 0; i < pPayload->logLength; ++i )
    pZclPayload[12 + i] = pPayload->pLogPayload[i];

  // return payload and length
  *pZclPayloadLen = zclPayloadLen;
  return pZclPayload;
}
예제 #2
0
/*********************************************************************
 * @fn      zclPartition_ConvertOtaToNative_ReadHandshakeParam
 *
 * @brief   Helper function used to process an incoming ReadHandshakeParam
 *          command. Remember to free memory.
 *
 * @param   pCmd   - (output) the converted command
 * @param   buf    - pointer to incoming frame (just after ZCL header)
 * @param   buflen - length of buffer (ZCL payload)
 *
 * @return  ZStatus_t - ZCL_STATUS_MALFORMED_COMMAND, ZMemError or ZCL_STATUS_SUCCESS
 */
ZStatus_t zclPartition_ConvertOtaToNative_ReadHandshakeParam( zclCmdReadHandshakeParam_t *pCmd, uint8 *buf, uint8 buflen )
{
  uint8 offset;
  uint8 i;

  // must have at least 1 attribute (clusterID + attrID)
  if ( buflen < 4 )
  {
    return ( ZCL_STATUS_MALFORMED_COMMAND );
  }

  pCmd->clusterID = BUILD_UINT16( buf[0], buf[1] );

  // allocate memory for attribute list
  pCmd->numAttrs = ( buflen - 2 ) >> 1;   // each AttrID is 2 bytes, - length of ClusterID
  pCmd->pAttrID = zcl_mem_alloc( (pCmd->numAttrs) << 1 );  // allocate 2 bytes per attribute
  if ( !pCmd->pAttrID )
  {
    return ( ZMemError ); // memory error
  }

  // convert attributes to native
  offset = 2;
  for ( i = 0; i < pCmd->numAttrs; ++i )
  {
    pCmd->pAttrID[i] = BUILD_UINT16( buf[offset], buf[offset+1] );;
    offset += 2;
  }

  return ( ZCL_STATUS_SUCCESS );
}
예제 #3
0
/*********************************************************************
 * @fn      zclApplianceStatistics_LogQueueRsp_NativeToOta
 *
 * @brief   Converts from native to OTA format.
 *
 * @param   disableDefaultRsp - whether to disable the Default Response command
 * @param   pZclPayloadLen - returns zcl payload len
 *
 * @return  pointer to zcl payload
*/
uint8 *zclApplianceStatistics_LogQueueRsp_NativeToOta( zclCmdApplianceStatisticsLogQueueRspPayload_t *pPayload , uint16 * pZclPayloadLen )
{
  uint8 *pZclPayload;      // OTA ZCL payload
  uint16 zclPayloadLen;    // OTA ZCL payload length
  uint16 i;
  uint16 offset;

  // allocate some memory for the ZCL payload
  zclPayloadLen = 1 + (pPayload->logQueueSize * sizeof(uint32));    // # of LogQueue IDs
  pZclPayload = zcl_mem_alloc( zclPayloadLen );
  if( !pZclPayload )
  {
    return NULL;  // no memory
  }

  // fill in payload
  pZclPayload[0] = pPayload->logQueueSize;
  offset = 1;
  for( i = 0; i < pPayload->logQueueSize; ++i )
  {
    pZclPayload[offset]   = BREAK_UINT32(pPayload->pLogID[i], 0);
    pZclPayload[offset+1] = BREAK_UINT32(pPayload->pLogID[i], 1);
    pZclPayload[offset+2] = BREAK_UINT32(pPayload->pLogID[i], 2);
    pZclPayload[offset+3] = BREAK_UINT32(pPayload->pLogID[i], 3);
    offset += sizeof( uint32 );
  }

  // return OTA payload and length
  *pZclPayloadLen = zclPayloadLen;
  return pZclPayload;
}
예제 #4
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 );
}
예제 #5
0
/*********************************************************************
 * @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 );
}
예제 #6
0
/*********************************************************************
 * @fn      zclPartition_ConvertOtaToNative_MultipleAck
 *
 * @brief   Helper function used to process an incoming MultipleACK
 *          command. Remember to free allocated memory.
 *
 * @param   pCmd   - (output) the converted command
 * @param   buf    - pointer to incoming frame (just after ZCL header)
 * @param   buflen - length of buffer (ZCL payload)
 *
 * @return  ZStatus_t - ZCL_STATUS_MALFORMED_COMMAND, ZMemError or ZCL_STATUS_SUCCESS
 */
ZStatus_t zclPartition_ConvertOtaToNative_MultipleAck( zclCmdMultipleAck_t *pCmd, uint8 *buf, uint8 buflen )
{
  uint8 nackSize;
  uint8 offset;
  uint8 i;

  // buffer not large enough!
  if ( buflen < 2 )
  {
    return ( ZCL_STATUS_MALFORMED_COMMAND );
  }

  pCmd->options = buf[0];
  if ( pCmd->options & ZCL_PARTITION_OPTIONS_NACK_16BIT )
  {
    pCmd->firstFrameID = BUILD_UINT16( buf[1], buf[2] );
    nackSize = 2;
    offset = 3;
  }
  else
  {
    pCmd->firstFrameID = buf[1];
    nackSize = 1;
    offset = 2;
  }

  // determine # of NACKs
  pCmd->numNAcks = ( buflen - offset ) / nackSize;

  // allocate enough memory for NACK IDs
  pCmd->pNAckID = zcl_mem_alloc ( pCmd->numNAcks * sizeof(uint16) );
  if ( !pCmd->pNAckID )
  {
    return ( ZMemError ); // memory error
  }

  // copy in NACK IDs
  for( i = 0; i < pCmd->numNAcks; ++i)
  {
    // copy NACk in native form
    if ( nackSize == 2 )
    {
      pCmd->pNAckID[i] = BUILD_UINT16( buf[offset], buf[offset+1] );
      offset += 2;
    }
    else
    {
      pCmd->pNAckID[i] = buf[offset++];
    }
  }

  return ( ZCL_STATUS_SUCCESS );
}
예제 #7
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 );
}
예제 #8
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 );
}
예제 #9
0
/*********************************************************************
 * @fn      zclPartition_RegisterCmdCallbacks
 *
 * @brief   Register applications command callbacks
 *
 * @param   endpoint - application's endpoint
 * @param   callbacks - pointer to the callback record.
 *
 * @return  ZMemError if not able to allocate
 */
ZStatus_t zclPartition_RegisterCmdCallbacks( uint8 endpoint, zclPartition_AppCallbacks_t *callbacks )
{
  zclPartitionCBRec_t *pNewItem;
  zclPartitionCBRec_t *pLoop;

  // Register as a ZCL Plugin
  if ( zclPartitionPluginRegisted == FALSE )
  {
    zcl_registerPlugin( ZCL_CLUSTER_ID_GEN_PARTITION,
                        ZCL_CLUSTER_ID_GEN_PARTITION,
                        zclPartition_HdlIncoming );
    zclPartitionPluginRegisted = TRUE;
  }

  // Fill in the new profile list
  pNewItem = zcl_mem_alloc( sizeof( zclPartitionCBRec_t ) );
  if ( pNewItem == NULL )
  {
    return ( ZMemError ); // memory error
  }

  pNewItem->next = (zclPartitionCBRec_t *)NULL;
  pNewItem->endpoint = endpoint;
  pNewItem->CBs = callbacks;

  // Find spot in list
  if ( zclPartitionCBs == NULL )
  {
    zclPartitionCBs = pNewItem;
  }
  else
  {
    // Look for end of list
    pLoop = zclPartitionCBs;
    while ( pLoop->next != NULL )
      pLoop = pLoop->next;

    // Put new item at end of list
    pLoop->next = pNewItem;
  }

  return ( ZSuccess );
}
예제 #10
0
/*********************************************************************
 * @fn      zclElectricalMeasurement_RegisterCmdCallbacks
 *
 * @brief   Register applications command callbacks
 *
 * @param   endpoint - application's endpoint
 * @param   callbacks - pointer to the callback record.
 *
 * @return  ZMemError if not able to allocate
 */
ZStatus_t zclElectricalMeasurement_RegisterCmdCallbacks( uint8 endpoint, zclElectricalMeasurement_AppCallbacks_t *callbacks )
{
  zclElectricalMeasurementCBRec_t *pNewItem;
  zclElectricalMeasurementCBRec_t *pLoop;

  // Register as a ZCL Plugin
  if ( zclElectricalMeasurementPluginRegisted == FALSE )
  {
    zcl_registerPlugin( ZCL_CLUSTER_ID_HA_ELECTRICAL_MEASUREMENT,
                        ZCL_CLUSTER_ID_HA_ELECTRICAL_MEASUREMENT,
                        zclElectricalMeasurement_HdlIncoming );
    zclElectricalMeasurementPluginRegisted = TRUE;
  }

  // Fill in the new profile list
  pNewItem = zcl_mem_alloc( sizeof( zclElectricalMeasurementCBRec_t ) );
  if ( pNewItem == NULL )
  {
    return ( ZMemError );
  }

  pNewItem->next = (zclElectricalMeasurementCBRec_t *)NULL;
  pNewItem->endpoint = endpoint;
  pNewItem->CBs = callbacks;

  // Find spot in list
  if ( zclElectricalMeasurementCBs == NULL )
  {
    zclElectricalMeasurementCBs = pNewItem;
  }
  else
  {
    // Look for end of list
    pLoop = zclElectricalMeasurementCBs;
    while ( pLoop->next != NULL )
      pLoop = pLoop->next;

    // Put new item at end of list
    pLoop->next = pNewItem;
  }

  return ( ZSuccess );
}
예제 #11
0
/*********************************************************************
 * @fn      zclApplianceStatistics_RegisterCmdCallbacks
 *
 * @brief   Register applications command callbacks
 *
 * @param   endpoint - application's endpoint
 * @param   callbacks - pointer to the callback record.
 *
 * @return  ZMemError if not able to allocate
 */
ZStatus_t zclApplianceStatistics_RegisterCmdCallbacks( uint8 endpoint, zclApplianceStatistics_AppCallbacks_t *callbacks )
{
  zclApplianceStatisticsCBRec_t *pNewItem;
  zclApplianceStatisticsCBRec_t *pLoop;

  // Register as a ZCL Plugin
  if ( zclApplianceStatisticsPluginRegisted == FALSE )
  {
    zcl_registerPlugin( ZCL_CLUSTER_ID_HA_APPLIANCE_STATISTICS,
                        ZCL_CLUSTER_ID_HA_APPLIANCE_STATISTICS,
                        zclApplianceStatistics_HdlIncoming );
    zclApplianceStatisticsPluginRegisted = TRUE;
  }

  // Fill in the new profile list
  pNewItem = zcl_mem_alloc( sizeof( zclApplianceStatisticsCBRec_t ) );
  if ( pNewItem == NULL )
  {
    return ( ZMemError );
  }

  pNewItem->next = (zclApplianceStatisticsCBRec_t *)NULL;
  pNewItem->endpoint = endpoint;
  pNewItem->CBs = callbacks;

  // Find spot in list
  if ( zclApplianceStatisticsCBs == NULL )
  {
    zclApplianceStatisticsCBs = pNewItem;
  }
  else
  {
    // Look for end of list
    pLoop = zclApplianceStatisticsCBs;
    while ( pLoop->next != NULL )
      pLoop = pLoop->next;

    // Put new item at end of list
    pLoop->next = pNewItem;
  }

  return ( ZSuccess );
}
예제 #12
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 );
}
예제 #13
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 );
}
예제 #14
0
파일: zcl_hvac.c 프로젝트: Daan1992/WSN-Lab
/*********************************************************************
 * @fn      zclHVAC_RegisterCmdCallbacks
 *
 * @brief   Register an applications command callbacks
 *
 * @param   endpoint - application's endpoint
 * @param   callbacks - pointer to the callback record.
 *
 * @return  ZMemError if not able to allocate
 */
ZStatus_t zclHVAC_RegisterCmdCallbacks( uint8 endpoint, zclHVAC_AppCallbacks_t *callbacks )
{
  zclHVACCBRec_t *pNewItem;
  zclHVACCBRec_t *pLoop;

  // Register as a ZCL Plugin
  if ( !zclHVACPluginRegisted )
  {
    zcl_registerPlugin( ZCL_CLUSTER_ID_HVAC_PUMP_CONFIG_CONTROL,
                        ZCL_CLUSTER_ID_HVAC_USER_INTERFACE_CONFIG,
                        zclHVAC_HdlIncoming );
    zclHVACPluginRegisted = TRUE;
  }

  // Fill in the new profile list
  pNewItem = zcl_mem_alloc( sizeof( zclHVACCBRec_t ) );
  if ( pNewItem == NULL )
    return (ZMemError);

  pNewItem->next = (zclHVACCBRec_t *)NULL;
  pNewItem->endpoint = endpoint;
  pNewItem->CBs = callbacks;

  // Find spot in list
  if ( zclHVACCBs == NULL )
  {
    zclHVACCBs = pNewItem;
  }
  else
  {
    // Look for end of list
    pLoop = zclHVACCBs;
    while ( pLoop->next != NULL )
      pLoop = pLoop->next;

    // Put new item at end of list
    pLoop->next = pNewItem;
  }
  return ( ZSuccess );
}
예제 #15
0
/*********************************************************************
 * @fn      zclMS_RegisterCmdCallbacks
 *
 * @brief   Register an applications command callbacks
 *
 * @param   endpoint - application's endpoint
 * @param   callbacks - pointer to the callback record.
 *
 * @return  ZMemError if not able to allocate
 */
ZStatus_t zclMS_RegisterCmdCallbacks( uint8 endpoint, zclMS_AppCallbacks_t *callbacks )
{
  zclMSCBRec_t *pNewItem;
  zclMSCBRec_t *pLoop;

  // Register as a ZCL Plugin
  if ( !zclMSPluginRegisted )
  {
    zcl_registerPlugin( ZCL_CLUSTER_ID_MS_ILLUMINANCE_MEASUREMENT,
                        ZCL_CLUSTER_ID_MS_OCCUPANCY_SENSING,
                        zclMS_HdlIncoming );
    zclMSPluginRegisted = TRUE;
  }

  // Fill in the new profile list
  pNewItem = zcl_mem_alloc( sizeof( zclMSCBRec_t ) );
  if ( pNewItem == NULL )
    return (ZMemError);

  pNewItem->next = (zclMSCBRec_t *)NULL;
  pNewItem->endpoint = endpoint;
  pNewItem->CBs = callbacks;

  // Find spot in list
  if ( zclMSCBs == NULL )
  {
    zclMSCBs = pNewItem;
  }
  else
  {
    // Look for end of list
    pLoop = zclMSCBs;
    while ( pLoop->next != NULL )
      pLoop = pLoop->next;

    // Put new item at end of list
    pLoop->next = pNewItem;
  }
  return ( ZSuccess );
}
예제 #16
0
/*********************************************************************
 * @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 );
}
예제 #17
0
/*********************************************************************
 * @fn      zclApplianceStatistics_LogQueueRsp_OtaToNative
 *
 * @brief   Converts from native to OTA format. Make sure to free pCmd->pLogID if ZSuccess.
 *
 * @param   pCmd - native format (destination)
 * @param   pZclPayloadLen - OTA ZCL payload (source)
 *
 * @return  ZSuccess if worked
*/
ZStatus_t zclApplianceStatistics_LogQueueRsp_OtaToNative( zclCmdApplianceStatisticsLogQueueRspPayload_t *pCmd, uint8 *pData )
{
  uint8  offset;
  uint8  i;

  // convert from OTA (stream) format to native format
  pCmd->logQueueSize = pData[0];
  pCmd->pLogID = zcl_mem_alloc( pCmd->logQueueSize * sizeof(uint32) );
  if( !pCmd->pLogID )
  {
    return ( ZMemError );
  }

  offset = 1;
  for( i = 0; i < pCmd->logQueueSize; ++i )
  {
    pCmd->pLogID[i] = BUILD_UINT32( pData[offset], pData[offset+1], pData[offset+2], pData[offset+3] );
    offset += sizeof(uint32);
  }

  return ( ZSuccess );
}
예제 #18
0
/*********************************************************************
 * @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 );
}
예제 #19
0
/*********************************************************************
 * @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 );
}
예제 #20
0
/*********************************************************************
 * @fn      zclPartition_ConvertOtaToNative_WriteHandshakeParam
 *
 * @brief   Helper function used to process an incoming WriteHandshakeParam
 *          command. Remember to free allocated memory.
 *
 * @param   pCmd   - (output) the converted command
 * @param   buf    - pointer to incoming frame (just after ZCL header)
 * @param   buflen - length of buffer (ZCL payload)
 *
 * @return  ZStatus_t - ZCL_STATUS_MALFORMED_COMMAND, ZMemError or ZCL_STATUS_SUCCESS
 */
ZStatus_t zclPartition_ConvertOtaToNative_WriteHandshakeParam( zclCmdWriteHandshakeParam_t *pCmd, uint8 *buf, uint8 buflen )
{
  uint8 offset;
  uint8 dataType;
  uint8 i;
  uint8 attrSize;

  // must have at least 1 attribute (clusterID + attrID)
  if ( buflen < 4 )
  {
    return ( ZCL_STATUS_MALFORMED_COMMAND );
  }

  pCmd->clusterID = BUILD_UINT16( buf[0], buf[1] );

  // allocate memory for attribute list
  // [clusterID][WriteRecord1][WriteRecord2]...
  pCmd->numRecords = 0;
  offset = 2;
  while ( offset < buflen )
  {
    dataType = buf[offset + 2];   // [AttrID][dataType][Attr]
    if ( dataType == ZCL_DATATYPE_UINT16 )
    {
      attrSize = 2;
    }
    else if ( dataType == ZCL_DATATYPE_UINT8 )
    {
      attrSize = 1;
    }
    else
    {
     return ( ZCL_STATUS_MALFORMED_COMMAND );  // can't convert invalid attributes
    }

    offset += 3 + attrSize;

    // ignore partial records
    if ( offset > buflen )
    {
      break;
    }
    ++pCmd->numRecords;
  }

  // allocate the memory
  pCmd->pWriteRecord = zcl_mem_alloc( pCmd->numRecords * sizeof( zclPartitionWriteRec_t ) );
  if ( !pCmd->pWriteRecord )
  {
    return ( ZMemError ); // memory error
  }

  // convert records native
  offset = 2;
  for ( i = 0; i < pCmd->numRecords; ++i )
  {
    pCmd->pWriteRecord[i].attrID = BUILD_UINT16( buf[offset], buf[offset+1] );
    pCmd->pWriteRecord[i].dataType = dataType = buf[offset+2];

    if ( dataType == ZCL_DATATYPE_UINT16 )
    {
      pCmd->pWriteRecord[i].attr = BUILD_UINT16( buf[offset+3], buf[offset+4] );
      attrSize = 2;
    }
    else if ( dataType == ZCL_DATATYPE_UINT8 )
    {
      pCmd->pWriteRecord[i].attr = buf[offset+3];
      attrSize = 1;
    }

    // move offset passed write record (2 bytes for attrID, 1 byte for AttrType + size of attr)
    offset += ( 3 + attrSize );
  }

  return ( ZCL_STATUS_SUCCESS );
}
예제 #21
0
/*********************************************************************
 * @fn      zclPartition_ConvertOtaToNative_ReadHandshakeParamRsp
 *
 * @brief   Helper function used to process an incoming ReadHandshakeParamRsp
 *          command. Remember to free allocated memory.
 *
 * @param   pCmd   - (output) the converted command
 * @param   buf    - pointer to incoming frame (just after ZCL header)
 * @param   buflen - length of buffer (ZCL payload)
 *
 * @return  ZStatus_t - ZCL_STATUS_MALFORMED_COMMAND, ZMemError or ZCL_STATUS_SUCCESS
 */
ZStatus_t zclPartition_ConvertOtaToNative_ReadHandshakeParamRsp( zclCmdReadHandshakeParamRsp_t *pCmd, uint8 *buf, uint8 buflen )
{
  uint8 status;
  uint8  dataType;
  uint8 offset;
  uint8 i;

  // must have at least 1 attribute (clusterID + attrID)
  if ( buflen < 4 )
  {
    return ( ZCL_STATUS_MALFORMED_COMMAND );
  }

  pCmd->clusterID = BUILD_UINT16( buf[0], buf[1] );

  // determine # of attributes
  offset = 2;
  pCmd->numRecords = 0;
  while ( offset < buflen )
  {
    // each record begins with [AttrID][Status]
    status = buf[offset+2];   // status listed in spec as 2 bytes, but it's really 1 byte
    offset += 3;              // skip [AttrID][Status]

    // followed by attrtype and data
    if ( status == ZCL_STATUS_SUCCESS )
    {
      // for partition cluster, all attributes are uint8 or uint16
      dataType = buf[offset];
      if ( dataType == ZCL_DATATYPE_UINT8 )
      {
        offset += 2;
      }
      else if ( dataType == ZCL_DATATYPE_UINT16 )
      {
        offset += 3;
      }
      else
      {
        break;    // invalidate data type, we don't know what to do with it.
      }
    }

    ++pCmd->numRecords;
  }

  // allocate memory for attribute list
  pCmd->pReadRecord =  zcl_mem_alloc( pCmd->numRecords * sizeof( zclPartitionReadRec_t ) );
  if ( !pCmd->pReadRecord )
  {
    return ( ZMemError ); // memory error
  }

  // convert attributes records to native
  offset = 2;
  for ( i = 0; i < pCmd->numRecords; ++i )
  {
    pCmd->pReadRecord[i].attrID = BUILD_UINT16( buf[offset], buf[offset+1] );
    pCmd->pReadRecord[i].status = buf[offset+2];
    offset += 3;

    if ( status == ZCL_STATUS_SUCCESS )
    {
      // for partition cluster, all attributes are uint8 or uint16
      pCmd->pReadRecord[i].dataType = dataType = buf[offset];
      if ( dataType == ZCL_DATATYPE_UINT8 )
      {
        pCmd->pReadRecord[i].attr = buf[offset+1];
        offset += 2;
      }
      else
      {
        pCmd->pReadRecord[i].attr = BUILD_UINT16( buf[offset+1], buf[offset+2] );
        offset += 3;
      }
    }
  }

  return ( ZCL_STATUS_SUCCESS );
}
예제 #22
0
파일: zcl_hvac.c 프로젝트: Daan1992/WSN-Lab
/*********************************************************************
 * @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;
}
예제 #23
0
파일: zcl_hvac.c 프로젝트: Daan1992/WSN-Lab
/*********************************************************************
 * @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 );
}