Example #1
0
  /**
   * Called for each value received from PV.
   *
   * <p>Base class remembers the <code>most_recent_value</code>, and asserts that one 'first' sample
   * is archived. Derived class <b>must</b> call <code>super()</code>.
   *
   * @param value Value received from PV
   * @return true if the value was already written because it's the first value after startup or
   *     error, so there's no need to write that sample again.
   */
  protected boolean handleNewValue(final VType value) {
    synchronized (this) {
      ++received_value_count;
      most_recent_value = value;
    }
    // NaN test
    if (value instanceof VNumber) {
      if (Double.isNaN(VTypeHelper.toDouble(value)))
        trouble_sample_log.log("'" + getName() + "': NaN " + VTypeHelper.toString(value));
    }
    if (!enabled) return false;

    // Did we recover from write errors?
    if (need_write_error_sample && SampleBuffer.isInErrorState() == false) {
      need_write_error_sample = false;
      Activator.getLogger().log(Level.FINE, "Wrote error sample for {0}", getName());
      addInfoToBuffer(ValueButcher.createWriteError());
      need_first_sample = true;
    }
    // Is this the first sample after startup or an error?
    if (!need_first_sample) return false;
    need_first_sample = false;
    // Try to add as-is, but time stamp will be corrected to fit in
    final VType added = addInfoToBuffer(value);
    Activator.getLogger()
        .log(Level.FINE, "Wrote first sample for {0}: {1}", new Object[] {getName(), added});
    return true;
  }
Example #2
0
  /**
   * Add given sample to buffer, performing a back-in-time check, updating the sample buffer error
   * state.
   *
   * @param value Value to archive
   * @return <code>false</code> if value failed back-in-time or future check, <code>true</code> if
   *     value was added.
   */
  protected final boolean addValueToBuffer(final VType value) {
    // Suppress samples that are too far in the future
    final Timestamp time = VTypeHelper.getTimestamp(value);

    if (isFuturistic(time)) {
      trouble_sample_log.log("'" + getName() + "': Futuristic " + value);
      return false;
    }

    synchronized (this) {
      if (last_archived_value != null
          && VTypeHelper.getTimestamp(last_archived_value).compareTo(time)
              >= 0) { // Cannot use this sample because of back-in-time problem.
        // Usually this is NOT an error:
        // We logged an initial sample, disconnected, disabled, ...,
        // and now we got an update from the IOC which still
        // carries the old, original time stamp of the PV,
        // and that's back in time...
        trouble_sample_log.log(
            getName()
                + " skips back-in-time:\n"
                + "last: "
                + VTypeHelper.toString(last_archived_value)
                + "\n"
                + "new : "
                + VTypeHelper.toString(value));
        return false;
      }
      // else ...
      last_archived_value = value;
    }
    buffer.add(value);
    if (SampleBuffer.isInErrorState()) need_write_error_sample = true;
    return true;
  }
  @Test
  public void testCSVImport() throws Exception {
    final InputStream input = getClass().getResourceAsStream("Lakeshore_A_9_2011.xml");
    final SampleImporter importer = new CSVSampleImporter();

    final List<VType> values = importer.importValues(input);
    assertTrue(values.size() > 0);
    for (VType value : values) System.out.println(VTypeHelper.toString(value));
    final String text = VTypeHelper.toString(values.get(values.size() - 1));
    assertThat(text, containsString("2011-09-13"));
    assertThat(text, containsString("08:57:44.968"));
    assertThat(text, containsString("84.912"));
  }
Example #4
0
 /**
  * Add given info value to buffer, tweaking its time stamp if necessary
  *
  * @param value Value to archive
  * @return Value that was actually added, which may have adjusted time stamp
  */
 protected final VType addInfoToBuffer(VType value) {
   synchronized (this) {
     if (last_archived_value != null) {
       final Timestamp last = VTypeHelper.getTimestamp(last_archived_value);
       if (last.compareTo(VTypeHelper.getTimestamp(value)) >= 0) { // Patch the time stamp
         final Timestamp next = last.plus(TimeDuration.ofMillis(100));
         value = VTypeHelper.transformTimestamp(value, next);
       }
       // else: value is OK as is
     }
   }
   addValueToBuffer(value);
   return value;
 }
Example #5
0
 /**
  * Check a received value for basic problems before passing it on to the sample mechanism
  *
  * @param value Value as received from network layer
  * @return Value to be used for archive
  */
 private VType checkReceivedValue(VType value) {
   if (value instanceof Time) {
     try {
       final Time time = (Time) value;
       // Invoke time.getTimestamp() to detect RuntimeError in VType 2013/11/01
       if (time.isTimeValid() && time.getTimestamp() != null) return value;
       else {
         trouble_sample_log.log("'" + getName() + "': Invalid time stamp ");
         value = VTypeHelper.transformTimestamp(value, Timestamp.now());
       }
     } catch (RuntimeException ex) {
       Logger.getLogger(getClass().getName())
           .log(Level.WARNING, "'" + getName() + "': Exception getting time stamp", ex);
       value = VTypeHelper.transformTimestamp(value, Timestamp.now());
     }
   } else trouble_sample_log.log("'" + getName() + "': Received no time information for " + value);
   return value;
 }
Example #6
0
 /** Add one(!) 'disconnected' sample */
 private void logDisconnected() {
   synchronized (samples) {
     final int size = samples.getSize();
     if (size > 0) {
       final String last = VTypeHelper.getMessage(samples.getSample(size - 1).getValue());
       // Does last sample already have 'disconnected' status?
       if (Messages.Model_Disconnected.equals(last)) return;
     }
     samples.addLiveSample(new PlotSample(Messages.LiveData, Messages.Model_Disconnected));
   }
 }
Example #7
0
 /** Enable or disable groups based on received value */
 private final void handleEnablement(final VType value) {
   if (enablement == Enablement.Passive)
     throw new Error("Not to be called when passive"); // $NON-NLS-1$
   // Get boolean value (true <==> >0.0)
   final double number = VTypeHelper.toDouble(value);
   final boolean yes = number > 0.0;
   // Do we enable or disable based on that value?
   final boolean enable = enablement == Enablement.Enabling ? yes : !yes;
   // Check which group needs to _change_
   for (ArchiveGroup group : groups) {
     if (group.isEnabled() != enable) group.enable(enable);
   }
 }
Example #8
0
 /** Update the enablement state in case of change */
 private final void updateEnabledState(final boolean new_enabled_state) {
   // Any change?
   if (new_enabled_state == enabled) return;
   enabled = new_enabled_state;
   // In case this arrived after shutdown, don't log it.
   if (!is_running) return;
   if (enabled) { // If we have the 'current' value of the PV...
     VType value;
     synchronized (this) {
       value = most_recent_value;
     }
     if (value != null) { // Add to the buffer with timestamp 'now' to show
       // the re-enablement
       value = VTypeHelper.transformTimestampToNow(value);
       addValueToBuffer(value);
     }
   } else addInfoToBuffer(ValueButcher.createDisabled());
 }
 /** {@inheritDoc} */
 @Override
 public VType next() throws Exception {
   if (index < 0) throw new Exception("End of samples"); // $NON-NLS-1$
   // Remember value, prepare the next value
   final VType result = value;
   samples.getLock().lock();
   try {
     ++index;
     if (index >= samples.size()) index = -1; // No more samples
     else {
       value = samples.get(index).getVType();
       if (VTypeHelper.getTimestamp(value).compareTo(end) > 0) index = -1; // Beyond end time
     }
   } finally {
     samples.getLock().unlock();
   }
   return result;
 }
Example #10
0
  /** {@inheritDoc} */
  @Override
  protected void performExport(final IProgressMonitor monitor, final PrintStream out)
      throws Exception {
    final DateFormat date_format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
    int count = 0;
    for (ModelItem item : model.getItems()) {
      // Item header
      if (count > 0) out.println();
      printItemInfo(out, item);
      // Get data
      monitor.subTask(NLS.bind("Fetching data for {0}", item.getName()));
      final ValueIterator values = createValueIterator(item);
      // Dump all values
      MatlabQualityHelper qualities = new MatlabQualityHelper();
      long line_count = 0;
      out.println("clear t;");
      out.println("clear v;");
      out.println("clear q;");
      while (values.hasNext() && !monitor.isCanceled()) {
        final VType value = values.next();
        ++line_count;
        // t(1)='2010/03/15 13:30:10.123';
        out.println(
            "t{"
                + line_count
                + "}='"
                + date_format.format(VTypeHelper.getTimestamp(value).toDate())
                + "';");
        // v(1)=4.125;
        final double num = VTypeHelper.toDouble(value);
        if (Double.isNaN(num) || Double.isInfinite(num)) out.println("v(" + line_count + ")=NaN;");
        else out.println("v(" + line_count + ")=" + num + ";");
        // q(1)=0;
        out.println(
            "q("
                + line_count
                + ")="
                + qualities.getQualityCode(
                    VTypeHelper.getSeverity(value), VTypeHelper.getMessage(value))
                + ";");
        if (line_count % PROGRESS_UPDATE_LINES == 0)
          monitor.subTask(NLS.bind("{0}: Wrote {1} samples", item.getName(), line_count));
      }

      out.println(comment + "Convert time stamps into 'date numbers'");
      out.println("tn=datenum(t, 'yyyy/mm/dd HH:MM:SS.FFF');");
      out.println(comment + "Prepare patched data because");
      out.println(comment + "timeseries() cannot handle duplicate time stamps");
      out.println("[xx, idx]=unique(tn, 'last');");
      out.println("pt=tn(idx);");
      out.println("pv=v(idx);");
      out.println("pq=q(idx);");
      out.println("clear xx idx");
      out.println(comment + "Convert into time series and plot");
      // Patch "_" in name because Matlab plot will interprete it as LaTeX sub-script
      final String channel_name = item.getDisplayName().replace("_", "\\_");
      out.println(
          "channel"
              + count
              + "=timeseries(pv', pt', pq', 'IsDatenum', true, 'Name', '"
              + channel_name
              + "');");

      out.print("channel" + count + ".QualityInfo.Code=[");
      for (int q = 0; q < qualities.getNumCodes(); ++q) out.print(" " + q);
      out.println(" ];");

      out.print("channel" + count + ".QualityInfo.Description={");
      for (int q = 0; q < qualities.getNumCodes(); ++q)
        out.print(" '" + qualities.getQuality(q) + "'");
      out.println(" };");

      out.println();
      ++count;
    }
    out.println(comment + "Example for plotting the data");
    for (int i = 0; i < count; ++i) {
      out.println("subplot(1, " + count + ", " + (i + 1) + ");");
      out.println("plot(channel" + i + ");");
    }
  }
Example #11
0
 /** @return Last value written to archive */
 public final synchronized String getLastArchivedValue() {
   return VTypeHelper.toString(last_archived_value);
 }
Example #12
0
 /** @return Most recent value of the channel's PV */
 public final synchronized String getCurrentValue() {
   return VTypeHelper.toString(most_recent_value);
 }
  /** {@inheritDoc} */
  @Override
  public VType next() throws Exception {

    final VType result = samples[index];

    ++index;

    if (index < samples.length) return result;

    // Prepare next batch of samples
    fetch(VTypeHelper.getTimestamp(result));

    if (samples == null) return result;

    // Inspect next batch of samples
    // In most cases, this fetch should return the 'result' again:
    //   some_timestamp value A
    //   last_timestamp value B <-- last_sample of previous batch
    //   new_timestamp  value C
    // Since we ask from at-or-before last_timestamp on,
    // we get the last_sample once more and need to skip it.
    //
    // But also consider the following situation, where the last batch ended
    // in a range of data that had the same time stamp, and even some same
    // values:
    //   some_timestamp value A
    //   last_timestamp value B
    //   last_timestamp value C
    //   last_timestamp value C
    //   last_timestamp value C <-- last_sample of previous batch
    //   last_timestamp value C
    //   last_timestamp value C
    //   last_timestamp value D
    //   last_timestamp value E
    //   new_timestamp  value F
    // Reasons for same timestamps: Stuck IOC clock,
    // or sequences like .. Repeat N, next value, Disconnected, Arch. Off.
    // Reason for the same value: General mess-up.
    //
    // When we request new data from 'last_sample.getTime()' on,
    // i.e. from last_timestamp on, we could get any of the values B to E,
    // since they're all stamped at-or-before last_timestamp.
    // Which one exactly depends on optimization inside the data server.

    // From the end of the new samples, go backward:
    for (index = samples.length - 1; index >= 0; --index) {

      // If we find the previous batch's last sample...
      if (samples[index].equals(result))
        // Skip all the samples up to and including it
        break;
    }

    // Nothing to skip? Return as is.
    if (index < 0) index = 0;

    // Nothing left? Clear samples.
    if (index >= samples.length - 1) samples = null;

    return result;
  }
Example #14
0
 /** @param value Value to log with 'now' as time stamp */
 private void logValueAsNow(final VType value) {
   if (value == null) logDisconnected();
   else
     // Transform value to have 'now' as time stamp
     samples.addLiveSample(VTypeHelper.transformTimestampToNow(value));
 }