Package tcg.scada.da

Source Code of tcg.scada.da.MeterDataPoint

package tcg.scada.da;

import java.util.Calendar;

import tcg.common.LoggerManager;
import tcg.scada.cos.CosDpQualityEnum;
import tcg.scada.cos.CosDpValueTypeEnum;

/**
* Implementation of metering datapoint.
*
* <p>
* Expected behaviour for metering datapoint:
* <ul>
* <li>Source value: accumulated meter value</li>
* <li>Source quality: quality of source datapoint</li>
* <li>Source timestamp: timestamp of source datapoint</li>
* <li>Output value: accumulated meter value</li>
* <li>Output quality: internal calculation</li>
* <li>Output timestamp: timestamp of source datapoint or last manual adjustment
* </li>
* </ul>
* </p>
*
* <p>
* Setting output value/quality/timestamp is not supported for metering
* datapoint.
* </p>
*
* <p>
* Setting source value/quality/timestamp is also not supported for metering
* datapoint. To update the value, run calculateMeterValue(). This will update
* the source value to the accumulated result, the source quality to the source
* datapoint quality and the source timestamp to source datapoint's timestamp.
* </p>
*
* <p>
* <b>On the other hand, inhibit and override IS supported for metering
* datapoint.</b> Alarm is also supported.
* </p>
*
* <p>
* Deadband and engineering conversion is not supported for virtual datapoint.
* </p>
*
* <p>
* Deadband and engineering conversion is not supported for metering datapoint.
* </p>
*
* @author Yoga
*
*/
public class MeterDataPoint extends DataPoint
{
  // metering point
  protected int readingRollOver = Integer.MAX_VALUE; // 2147483647 (2^31 - 1)
  protected int datapointRollOver = Integer.MAX_VALUE;

  protected int lastReadingValue = 0;

  // source point where the reading value is taken from
  protected IDataPoint sourcePoint = null;

  /**
   * Default ctor.
   *
   * @param inDataType
   *            - the internal data type
   */
  public MeterDataPoint(CosDpValueTypeEnum inDataType)
  {
    // metering point is only supported for number/unsigned data type
    if (inDataType.value() != CosDpValueTypeEnum._TypeNumber
        && inDataType.value() != CosDpValueTypeEnum._TypeUnsigned)
    {
      // force it to be number type
      inDataType = CosDpValueTypeEnum.TypeNumber;
    }
    super._setDataType(inDataType);
    // override the logger
    logger = LoggerManager.getLogger(this.getClass().getName());
    // set the default quality to bad.
    // this way, as soon as the source quality is good, the quality is updated.
    // this in turn will update the datapoint timestamp
    sourceQuality = CosDpQualityEnum.QualityBad;
    outputQuality = CosDpQualityEnum.QualityBad;
  }

  @Override
  public EDataPointType getType()
  {
    return EDataPointType.TYPE_METER;
  }

  /**
   * Helper function to initialize the last meter reading. This will set the
   * source value without triggering notification to datastore.
   *
   * @param inLastReading
   */
  protected synchronized void _setLastMeterReading(int inLastReading)
  {
    lastReadingValue = inLastReading;
  }

  /**
   * Get last meter reading
   *
   * @param the
   *            last meter reading
   */
  protected synchronized int _getLastMeterReading()
  {
    return lastReadingValue;
  }

  @Override
  public synchronized int adjustMeterValue(int inAdjustment)
  {
    // validation
    if (inAdjustment == 0)
    {
      return 0;
    }

    // get current value
    long curMeterValue = 0;
    if (sourceValue.discriminator() == CosDpValueTypeEnum.TypeNumber)
    {
      curMeterValue = sourceValue.longValue();
    }
    else
    {
      curMeterValue = sourceValue.unsignedValue();
    }

    // add the adjustment
    curMeterValue += inAdjustment;

    // check for datapoint rollover
    if (curMeterValue >= datapointRollOver)
    {
      curMeterValue -= datapointRollOver;
    }
    else if (curMeterValue < 0)
    {
      inAdjustment += curMeterValue;
      curMeterValue = 0;
    }

    // DO NOT ADJUST THE LAST_METER_READING!!!

    // set the datapoint value
    if (sourceValue.discriminator() == CosDpValueTypeEnum.TypeNumber)
    {
      sourceValue.longValue((int) curMeterValue);
    }
    else
    {
      sourceValue.unsignedValue((int) curMeterValue);
    }

    // update the source timestamp
    sourceTimestamp = Calendar.getInstance().getTimeInMillis();

    // update the update timestamp
    updateTimestamp_ = sourceTimestamp;

    // synchronize the source and output value/quality/timestamp
    if (_synchronize() > 0)
    {
      // re-evaluate all related calculated points, if any
      for (int i = 0; i < calculatedPoints.size(); i++)
      {
        calculatedPoints.get(i).evaluate();
      }
      // re-calculate all related meter points, if any
      for (int i = 0; i < meterPoints.size(); i++)
      {
        meterPoints.get(i).calculateMeterValue();
      }
      // re-evaluate all child points' quality, if any
      for (int i = 0; i < childPoints.size(); i++)
      {
        childPoints.get(i).updateQuality();
      }
    }

    // TODO: notify datastore
    if (datastore != null)
    {
      // dpServer.onDataPointChange(this);
    }

    // return value
    return inAdjustment;
  }

  @Override
  public int setReadingRollOver(int inRollOver)
  {
    // validation: inRollOver
    if (inRollOver <= 0)
    {
      return 0;
    }
    // set local variable
    readingRollOver = inRollOver;
    return readingRollOver;
  }

  @Override
  public int getReadingRollOver()
  {
    return readingRollOver;
  }

  @Override
  public int setDataPointRollOver(int inRollOver)
  {
    // validation: inRollOver
    if (inRollOver <= 0)
    {
      return 0;
    }
    // set local variable
    datapointRollOver = inRollOver;
    return datapointRollOver;
  }

  @Override
  public int getDataPointRollOver()
  {
    return datapointRollOver;
  }

  @Override
  public boolean setMeterSourcePoint(IDataPoint inDataPoint)
  {
    // validation: inDataPoint
    if (inDataPoint == null)
    {
      return false;
    }

    // only number/unsigned as allowed as source point
    CosDpValueTypeEnum dataType = inDataPoint.getInternalDataType();
    if (dataType != CosDpValueTypeEnum.TypeNumber
        && dataType != CosDpValueTypeEnum.TypeUnsigned)
    {
      return false;
    }

    // set as source point. also add this datapoint for notification in
    // source datapoint
    sourcePoint = inDataPoint;
    sourcePoint.addMeterPoint(this);

    // calculate the meter value right away
    calculateMeterValue();

    return true;
  }

  @Override
  public int calculateMeterValue()
  {
    // validation: source point is never set
    if (sourcePoint == null)
    {
      return -1;
    }

    // get current source value
    int curValue = 0;
    if (sourcePoint.getInternalDataType() == CosDpValueTypeEnum.TypeNumber)
    {
      curValue = sourcePoint.getValue().longValue();
    }
    else
    {
      curValue = sourcePoint.getValue().unsignedValue();
    }

    // calculate the accumulated value
    int status1 = 0;
    if (curValue != lastReadingValue)
    {
      // if curValue is the same as last reading value, ignore calculating
      // the value
      long meterReading = 0;
      // check for reading rollover
      if (curValue < lastReadingValue)
      {
        meterReading = curValue + readingRollOver - lastReadingValue;
        logger
            .warn("Equipment reading has rolled over. Current reading: "
                + curValue
                + ". Last reading: "
                + lastReadingValue
                + ". Equipment roll-over value: "
                + datapointRollOver);
      }
      else
      {
        meterReading = curValue - lastReadingValue;
      }
      // get current meter value
      long curMeterValue = 0;
      if (sourceValue.discriminator() == CosDpValueTypeEnum.TypeNumber)
      {
        curMeterValue = sourceValue.longValue();
      }
      else
      {
        curMeterValue = sourceValue.unsignedValue();
      }
      // TODO: check for datapoint rollover
      // add the new reading value
      curMeterValue += meterReading;
      // rollover if necessary
      if (curMeterValue >= datapointRollOver)
      {
        // datapoint rollover
        curMeterValue -= datapointRollOver;
        logger.warn("Metering point has rolled over. Current value: "
            + curMeterValue + ". Datapoint roll-over value: "
            + datapointRollOver);
      }
      // set the datapoint value
      if (sourceValue.discriminator() == CosDpValueTypeEnum.TypeNumber)
      {
        sourceValue.longValue((int) curMeterValue);
      }
      else
      {
        sourceValue.unsignedValue((int) curMeterValue);
      }
      // update the last reading value
      lastReadingValue = curValue;
      // TODO: notify the datastore
      status1 = +1;
    }

    // set the quality
    int status2 = 0;
    if (sourceQuality != sourcePoint.getQuality())
    {
      sourceQuality = sourcePoint.getQuality();
      status2 = +1;
      // TODO: notify the datastore
    }

    // overall status
    int status = 0;
    if (status1 > 0 || status2 > 0)
    {
      status = +1;
    }
    else
    {
      status = 0;
    }

    // post-processing
    if (status > 0)
    {
      // update the source timestamp
      sourceTimestamp = Calendar.getInstance().getTimeInMillis();

      // update the update timestamp
      updateTimestamp_ = sourceTimestamp;

      // synchronize the source and output value/quality/timestamp
      if (_synchronize() > 0)
      {
        // re-evaluate all related calculated points, if any
        for (int i = 0; i < calculatedPoints.size(); i++)
        {
          calculatedPoints.get(i).evaluate();
        }
        // re-calculate all related meter points, if any
        for (int i = 0; i < meterPoints.size(); i++)
        {
          meterPoints.get(i).calculateMeterValue();
        }
        // re-evaluate all child points' quality, if any
        for (int i = 0; i < childPoints.size(); i++)
        {
          childPoints.get(i).updateQuality();
        }
      }

      // TODO: notify datastore
      if (datastore != null)
      {
        // dpServer.onDataPointChange(this);
      }
    }

    return status;
  }
}
TOP

Related Classes of tcg.scada.da.MeterDataPoint

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.