private void intervalSave(PointValueTime pvt) { synchronized (intervalLoggingLock) { if (vo.getIntervalLoggingType() == DataPointVO.IntervalLoggingTypes.MAXIMUM) { if (intervalValue == null) intervalValue = pvt; else if (pvt != null) { if (intervalValue.getDoubleValue() < pvt.getDoubleValue()) intervalValue = pvt; } } else if (vo.getIntervalLoggingType() == DataPointVO.IntervalLoggingTypes.MINIMUM) { if (intervalValue == null) intervalValue = pvt; else if (pvt != null) { if (intervalValue.getDoubleValue() > pvt.getDoubleValue()) intervalValue = pvt; } } else if (vo.getIntervalLoggingType() == DataPointVO.IntervalLoggingTypes.AVERAGE) { // Using the averaging values, ensure we keep the most recent values and pop off the old // ones if (vo.isOverrideIntervalLoggingSamples()) { while (averagingValues.size() >= vo.getIntervalLoggingSampleWindowSize()) { averagingValues.remove(0); // Size -1 for the next item we are going to add } } averagingValues.add(pvt); } } }
// // // Lifecycle // @Override public void initialize() { // Get the latest value for the point from the database. pointValue = valueCache.getLatestPointValue(); // Set the tolerance origin if this is a numeric if (pointValue != null && pointValue.getValue() instanceof NumericValue) toleranceOrigin = pointValue.getDoubleValue(); // Add point event listeners for (PointEventDetectorVO ped : vo.getEventDetectors()) { if (detectors == null) detectors = new ArrayList<PointEventDetectorRT>(); PointEventDetectorRT pedRT = ped.createRuntime(); detectors.add(pedRT); pedRT.initialize(); Common.runtimeManager.addDataPointListener(vo.getId(), pedRT); } initializeIntervalLogging(); }
private void savePointValue( PointValueTime newValue, SetPointSource source, boolean async, boolean saveToDatabase) { // Null values are not very nice, and since they don't have a specific meaning they are hereby // ignored. if (newValue == null) return; // Check the data type of the value against that of the locator, just for fun. int valueDataType = DataTypes.getDataType(newValue.getValue()); if (valueDataType != DataTypes.UNKNOWN && valueDataType != vo.getPointLocator().getDataTypeId()) // This should never happen, but if it does it can have serious downstream consequences. Also, // we need // to know how it happened, and the stack trace here provides the best information. throw new ShouldNeverHappenException( "Data type mismatch between new value and point locator: newValue=" + DataTypes.getDataType(newValue.getValue()) + ", locator=" + vo.getPointLocator().getDataTypeId()); // Check if this value qualifies for discardation. if (vo.isDiscardExtremeValues() && DataTypes.getDataType(newValue.getValue()) == DataTypes.NUMERIC) { double newd = newValue.getDoubleValue(); if (newd < vo.getDiscardLowLimit() || newd > vo.getDiscardHighLimit()) // Discard the value return; } if (newValue.getTime() > System.currentTimeMillis() + SystemSettingsDao.getFutureDateLimit()) { // Too far future dated. Toss it. But log a message first. LOG.warn( "Future dated value detected: pointId=" + vo.getId() + ", value=" + newValue.getStringValue() + ", type=" + vo.getPointLocator().getDataTypeId() + ", ts=" + newValue.getTime(), new Exception()); return; } boolean backdated = pointValue != null && newValue.getTime() < pointValue.getTime(); // Determine whether the new value qualifies for logging. boolean logValue; // ... or even saving in the cache. boolean saveValue = true; switch (vo.getLoggingType()) { case DataPointVO.LoggingTypes.ON_CHANGE: if (pointValue == null) logValue = true; else if (backdated) // Backdated. Ignore it logValue = false; else { if (newValue.getValue() instanceof NumericValue) { // Get the new double double newd = newValue.getDoubleValue(); // See if the new value is outside of the tolerance. double diff = toleranceOrigin - newd; if (diff < 0) diff = -diff; if (diff > vo.getTolerance()) { toleranceOrigin = newd; logValue = true; } else logValue = false; } else logValue = !ObjectUtils.equals(newValue.getValue(), pointValue.getValue()); } saveValue = logValue; break; case DataPointVO.LoggingTypes.ALL: logValue = true; break; case DataPointVO.LoggingTypes.ON_TS_CHANGE: if (pointValue == null) logValue = true; else if (backdated) // Backdated. Ignore it logValue = false; else logValue = newValue.getTime() != pointValue.getTime(); saveValue = logValue; break; case DataPointVO.LoggingTypes.INTERVAL: if (!backdated) intervalSave(newValue); default: logValue = false; } if (!saveToDatabase) logValue = false; if (saveValue) valueCache.savePointValue(newValue, source, logValue, async); // add annotation to newValue before firing events so event detectors can // fetch the annotation if (source != null) { newValue = new AnnotatedPointValueTime( newValue.getValue(), newValue.getTime(), source.getSetPointSourceMessage()); } // Ignore historical values. if (pointValue == null || newValue.getTime() >= pointValue.getTime()) { PointValueTime oldValue = pointValue; pointValue = newValue; fireEvents(oldValue, newValue, source != null, false); } else fireEvents(null, newValue, false, true); }