Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,10 @@
if (Double.isNaN(value))
{
flushPolyLine(gc, poly_x, poly_y, line_width);
if (last_y != -1) {
highlightDiscontinuity(gc, x_transform, item);
gc.setStroke(createStroke(line_width, line_style));
}
last_x = last_y = -1;
}
else
Expand Down Expand Up @@ -346,6 +350,10 @@
final double value = item.getValue();
if (Double.isNaN(value)) {
flushPolyLine(gc, value_poly_x, value_poly_y, line_width);
if (last_y != -1) {
highlightDiscontinuity(gc, x_transform, item);
gc.setStroke(createStroke(line_width, line_style));
}
}
else
{
Expand Down Expand Up @@ -599,6 +607,20 @@
gc.fillOval(x-size/2, y-size/2, size, size);
}

/**
* Plot an additional vertical dashed line to indicate a transition to a
* non-plottable value, to highlight events such as an archiver disconnect.
* @param gc GC
* @param x_transform Horizontal axis
* @param item PlotDataItem
*/
final private void highlightDiscontinuity(final Graphics2D gc, final ScreenTransform<XTYPE> x_transform,

Check warning on line 617 in app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/TracePainter.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Reorder the modifiers to comply with the Java Language Specification.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AaFZU3eeRFT41ttUUu3A&open=AaFZU3eeRFT41ttUUu3A&pullRequest=3974

Check warning on line 617 in app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/TracePainter.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AaFZU3eeRFT41ttUUu2_&open=AaFZU3eeRFT41ttUUu2_&pullRequest=3974
final PlotDataItem<XTYPE> item) {
final int x1 = clipX(x_transform.transform(item.getPosition()));
gc.setStroke(createStroke(1, LineStyle.DOT));
gc.drawLine(x1, y_min, x1, y_max);
}

/** Fill area. All lists will be cleared.
* @param gc GC
* @param pos Horizontal screen positions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,7 @@
import org.epics.archiverappliance.retrieval.client.DataRetrieval;
import org.epics.archiverappliance.retrieval.client.EpicsMessage;
import org.epics.archiverappliance.retrieval.client.GenMsgIterator;
import org.epics.vtype.Alarm;
import org.epics.vtype.AlarmStatus;
import org.epics.vtype.Display;
import org.epics.vtype.Time;
import org.epics.vtype.VNumber;
import org.epics.vtype.VStatistics;
import org.epics.vtype.VType;
import org.epics.vtype.*;
import org.phoebus.pv.TimeHelper;

import edu.stanford.slac.archiverappliance.PB.EPICSEvent.PayloadInfo;
Expand All @@ -33,6 +27,8 @@

private final int requestedPoints;
private final boolean useStatistics;
private boolean firstDisconnnect;
private EpicsMessage previousMessage;

/**
* Constructor that fetches data from appliance archive reader.
Expand All @@ -55,6 +51,8 @@
super(reader, name, start, end);
this.requestedPoints = points;
this.useStatistics = useStatistics;
this.firstDisconnnect = false;
this.previousMessage = null;
this.display = determineDisplay(reader, name, end);
fetchData();
}
Expand Down Expand Up @@ -130,7 +128,22 @@
if (closed) {
return null;
}
message = mainIterator.next();
if (!reuseMessage)
message = mainIterator.next();
else {
message = savedMessage;
reuseMessage = false;
}

// Check if a disconnect event was recorded and return a special
// value if so.
VType check = checkDisconnect(message);
if (check != null)
return check;

savedMessage = null;
firstDisconnnect = false;
previousMessage = message;
}
PayloadType type = mainStream.getPayLoadInfo().getType();
if (type == PayloadType.WAVEFORM_DOUBLE) {
Expand Down Expand Up @@ -159,4 +172,43 @@
return super.extractData(message);
}
}

/**
* Method to check the EpicsMessage for fieldValues containing the
* 'cnxlostepsecs' and 'cnxregainedepsecs' signifying a disconnect and reconnect
* of the PV (for raw data) or 'connectionChange' (for optimized data).
* Method extracts the time of the disconnect and returns an
* ArchiveVString with the value 'Disconnect'
*
* @param message Current EpicsMessage to check
* @return a VType that can be inserted to indicate a disconnect
*/
@Override
VType checkDisconnect(EpicsMessage message) {
// Call parent method to test for "cnxlostepsecs" field in case of raw data
VType check = super.checkDisconnect(message);
if (check != null)
return check;

// In the OptimizedWithLastSample PP we get a connectionChange and then the following bins
// will have 0 events (count) in them.
Boolean disconnectCondition = Boolean.parseBoolean(message.getFieldValues().get("connectionChange"))
&& message.getNumberAt(4).intValue() == 0;
// In the Optimized PP we get a connectionChange but the following bins (which
// technically have no events) will be a repeat of the last bin to have
// events. Cannot currently detect disconnect times in the Optimized
// request so disconnectCondition will always evaluate as false.

if (disconnectCondition && savedMessage == null) {

Check warning on line 202 in app/trends/archive-reader/src/main/java/org/phoebus/archive/reader/appliance/ApplianceOptimizedValueIterator.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a primitive boolean expression here.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AaFZU3jjRFT41ttUUu3B&open=AaFZU3jjRFT41ttUUu3B&pullRequest=3974
if (!firstDisconnnect) {
firstDisconnnect = true;
return VString.of("Disconnect in bin", Alarm.disconnected(),
Time.of(TimestampHelper.fromSQLTimestamp(message.getTimestamp())));
} else {
return VString.of("", Alarm.disconnected(),
Time.of(TimestampHelper.fromSQLTimestamp(message.getTimestamp())));
}
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,9 @@

import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.Iterator;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.Comparator;

import org.epics.archiverappliance.retrieval.client.DataRetrieval;
import org.epics.archiverappliance.retrieval.client.EpicsMessage;
Expand Down Expand Up @@ -72,6 +67,10 @@

private final Object lock = new Object();

protected EpicsMessage savedMessage;
protected boolean reuseMessage;


/**
* Constructs a new ApplianceValueIterator.
*
Expand All @@ -85,6 +84,8 @@
this.name = name;
this.start = start;
this.end = end;
this.reuseMessage = false;
this.savedMessage = null;
}

/**
Expand Down Expand Up @@ -130,6 +131,10 @@
public boolean hasNext() {
if (closed || mainIterator == null)
return false;
else if (reuseMessage)
// Disconnect is at the end of the iterator so
// still need to iterate one last time
return true;
return mainIterator.hasNext();
}

Expand All @@ -144,7 +149,17 @@
synchronized (this) {
if (closed)
return null;
message = mainIterator.next();
if (!reuseMessage)
message = mainIterator.next();
else {
message = savedMessage;
reuseMessage = false;
}

VType check = checkDisconnect(message);
if (check != null)
return check;
savedMessage = null;
}
return extractData(message);
}
Expand Down Expand Up @@ -232,6 +247,29 @@
throw new UnsupportedOperationException("PV type " + type + " is not supported.");
}

/**
* Method to check the EpicsMessage for fieldValues containing the
* 'cnxlostepsecs' and 'cnxregainedepsecs' signifying a disconnect and reconnect
* of the PV. Method extracts the time of the disconnect and returns an
* ArchiveVString with the value 'Disconnect'
*
* @param message Current EpicsMessage to check
* @return a VType that can be inserted to indicate a disconnect
*/
VType checkDisconnect(EpicsMessage message) {
Set<String> messageKeys = message.getFieldValues().keySet();
Boolean disconnectCondition = messageKeys.contains("cnxlostepsecs")
&& messageKeys.contains("cnxregainedepsecs")
&& !messageKeys.contains("startup");
if (disconnectCondition && savedMessage == null) {

Check warning on line 264 in app/trends/archive-reader/src/main/java/org/phoebus/archive/reader/appliance/ApplianceValueIterator.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a primitive boolean expression here.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AaFZU3lWRFT41ttUUu3C&open=AaFZU3lWRFT41ttUUu3C&pullRequest=3974
long lostT = Long.parseLong(message.getFieldValues().get("cnxlostepsecs"));
reuseMessage = true;
savedMessage = message;
return VString.of("Disconnect", Alarm.disconnected(), Time.of(Instant.ofEpochSecond(lostT)));
}
return null;
}

/**
* Extracts the descriptor for the value field so it can be reused on each iteration.
*
Expand Down Expand Up @@ -307,7 +345,7 @@
}

/**
* Extract the labels from the given payloadinfo when processing Enum Values.
* Extract the labels from the given payloadinfo when processing Enum Values.
* EnumLabels list empty if payloadinfo from request without "fetchLatestMetadata" set to true
*
* @param info the info to extract the labels
Expand Down
Loading