Compare commits
62 Commits
2.x.experi
...
server
| Author | SHA1 | Date | |
|---|---|---|---|
| a40573d320 | |||
| 70089581c4 | |||
| 08cbd0bad0 | |||
| f4d5102ea3 | |||
| e483f90837 | |||
| 795b269bd0 | |||
| 3cb7458e64 | |||
| 51d7b36219 | |||
| 67e7f9a6c8 | |||
| 491812ddeb | |||
| 40cc7f6a31 | |||
| 9386f42d06 | |||
| 855535134e | |||
| e2921ff1f4 | |||
| 36cd4335ab | |||
| d92534ec37 | |||
| ca871ad478 | |||
| b65764ac57 | |||
| 63e681c3bb | |||
| 48cda75405 | |||
| 4b615d29a6 | |||
| d8f1e2d8f1 | |||
| 768ea9f254 | |||
| 2cba6e7991 | |||
| cb6ec74859 | |||
| 36f717c8bf | |||
| 716eeba98b | |||
| c1c8170f36 | |||
| c8031db1fd | |||
| a2d9216e84 | |||
| 57eca36d27 | |||
| 809caa3ed1 | |||
| 3532f95acb | |||
| 5d2c2b94d6 | |||
| 2520573d12 | |||
| 97ab9fa5b2 | |||
| debc54a28a | |||
| 55ed5ac764 | |||
| 84c86b8d9f | |||
| b38654056b | |||
| 5660fafe25 | |||
| bf3535a9b5 | |||
| b9c15b0fc8 | |||
| 83dd7654ed | |||
| e723f66df3 | |||
| 1574dcc7bb | |||
| 1de3b6c14e | |||
| 2a6018c4f5 | |||
| c3238e4d22 | |||
| 4045873135 | |||
| 3e38e4002d | |||
| 0958b76bb0 | |||
| eaffe7ff91 | |||
| 70cb7a8939 | |||
| 0b9ee77f76 | |||
| 81af4449dc | |||
| 858d8dbd45 | |||
| 879ec1d657 | |||
| 3025f597c0 | |||
| 73107a4799 | |||
| a5da9a2527 | |||
| 21d935e35e |
3
ch.psi.fda/.settings/org.eclipse.core.resources.prefs
Normal file
3
ch.psi.fda/.settings/org.eclipse.core.resources.prefs
Normal file
@@ -0,0 +1,3 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=UTF-8
|
||||
encoding//src/test/java=UTF-8
|
||||
@@ -3,9 +3,41 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ch.psi</groupId>
|
||||
<artifactId>fda</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>1.1.41</version>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.containers</groupId>
|
||||
<artifactId>jersey-container-grizzly2-http</artifactId>
|
||||
<version>2.3.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
<artifactId>jersey-media-sse</artifactId>
|
||||
<version>2.3.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
<artifactId>jersey-media-json-jackson</artifactId>
|
||||
<version>2.3.1</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jeromq</groupId>
|
||||
<artifactId>jeromq</artifactId>
|
||||
<version>0.2.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>15.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.psi</groupId>
|
||||
<artifactId>jcae</artifactId>
|
||||
@@ -15,7 +47,7 @@
|
||||
<dependency>
|
||||
<groupId>ch.psi</groupId>
|
||||
<artifactId>plot</artifactId>
|
||||
<version>1.1.30</version>
|
||||
<version>1.1.31</version>
|
||||
</dependency>
|
||||
<!-- Java SMB/CIFS library -->
|
||||
<dependency>
|
||||
@@ -32,7 +64,6 @@
|
||||
<dependency>
|
||||
<groupId>org.python</groupId>
|
||||
<artifactId>jython</artifactId>
|
||||
<!-- <artifactId>jython-standalone</artifactId> -->
|
||||
<version>2.5.3</version>
|
||||
</dependency>
|
||||
<!-- CLI Libraries -->
|
||||
@@ -49,9 +80,9 @@
|
||||
</dependency>
|
||||
<!-- Mail Libraries -->
|
||||
<dependency>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<groupId>com.sun.mail</groupId>
|
||||
<artifactId>javax.mail</artifactId>
|
||||
<version>1.5.0</version>
|
||||
</dependency>
|
||||
<!-- Library for reading/writing XDR Format (MDA) -->
|
||||
<dependency>
|
||||
@@ -59,51 +90,13 @@
|
||||
<artifactId>freehep-xdr</artifactId>
|
||||
<version>2.0.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JUnit test library -->
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<version>3.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>14.0.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<scope>test</scope>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<version>4.8.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- For Testing NG functionality purposes -->
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.containers</groupId>
|
||||
<artifactId>jersey-container-grizzly2-http</artifactId>
|
||||
<version>2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
<artifactId>jersey-media-sse</artifactId>
|
||||
<version>2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
<artifactId>jersey-media-json-jackson</artifactId>
|
||||
<version>2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-cli</groupId>
|
||||
<artifactId>commons-cli</artifactId>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -112,6 +105,7 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
@@ -225,6 +219,23 @@
|
||||
</lifecycleMappingMetadata>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<finalName>${project.name}-${project.version}</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
<archive>
|
||||
<!-- <manifest>
|
||||
<mainClass>ch.psi.fda.AcquisitionMain</mainClass>
|
||||
</manifest> -->
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.aq;
|
||||
package ch.psi.fda;
|
||||
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
@@ -27,6 +27,7 @@ import java.awt.event.WindowEvent;
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@@ -47,10 +48,14 @@ import org.apache.commons.cli.OptionBuilder;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
|
||||
import com.google.common.eventbus.AsyncEventBus;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import sun.misc.Signal;
|
||||
import sun.misc.SignalHandler;
|
||||
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import ch.psi.fda.aq.Acquisition;
|
||||
import ch.psi.fda.aq.AcquisitionConfiguration;
|
||||
import ch.psi.fda.aq.VisualizationMapper;
|
||||
import ch.psi.fda.gui.ProgressPanel;
|
||||
import ch.psi.fda.gui.ScrollableFlowPanel;
|
||||
import ch.psi.fda.install.ApplicationConfigurator;
|
||||
@@ -58,16 +63,14 @@ import ch.psi.fda.model.ModelManager;
|
||||
import ch.psi.fda.model.v1.Configuration;
|
||||
import ch.psi.fda.model.v1.Data;
|
||||
import ch.psi.fda.visualizer.Visualizer;
|
||||
import ch.psi.jcae.impl.DefaultChannelService;
|
||||
|
||||
/**
|
||||
* Main class for data acquisition
|
||||
* @author ebner
|
||||
*
|
||||
* Entry class for command line based data acquisition
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class AcquisitionMain {
|
||||
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(AcquisitionMain.class.getName());
|
||||
|
||||
private static boolean abortedViaSignal = false;
|
||||
@@ -128,10 +131,6 @@ public class AcquisitionMain {
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
// Check whether exactly one file is specified
|
||||
// if(line.getArgs().length>1){
|
||||
// throw new ParseException("Only up to one argument is supported");
|
||||
// }
|
||||
if(line.getArgs().length<1){
|
||||
throw new ParseException("One argument is required");
|
||||
}
|
||||
@@ -207,22 +206,13 @@ public class AcquisitionMain {
|
||||
ApplicationConfigurator ac = new ApplicationConfigurator();
|
||||
ac.initializeApplication();
|
||||
|
||||
// Read in base configuration
|
||||
// AcquisitionEngineConfiguration configuration = AcquisitionEngineConfiguration.getInstance();
|
||||
|
||||
if(!file.exists()){
|
||||
throw new RuntimeException("File "+file.getAbsolutePath()+" does not exist");
|
||||
}
|
||||
|
||||
Configuration c;
|
||||
try {
|
||||
if(file.getName().endsWith(".xsl")){
|
||||
c = ModelManager.unmarshall(file, variables);
|
||||
}
|
||||
else{
|
||||
c = ModelManager.unmarshall(file);
|
||||
}
|
||||
|
||||
c = ModelManager.unmarshall(file);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to deserialize configuration: "+e.getMessage(), e);
|
||||
}
|
||||
@@ -256,7 +246,7 @@ public class AcquisitionMain {
|
||||
}
|
||||
|
||||
// Create/get acquisition engine
|
||||
final Acquisition acquisition = new Acquisition();
|
||||
final Acquisition acquisition = new Acquisition(new DefaultChannelService(), new AcquisitionConfiguration());
|
||||
|
||||
boolean vis = false;
|
||||
// Only register data visualization task/processor if there are visualizations
|
||||
@@ -264,12 +254,20 @@ public class AcquisitionMain {
|
||||
vis=true;
|
||||
}
|
||||
|
||||
DataQueue vdq = acquisition.initalize(c, vis);
|
||||
EventBus b = new AsyncEventBus(Executors.newSingleThreadExecutor());
|
||||
|
||||
|
||||
acquisition.initalize(b, c);
|
||||
|
||||
Visualizer visualizer = null;
|
||||
// Only register data visualization task/processor if there are visualizations
|
||||
if(vis){
|
||||
visualizer = new Visualizer(vdq, c.getVisualization());
|
||||
|
||||
visualizer = new Visualizer(VisualizationMapper.mapVisualizations(c.getVisualization()));
|
||||
b.register(visualizer);
|
||||
|
||||
// TODO eventually set update on delimiter/dim boundary here
|
||||
|
||||
// If there is a continous dimension only update plot at the end of a line
|
||||
if(c.getScan() != null && c.getScan().getCdimension()!=null){
|
||||
visualizer.setUpdateAtStreamElement(false);
|
||||
@@ -317,7 +315,6 @@ public class AcquisitionMain {
|
||||
splitPane.setRightComponent(tpane);
|
||||
|
||||
frame.add(splitPane);
|
||||
// frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
frame.addWindowListener(new WindowAdapter(){
|
||||
@Override
|
||||
public void windowClosing(WindowEvent we){
|
||||
@@ -403,16 +400,11 @@ public class AcquisitionMain {
|
||||
try {
|
||||
if(visualizer != null){
|
||||
// Start visualization
|
||||
visualizer.startVisualization();
|
||||
visualizer.configure();
|
||||
}
|
||||
|
||||
acquisition.execute();
|
||||
|
||||
if(visualizer != null){
|
||||
// Stop visualization
|
||||
visualizer.stopVisualization();
|
||||
}
|
||||
|
||||
} catch (InterruptedException e1) {
|
||||
throw new RuntimeException("Acquisition was interrupted",e1);
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.co;
|
||||
package ch.psi.fda;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
@@ -33,6 +33,8 @@ import org.apache.commons.cli.OptionBuilder;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ch.psi.fda.deserializer.DataDeserializer;
|
||||
import ch.psi.fda.deserializer.DataDeserializerMDA;
|
||||
import ch.psi.fda.deserializer.DataDeserializerTXT;
|
||||
@@ -46,24 +48,15 @@ import ch.psi.fda.serializer.DataSerializerTXT2D;
|
||||
import ch.psi.fda.serializer.DataSerializerTXTSplit;
|
||||
|
||||
/**
|
||||
* Visualize data according to the scan description
|
||||
*
|
||||
* @author ebner
|
||||
*
|
||||
* Converter to convert the format of datafiles
|
||||
*/
|
||||
public class ConversionEngine {
|
||||
public class ConversionMain {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ConversionEngine.class.getName());
|
||||
private static Logger logger = Logger.getLogger(ConversionMain.class.getName());
|
||||
|
||||
public enum Writer {TXT, TXT_2D, TXT_SPLIT, MAT, MAT_2D, MDA, MAT_2D_Z};
|
||||
public enum Reader {TXT, MDA};
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public ConversionEngine(){
|
||||
}
|
||||
|
||||
/**
|
||||
* Visualize data
|
||||
@@ -89,14 +82,17 @@ public class ConversionEngine {
|
||||
else if(output.exists()){
|
||||
throw new IllegalArgumentException("Output file ["+output.getAbsolutePath()+"] already exists");
|
||||
}
|
||||
|
||||
|
||||
EventBus bus = new EventBus();
|
||||
|
||||
// Create deserializer
|
||||
DataDeserializer deserializer;
|
||||
if(reader.equals(Reader.TXT)){
|
||||
deserializer = new DataDeserializerTXT(input);
|
||||
deserializer = new DataDeserializerTXT(bus, input);
|
||||
}
|
||||
else if(reader.equals(Reader.MDA)){
|
||||
deserializer = new DataDeserializerMDA(input);
|
||||
deserializer = new DataDeserializerMDA(bus, input);
|
||||
}
|
||||
else{
|
||||
throw new IllegalArgumentException("Reader of type "+reader+" not supported.");
|
||||
@@ -104,39 +100,33 @@ public class ConversionEngine {
|
||||
|
||||
DataSerializer serializer;
|
||||
if(writer.equals(Writer.MAT)){
|
||||
serializer = new DataSerializerMAT(deserializer.getQueue(), output);
|
||||
serializer = new DataSerializerMAT(output);
|
||||
}
|
||||
else if(writer.equals(Writer.MAT_2D)){
|
||||
serializer = new DataSerializerMAT2D(deserializer.getQueue(), output);
|
||||
serializer = new DataSerializerMAT2D(output);
|
||||
}
|
||||
else if(writer.equals(Writer.TXT)){
|
||||
serializer = new DataSerializerTXT(deserializer.getQueue(), output, false);
|
||||
serializer = new DataSerializerTXT(output, false);
|
||||
}
|
||||
else if(writer.equals(Writer.TXT_2D)){
|
||||
serializer = new DataSerializerTXT2D(deserializer.getQueue(), output);
|
||||
serializer = new DataSerializerTXT2D(output);
|
||||
}
|
||||
else if(writer.equals(Writer.TXT_SPLIT)){
|
||||
serializer = new DataSerializerTXTSplit(deserializer.getQueue(), output);
|
||||
serializer = new DataSerializerTXTSplit(output);
|
||||
}
|
||||
else if(writer.equals(Writer.MDA)){
|
||||
serializer = new DataSerializerMDA(deserializer.getQueue(), output);
|
||||
serializer = new DataSerializerMDA(output);
|
||||
}
|
||||
else if(writer.equals(Writer.MAT_2D_Z)){
|
||||
serializer = new DataSerializerMAT2DZigZag(deserializer.getQueue(), output);
|
||||
serializer = new DataSerializerMAT2DZigZag(output);
|
||||
}
|
||||
else{
|
||||
throw new IllegalArgumentException("Writer of type "+writer+" not supported.");
|
||||
}
|
||||
|
||||
// Start deserializer and serializer
|
||||
Thread td = new Thread(deserializer);
|
||||
Thread ts = new Thread(serializer);
|
||||
|
||||
td.start();
|
||||
ts.start();
|
||||
|
||||
td.join();
|
||||
ts.join();
|
||||
|
||||
// Start conversion
|
||||
bus.register(serializer);
|
||||
deserializer.read();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,7 +233,7 @@ public class ConversionEngine {
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
ConversionEngine e = new ConversionEngine();
|
||||
ConversionMain e = new ConversionMain();
|
||||
try{
|
||||
e.convert(infile, outfile, reader, writer);
|
||||
}
|
||||
162
ch.psi.fda/src/main/java/ch/psi/fda/ViewerMain.java
Normal file
162
ch.psi.fda/src/main/java/ch/psi/fda/ViewerMain.java
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda;
|
||||
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.ScrollPaneLayout;
|
||||
|
||||
import org.jeromq.ZMQ;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ch.psi.fda.gui.ScrollableFlowPanel;
|
||||
import ch.psi.fda.visualizer.SeriesDataFilter;
|
||||
import ch.psi.fda.visualizer.Visualizer;
|
||||
import ch.psi.fda.visualizer.XYSeriesDataFilter;
|
||||
import ch.psi.plot.xy.LinePlot;
|
||||
|
||||
/**
|
||||
* Visualize data according to the scan description
|
||||
*/
|
||||
public class ViewerMain {
|
||||
|
||||
private static Logger logger = Logger.getLogger(ViewerMain.class.getName());
|
||||
|
||||
/**
|
||||
* Visualize data
|
||||
* @param configuration
|
||||
* @param data
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void visualize() throws InterruptedException{
|
||||
|
||||
List<SeriesDataFilter> filters = new ArrayList<>();
|
||||
filters.add(new XYSeriesDataFilter("id0", "timestamp", new LinePlot("One")));
|
||||
|
||||
Visualizer visualizer = new Visualizer(filters);
|
||||
|
||||
// visualizer.setTerminateAtEOS(true);
|
||||
// Adapt default visualizer behavior to optimize performance for visualization
|
||||
visualizer.setUpdateAtStreamElement(true);
|
||||
visualizer.setUpdateAtStreamDelimiter(true);
|
||||
visualizer.setUpdateAtEndOfStream(true);
|
||||
|
||||
JPanel opanel = new ScrollableFlowPanel();
|
||||
opanel.setLayout(new FlowLayout());
|
||||
|
||||
JScrollPane spane = new JScrollPane(opanel, ScrollPaneLayout.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneLayout.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
JTabbedPane tpane = new JTabbedPane();
|
||||
tpane.addTab("Overview", spane);
|
||||
|
||||
for (JPanel p : visualizer.getPlotPanels()) {
|
||||
opanel.add(p);
|
||||
}
|
||||
|
||||
final JFrame frame = new JFrame();
|
||||
frame.setSize(1200,800);
|
||||
frame.add(tpane);
|
||||
// frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
frame.addWindowListener(new WindowAdapter(){
|
||||
@Override
|
||||
public void windowClosing(WindowEvent we){
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);//.DO_NOTHING_ON_CLOSE);
|
||||
|
||||
java.awt.EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
frame.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
// Start receiving messages
|
||||
EventBus bus = new EventBus();
|
||||
bus.register(visualizer);
|
||||
visualizer.configure();
|
||||
|
||||
ZMQ.Context context = ZMQ.context();
|
||||
zmq.ZError.clear(); // Clear error code
|
||||
ZMQ.Socket socket = context.socket(ZMQ.SUB);
|
||||
socket.connect("tcp://emac:10000");
|
||||
socket.subscribe(""); // SUBSCRIBE !
|
||||
|
||||
while(true){
|
||||
byte[] content = null;
|
||||
// String header = socket.recvStr(); // header
|
||||
socket.recvStr(); // header
|
||||
while(socket.hasReceiveMore()){
|
||||
content = socket.recv();
|
||||
}
|
||||
if(content==null){ // we lost something discard read messages
|
||||
logger.warning("Lost some message - discard and continue");
|
||||
continue;
|
||||
}
|
||||
|
||||
try (
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(content);
|
||||
ObjectInput in = new ObjectInputStream(bis);
|
||||
) {
|
||||
Object o = in.readObject();
|
||||
bus.post(o);
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
logger.log(Level.WARNING,"Unable to deserialize message",e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method accepts a data file and an option (-file) specifying the scan configuration file
|
||||
* used for creating the data file. If no option is specified the configuration file is derived by the
|
||||
* data file name.
|
||||
*
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
||||
try{
|
||||
ViewerMain e = new ViewerMain();
|
||||
e.visualize();
|
||||
}
|
||||
catch(Exception ee){
|
||||
System.out.println("Visualization failed due to: "+ee.getMessage());
|
||||
logger.log(Level.WARNING, "Visualization failed due to Exception:", ee);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,13 +17,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.vis;
|
||||
package ch.psi.fda;
|
||||
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -44,6 +45,10 @@ import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.common.eventbus.AsyncEventBus;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ch.psi.fda.aq.VisualizationMapper;
|
||||
import ch.psi.fda.deserializer.DataDeserializer;
|
||||
import ch.psi.fda.deserializer.DataDeserializerTXT;
|
||||
import ch.psi.fda.gui.ScrollableFlowPanel;
|
||||
@@ -53,19 +58,15 @@ import ch.psi.fda.visualizer.Visualizer;
|
||||
|
||||
/**
|
||||
* Visualize data according to the scan description
|
||||
*
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class VisualizationEngine {
|
||||
public class VisualizationMain {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(VisualizationEngine.class.getName());
|
||||
private static Logger logger = Logger.getLogger(VisualizationMain.class.getName());
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public VisualizationEngine(){
|
||||
public VisualizationMain(){
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,13 +113,14 @@ public class VisualizationEngine {
|
||||
throw new IllegalArgumentException("Data file ["+data.getAbsolutePath()+"] does not exist");
|
||||
}
|
||||
|
||||
EventBus bus = new AsyncEventBus(Executors.newCachedThreadPool());
|
||||
// Create deserializer
|
||||
DataDeserializer deserializer = new DataDeserializerTXT(data);
|
||||
DataDeserializer deserializer = new DataDeserializerTXT(bus, data);
|
||||
|
||||
// Create Visualizer
|
||||
Visualizer visualizer = new Visualizer(deserializer.getQueue(), configuration.getVisualization());
|
||||
Visualizer visualizer = new Visualizer(VisualizationMapper.mapVisualizations(configuration.getVisualization()));
|
||||
|
||||
visualizer.setTerminateAtEOS(true);
|
||||
// visualizer.setTerminateAtEOS(true);
|
||||
// Adapt default visualizer behavior to optimize performance for visualization
|
||||
visualizer.setUpdateAtStreamElement(false);
|
||||
visualizer.setUpdateAtStreamDelimiter(false);
|
||||
@@ -155,12 +157,10 @@ public class VisualizationEngine {
|
||||
|
||||
// Start deserializer and visualizer
|
||||
|
||||
Thread td = new Thread(deserializer);
|
||||
bus.register(visualizer);
|
||||
visualizer.configure();
|
||||
deserializer.read();
|
||||
|
||||
td.start();
|
||||
visualizer.startVisualization();
|
||||
|
||||
td.join();
|
||||
logger.info("Deserializer finished");
|
||||
// visualizer.stopVisualization();
|
||||
}
|
||||
@@ -215,7 +215,7 @@ public class VisualizationEngine {
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
VisualizationEngine e = new VisualizationEngine();
|
||||
VisualizationMain e = new VisualizationMain();
|
||||
try{
|
||||
e.visualize(cfile, dfile);
|
||||
}
|
||||
@@ -24,27 +24,26 @@ import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
|
||||
import ch.psi.fda.aq.ng.AcquisitionEngineNG;
|
||||
import ch.psi.fda.aq.ng.ScanMapperNG;
|
||||
import com.google.common.eventbus.AsyncEventBus;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ch.psi.fda.core.ActionLoop;
|
||||
import ch.psi.fda.core.Actor;
|
||||
import ch.psi.fda.core.EngineConfiguration;
|
||||
import ch.psi.fda.core.Manipulation;
|
||||
import ch.psi.fda.core.Sensor;
|
||||
import ch.psi.fda.core.actions.ChannelAccessCondition;
|
||||
import ch.psi.fda.core.actions.ChannelAccessConditionAnd;
|
||||
import ch.psi.fda.core.actions.ChannelAccessConditionOr;
|
||||
import ch.psi.fda.core.actions.ChannelAccessConditionRegex;
|
||||
import ch.psi.fda.core.actions.ChannelAccessPut;
|
||||
import ch.psi.fda.core.actions.Delay;
|
||||
import ch.psi.fda.core.actors.ChannelAccessFunctionActuator;
|
||||
@@ -52,35 +51,26 @@ import ch.psi.fda.core.actors.ChannelAccessLinearActuator;
|
||||
import ch.psi.fda.core.actors.ChannelAccessTableActuator;
|
||||
import ch.psi.fda.core.actors.ComplexActuator;
|
||||
import ch.psi.fda.core.actors.JythonFunction;
|
||||
import ch.psi.fda.core.actors.OTFActuator;
|
||||
import ch.psi.fda.core.actors.PseudoActuatorSensor;
|
||||
import ch.psi.fda.core.collector.Collector;
|
||||
import ch.psi.fda.core.collector.DataDispatcher;
|
||||
import ch.psi.fda.core.guard.ChannelAccessGuard;
|
||||
import ch.psi.fda.core.guard.ChannelAccessGuardCondition;
|
||||
import ch.psi.fda.core.loops.ActorSensorLoop;
|
||||
import ch.psi.fda.core.loops.OTFLoop;
|
||||
import ch.psi.fda.core.loops.cr.CrlogicLoop;
|
||||
import ch.psi.fda.core.loops.cr.CrlogicResource;
|
||||
import ch.psi.fda.core.loops.cr.ParallelCrlogic;
|
||||
import ch.psi.fda.core.loops.cr.ScrlogicLoop;
|
||||
import ch.psi.fda.core.loops.otf.OTFLoop;
|
||||
import ch.psi.fda.core.loops.otf.OTFNamedChannelSensor;
|
||||
import ch.psi.fda.core.loops.otf.OTFScalerChannelSensor;
|
||||
import ch.psi.fda.core.loops.otf.TemplateOTF;
|
||||
import ch.psi.fda.core.manipulator.JythonManipulation;
|
||||
import ch.psi.fda.core.manipulator.Manipulation;
|
||||
import ch.psi.fda.core.manipulator.Manipulator;
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
import ch.psi.fda.core.scripting.JythonGlobalVariable;
|
||||
import ch.psi.fda.core.scripting.JythonGlobalVariableDictionary;
|
||||
import ch.psi.fda.core.scripting.JythonParameterMapping;
|
||||
import ch.psi.fda.core.scripting.JythonParameterMappingChannel;
|
||||
import ch.psi.fda.core.scripting.JythonParameterMappingGlobalVariable;
|
||||
import ch.psi.fda.core.scripting.JythonParameterMappingID;
|
||||
import ch.psi.fda.core.sensors.ChannelAccessDoubleArraySensor;
|
||||
import ch.psi.fda.core.sensors.ChannelAccessDoubleSensor;
|
||||
import ch.psi.fda.core.sensors.ChannelAccessStringSensor;
|
||||
import ch.psi.fda.core.sensors.MillisecondTimestampSensor;
|
||||
import ch.psi.fda.core.sensors.OTFNamedChannelSensor;
|
||||
import ch.psi.fda.core.sensors.OTFReadbackSensor;
|
||||
import ch.psi.fda.core.sensors.OTFScalerChannelSensor;
|
||||
import ch.psi.fda.core.sensors.ChannelAccessSensor;
|
||||
import ch.psi.fda.core.sensors.TimestampSensor;
|
||||
import ch.psi.fda.model.ModelManager;
|
||||
import ch.psi.fda.model.v1.Action;
|
||||
import ch.psi.fda.model.v1.ArrayDetector;
|
||||
@@ -116,10 +106,15 @@ import ch.psi.fda.model.v1.SimpleScalarDetector;
|
||||
import ch.psi.fda.model.v1.Timestamp;
|
||||
import ch.psi.fda.model.v1.Variable;
|
||||
import ch.psi.fda.model.v1.VariableParameterMapping;
|
||||
import ch.psi.fda.notification.NotificationAgent;
|
||||
import ch.psi.fda.serializer.DataSerializerTXT;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
import ch.psi.jcae.impl.DefaultChannelService;
|
||||
import ch.psi.jcae.impl.type.DoubleTimestamp;
|
||||
import ch.psi.jcae.util.ComparatorAND;
|
||||
import ch.psi.jcae.util.ComparatorOR;
|
||||
import ch.psi.jcae.util.ComparatorREGEX;
|
||||
|
||||
/**
|
||||
* Data acquisition engine for performing scans
|
||||
@@ -129,18 +124,11 @@ import ch.psi.jcae.impl.DefaultChannelService;
|
||||
*/
|
||||
public class Acquisition {
|
||||
|
||||
private static boolean NEW_ENGINE = true;
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(Acquisition.class.getName());
|
||||
|
||||
private AcquisitionEngineConfiguration configuration;
|
||||
private final AcquisitionConfiguration configuration;
|
||||
|
||||
private ActionLoop actionLoop;
|
||||
private Collector collector;
|
||||
private ScanMapperNG mapper;
|
||||
private AcquisitionEngineNG acquisitionEngine;
|
||||
private DataDispatcher dispatcher;
|
||||
private Manipulator manipulator;
|
||||
private DataSerializerTXT serializer;
|
||||
|
||||
@@ -151,21 +139,23 @@ public class Acquisition {
|
||||
|
||||
private Handler logHandler = null;
|
||||
|
||||
private ChannelService cservice;
|
||||
|
||||
/**
|
||||
* Name of the datafile
|
||||
*/
|
||||
private File datafile;
|
||||
|
||||
// private Thread acquisitionThread = null;
|
||||
|
||||
public Acquisition(){
|
||||
configuration = AcquisitionEngineConfiguration.getInstance();
|
||||
actionLoop = null;
|
||||
collector = new Collector();
|
||||
manipulations = new ArrayList<Manipulation>();
|
||||
|
||||
private ChannelService cservice;
|
||||
private List<Channel<?>> channels = new ArrayList<>();
|
||||
private List<Object> templates = new ArrayList<>();
|
||||
|
||||
|
||||
private Configuration configModel;
|
||||
|
||||
private HashMap<String, JythonGlobalVariable> jVariableDictionary = new HashMap<String, JythonGlobalVariable>();
|
||||
|
||||
public Acquisition(ChannelService cservice, AcquisitionConfiguration configuration){
|
||||
this.cservice = cservice;
|
||||
this.configuration = configuration;
|
||||
this.actionLoop = null;
|
||||
this.manipulations = new ArrayList<Manipulation>();
|
||||
}
|
||||
|
||||
|
||||
@@ -187,10 +177,8 @@ public class Acquisition {
|
||||
* @param getQueue Flag whether to return a queue or not. If false the return value of the function will be null.
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public DataQueue initalize(Configuration smodel, boolean getQueue) {
|
||||
|
||||
cservice = new DefaultChannelService();
|
||||
|
||||
public void initalize(EventBus bus, Configuration smodel) {
|
||||
|
||||
// Create notification agent with globally configured recipients
|
||||
notificationAgent = new NotificationAgent(configuration.getSmptServer(), "fda.notification@psi.ch");
|
||||
|
||||
@@ -243,52 +231,37 @@ public class Acquisition {
|
||||
throw new RuntimeException("Unable to serialize scan",e);
|
||||
}
|
||||
|
||||
// Configure core engine
|
||||
EngineConfiguration.getInstance().setFailOnSensorError(smodel.isFailOnSensorError());
|
||||
|
||||
if(NEW_ENGINE){
|
||||
acquisitionEngine = new AcquisitionEngineNG(cservice);
|
||||
mapper = new ScanMapperNG();
|
||||
mapper.map(smodel);
|
||||
|
||||
this.manipulator = new Manipulator(new DataQueue( acquisitionEngine.getOutQueue(), mapper.getDataMessageMetadata()), this.manipulations);
|
||||
}
|
||||
else{
|
||||
logger.fine("Map Model to internal logic");
|
||||
|
||||
logger.fine("Map Model to internal logic");
|
||||
|
||||
if(smodel.getScan().getManipulation()!= null && smodel.getScan().getManipulation().size()>0){
|
||||
// Setup optimized with manipulations
|
||||
EventBus b = new AsyncEventBus(Executors.newCachedThreadPool());
|
||||
// Map scan to base model
|
||||
// After this call actionLoop and collector will be initialized
|
||||
mapScan(smodel);
|
||||
|
||||
Collector collector = new Collector(b);
|
||||
mapScan(collector, smodel);
|
||||
// col = collector;
|
||||
logger.fine("ActionLoop and Collector initialized");
|
||||
|
||||
// TODO Remove this workaround
|
||||
Collections.reverse(collector.getQueues());
|
||||
|
||||
|
||||
// Add manipulator into processing chain
|
||||
this.manipulator = new Manipulator(collector.getOutQueue(), this.manipulations);
|
||||
this.manipulator = new Manipulator(bus, this.manipulations);
|
||||
b.register(this.manipulator);
|
||||
|
||||
|
||||
this.serializer = new DataSerializerTXT(datafile, true);
|
||||
bus.register(serializer);
|
||||
}
|
||||
|
||||
|
||||
// // Insert dispatcher into processing chain
|
||||
this.dispatcher = new DataDispatcher(manipulator.getOutQueue());
|
||||
|
||||
DataQueue dq = new DataQueue(new LinkedBlockingQueue<Message>(1000), manipulator.getOutQueue().getDataMessageMetadata()); // Create bounded queue to
|
||||
// prevent running out of
|
||||
// memory ...
|
||||
this.serializer = new DataSerializerTXT(dq, datafile, true);
|
||||
|
||||
DataQueue vdq = null;
|
||||
if (getQueue) {
|
||||
vdq = new DataQueue(new LinkedBlockingQueue<Message>(1000), manipulator.getOutQueue().getDataMessageMetadata()); // Create bounded queue to prevent
|
||||
// running out of memory ...
|
||||
dispatcher.getOutQueues().add(vdq);
|
||||
else{
|
||||
// Setup optimized without manipulations
|
||||
Collector collector = new Collector(bus);
|
||||
mapScan(collector, smodel);
|
||||
// col = collector;
|
||||
|
||||
this.serializer = new DataSerializerTXT(datafile, true);
|
||||
bus.register(serializer);
|
||||
}
|
||||
|
||||
// Add queue for serializer to dispatcher
|
||||
dispatcher.getOutQueues().add(dq);
|
||||
|
||||
return (vdq);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,48 +270,12 @@ public class Acquisition {
|
||||
*/
|
||||
public void execute() throws InterruptedException {
|
||||
|
||||
// acquisitionThread = Thread.currentThread();
|
||||
|
||||
try{
|
||||
active = true;
|
||||
|
||||
Thread tc = null;
|
||||
if(!NEW_ENGINE){
|
||||
tc = new Thread(collector);
|
||||
tc.start();
|
||||
}
|
||||
|
||||
Thread tm = new Thread(manipulator);
|
||||
tm.start();
|
||||
|
||||
Thread td = new Thread(dispatcher);
|
||||
td.start();
|
||||
|
||||
Thread t = new Thread(serializer);
|
||||
t.start();
|
||||
|
||||
if(NEW_ENGINE){
|
||||
acquisitionEngine.execute(mapper.getResourceDescriptors(), mapper.getScript(), new ArrayList<String>());
|
||||
}
|
||||
else {
|
||||
actionLoop.prepare();
|
||||
actionLoop.execute();
|
||||
actionLoop.cleanup();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Wait for data collector threads
|
||||
// Do this with a Latch or something like that
|
||||
|
||||
// Give the threads 1 minute to catch up
|
||||
if(!NEW_ENGINE){
|
||||
tc.join(60000);
|
||||
}
|
||||
tm.join(60000);
|
||||
td.join(60000);
|
||||
t.join(60000);
|
||||
actionLoop.prepare();
|
||||
actionLoop.execute();
|
||||
actionLoop.cleanup();
|
||||
|
||||
// Send notifications out to all recipients that want to have success notifications
|
||||
try {
|
||||
@@ -347,8 +284,6 @@ public class Acquisition {
|
||||
} catch (UnknownHostException e1) {
|
||||
logger.log(Level.WARNING, "Unable to send notification", e1);
|
||||
}
|
||||
|
||||
// active = false;
|
||||
}
|
||||
catch(RuntimeException e){
|
||||
logger.log(Level.WARNING, "Execution failed: ", e);
|
||||
@@ -383,26 +318,31 @@ public class Acquisition {
|
||||
|
||||
public void destroy(){
|
||||
if(actionLoop != null){
|
||||
logger.finest("Destroy action loop");
|
||||
try{
|
||||
actionLoop.destroy();
|
||||
logger.finest("Destroy managed resources");
|
||||
|
||||
for(Channel<?> c: channels){
|
||||
try {
|
||||
c.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel "+c.getName(),e);
|
||||
}
|
||||
}
|
||||
catch(Exception e){
|
||||
logger.log(Level.SEVERE, "Unable to destroy action loop", e);
|
||||
for(Object o: templates){
|
||||
try {
|
||||
cservice.destroyAnnotatedChannels(o);
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channels of template: "+o.getClass().getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Clear global variables Jython
|
||||
JythonGlobalVariableDictionary.getInstance().clear();
|
||||
jVariableDictionary.clear();
|
||||
|
||||
// Destroy the CA context
|
||||
try {
|
||||
logger.fine("Destroy Channel Access context");
|
||||
cservice.destroy();
|
||||
} catch (IllegalStateException e) {
|
||||
logger.log(Level.SEVERE, "Unable to destroy channel access context", e);
|
||||
}
|
||||
logger.fine("Context destroyed");
|
||||
// // Destroy the CA context
|
||||
// cservice.destroy();
|
||||
// logger.fine("ChannelService destroyed");
|
||||
|
||||
// Remove log handler
|
||||
if(logHandler!=null){
|
||||
@@ -455,20 +395,21 @@ public class Acquisition {
|
||||
* Map scan to base model
|
||||
* @param scan
|
||||
*/
|
||||
private void mapScan(Configuration configuration){
|
||||
private void mapScan(Collector collector, Configuration configuration){
|
||||
this.configModel = configuration;
|
||||
Scan scan = configuration.getScan();
|
||||
|
||||
// Map continuous dimension
|
||||
if(scan.getCdimension() != null){
|
||||
ActionLoop aLoop = mapContinuousDimension(scan.getCdimension());
|
||||
actionLoop = aLoop;
|
||||
collector.getQueues().add(aLoop.getDataQueue());
|
||||
collector.addEventBus(aLoop.getEventBus());
|
||||
}
|
||||
|
||||
// Map discrete step dimensions
|
||||
for(DiscreteStepDimension d: scan.getDimension()){
|
||||
ActorSensorLoop l = mapDiscreteStepDimension(d);
|
||||
collector.getQueues().add(l.getDataQueue());
|
||||
collector.addEventBus(l.getEventBus());
|
||||
if(actionLoop != null){
|
||||
l.getActionLoops().add(actionLoop);
|
||||
}
|
||||
@@ -487,6 +428,7 @@ public class Acquisition {
|
||||
actionLoop.getPostActions().addAll(mapActions(scan.getPostAction()));
|
||||
|
||||
|
||||
// TODO need to be removed! and done differently !!!!
|
||||
// Handle iterations by adding a pseudo dimension and setting the
|
||||
// datagroup flag in the main loop
|
||||
if(configuration.getNumberOfExecution()>1){
|
||||
@@ -499,11 +441,10 @@ public class Acquisition {
|
||||
|
||||
// Set toplevel action loop
|
||||
actionLoop = l;
|
||||
collector.getQueues().add(l.getDataQueue());
|
||||
collector.addEventBus(l.getEventBus());
|
||||
}
|
||||
|
||||
|
||||
JythonGlobalVariableDictionary dict = JythonGlobalVariableDictionary.getInstance();
|
||||
// handling manipulations
|
||||
for(ch.psi.fda.model.v1.Manipulation m : scan.getManipulation()){
|
||||
if(m instanceof ScriptManipulation){
|
||||
ScriptManipulation sm = (ScriptManipulation) m;
|
||||
@@ -517,13 +458,13 @@ public class Acquisition {
|
||||
else if(pm instanceof ChannelParameterMapping){
|
||||
ChannelParameterMapping cpm = (ChannelParameterMapping) pm;
|
||||
if(cpm.getType().equals("String")){
|
||||
mapping.add( new JythonParameterMappingChannel(cpm.getVariable(), cpm.getChannel(), String.class));
|
||||
mapping.add( new JythonParameterMappingChannel<String>(cpm.getVariable(), createChannel(String.class, cpm.getChannel())));
|
||||
}
|
||||
else if(cpm.getType().equals("Integer")){
|
||||
mapping.add( new JythonParameterMappingChannel(cpm.getVariable(), cpm.getChannel(), Integer.class));
|
||||
mapping.add( new JythonParameterMappingChannel<Integer>(cpm.getVariable(), createChannel(Integer.class, cpm.getChannel())));
|
||||
}
|
||||
else if(cpm.getType().equals("Double")){
|
||||
mapping.add( new JythonParameterMappingChannel(cpm.getVariable(), cpm.getChannel(), Double.class));
|
||||
mapping.add( new JythonParameterMappingChannel<Double>(cpm.getVariable(), createChannel(Double.class, cpm.getChannel())));
|
||||
}
|
||||
else{
|
||||
logger.warning("Channel type ["+cpm.getType()+"] is not supported for mapping");
|
||||
@@ -532,13 +473,19 @@ public class Acquisition {
|
||||
else if(pm instanceof VariableParameterMapping){
|
||||
VariableParameterMapping vp = (VariableParameterMapping) pm;
|
||||
Variable v = (Variable)vp.getName();
|
||||
JythonGlobalVariable var = dict.getVariable(v.getName());
|
||||
JythonGlobalVariable var = jVariableDictionary.get(v.getName());
|
||||
var.setValue(v.getValue());
|
||||
mapping.add(new JythonParameterMappingGlobalVariable(vp.getVariable(), var));
|
||||
}
|
||||
}
|
||||
|
||||
JythonManipulation manipulation = new JythonManipulation(cservice, sm.getId(), sm.getScript(), mapping, sm.isReturnArray());
|
||||
JythonManipulation manipulation = new JythonManipulation(sm.getId(), sm.getScript(), mapping, sm.isReturnArray());
|
||||
|
||||
if(configuration.getData()!=null){ // Safety
|
||||
manipulation.setVariable("FILENAME", configuration.getData().getFileName());
|
||||
manipulation.setVariable("DATAFILE", datafile.getAbsoluteFile());
|
||||
}
|
||||
|
||||
this.manipulations.add(manipulation);
|
||||
}
|
||||
}
|
||||
@@ -564,24 +511,24 @@ public class Acquisition {
|
||||
timeout = Math.round(ca.getTimeout()*1000);
|
||||
}
|
||||
if(type.equals("String")){
|
||||
alist.add(new ChannelAccessPut<String>(cservice, ca.getChannel(), ca.getValue(), false, timeout));
|
||||
alist.add(new ChannelAccessPut<String>(createChannel(String.class, ca.getChannel()), ca.getValue(), false, timeout));
|
||||
}
|
||||
else if(type.equals("Integer")){
|
||||
alist.add(new ChannelAccessPut<Integer>(cservice, ca.getChannel(), new Integer(ca.getValue()), false, timeout));
|
||||
alist.add(new ChannelAccessPut<Integer>(createChannel(Integer.class, ca.getChannel()), new Integer(ca.getValue()), false, timeout));
|
||||
}
|
||||
else if(type.equals("Double")){
|
||||
alist.add(new ChannelAccessPut<Double>(cservice, ca.getChannel(), new Double(ca.getValue()), false, timeout));
|
||||
alist.add(new ChannelAccessPut<Double>(createChannel(Double.class,ca.getChannel()), new Double(ca.getValue()), false, timeout));
|
||||
}
|
||||
}
|
||||
else if(operation.equals("putq")){
|
||||
if(type.equals("String")){
|
||||
alist.add(new ChannelAccessPut<String>(cservice, ca.getChannel(), ca.getValue(), true, null));
|
||||
alist.add(new ChannelAccessPut<String>(createChannel(String.class,ca.getChannel()), ca.getValue(), true, null));
|
||||
}
|
||||
else if(type.equals("Integer")){
|
||||
alist.add(new ChannelAccessPut<Integer>(cservice, ca.getChannel(), new Integer(ca.getValue()), true, null));
|
||||
alist.add(new ChannelAccessPut<Integer>(createChannel(Integer.class,ca.getChannel()), new Integer(ca.getValue()), true, null));
|
||||
}
|
||||
else if(type.equals("Double")){
|
||||
alist.add(new ChannelAccessPut<Double>(cservice, ca.getChannel(), new Double(ca.getValue()), true, null));
|
||||
alist.add(new ChannelAccessPut<Double>(createChannel(Double.class,ca.getChannel()), new Double(ca.getValue()), true, null));
|
||||
}
|
||||
}
|
||||
else if(operation.equals("wait")){
|
||||
@@ -590,13 +537,13 @@ public class Acquisition {
|
||||
timeout = Math.round(ca.getTimeout()*1000);
|
||||
}
|
||||
if(type.equals("String")){
|
||||
alist.add(new ChannelAccessCondition<String>(cservice, ca.getChannel(), ca.getValue(), timeout));
|
||||
alist.add(new ChannelAccessCondition<String>(createChannel(String.class,ca.getChannel()), ca.getValue(), timeout));
|
||||
}
|
||||
else if(type.equals("Integer")){
|
||||
alist.add(new ChannelAccessCondition<Integer>(cservice, ca.getChannel(), new Integer(ca.getValue()), timeout));
|
||||
alist.add(new ChannelAccessCondition<Integer>(createChannel(Integer.class,ca.getChannel()), new Integer(ca.getValue()), timeout));
|
||||
}
|
||||
else if(type.equals("Double")){
|
||||
alist.add(new ChannelAccessCondition<Double>(cservice, ca.getChannel(), new Double(ca.getValue()), timeout));
|
||||
alist.add(new ChannelAccessCondition<Double>(createChannel(Double.class,ca.getChannel()), new Double(ca.getValue()), timeout));
|
||||
}
|
||||
}
|
||||
else if(operation.equals("waitREGEX")){
|
||||
@@ -605,7 +552,7 @@ public class Acquisition {
|
||||
timeout = Math.round(ca.getTimeout()*1000);
|
||||
}
|
||||
if(type.equals("String")){
|
||||
alist.add(new ChannelAccessConditionRegex<String>(cservice, ca.getChannel(), ca.getValue(), timeout));
|
||||
alist.add(new ChannelAccessCondition<>(createChannel(String.class, ca.getChannel()), ca.getValue(), new ComparatorREGEX(), timeout));
|
||||
}
|
||||
else{
|
||||
logger.warning("Operation "+operation+" wity type "+type+" for action is not supported");
|
||||
@@ -618,7 +565,7 @@ public class Acquisition {
|
||||
}
|
||||
|
||||
if(type.equals("Integer")){
|
||||
alist.add(new ChannelAccessConditionOr<Integer>(cservice, ca.getChannel(), new Integer(ca.getValue()), timeout));
|
||||
alist.add(new ChannelAccessCondition<>(createChannel(Integer.class,ca.getChannel()), new Integer(ca.getValue()), new ComparatorOR(), timeout));
|
||||
}
|
||||
else{
|
||||
logger.warning("Operation "+operation+" wity type "+type+" for action is not supported");
|
||||
@@ -630,7 +577,7 @@ public class Acquisition {
|
||||
timeout = Math.round(ca.getTimeout()*1000);
|
||||
}
|
||||
if(type.equals("Integer")){
|
||||
alist.add(new ChannelAccessConditionAnd<Integer>(cservice, ca.getChannel(), new Integer(ca.getValue()), timeout));
|
||||
alist.add(new ChannelAccessCondition<>(createChannel(Integer.class,ca.getChannel()), new Integer(ca.getValue()), new ComparatorAND(), timeout));
|
||||
}
|
||||
else {
|
||||
logger.warning("Operation "+operation+" wity type "+type+" for action is not supported");
|
||||
@@ -650,7 +597,9 @@ public class Acquisition {
|
||||
}
|
||||
else if(a instanceof ShellAction){
|
||||
ShellAction sa = (ShellAction) a;
|
||||
ch.psi.fda.core.actions.ShellAction action = new ch.psi.fda.core.actions.ShellAction(sa.getCommand());
|
||||
String com = sa.getCommand().replaceAll("\\$\\{DATAFILE\\}", datafile.getAbsolutePath());
|
||||
com = com.replaceAll("\\$\\{FILENAME\\}", datafile.getName().replaceAll("\\.\\w*$", ""));
|
||||
ch.psi.fda.core.actions.ShellAction action = new ch.psi.fda.core.actions.ShellAction(com);
|
||||
action.setCheckExitValue(sa.isCheckExitValue());
|
||||
action.setExitValue(sa.getExitValue());
|
||||
alist.add(action);
|
||||
@@ -658,23 +607,32 @@ public class Acquisition {
|
||||
else if(a instanceof ScriptAction){
|
||||
|
||||
ScriptAction sa = (ScriptAction) a;
|
||||
|
||||
// TODO set global variables DATAFILE and FILENAME
|
||||
|
||||
// TODO create Jython Action
|
||||
List<JythonParameterMappingChannel> mapping = new ArrayList<JythonParameterMappingChannel>();
|
||||
Map<String, Channel<?>> mapping = new HashMap<>();
|
||||
for(ChannelParameterMapping ma: sa.getMapping()){
|
||||
if(ma.getType().equals("String")){
|
||||
mapping.add(new JythonParameterMappingChannel(ma.getVariable(), ma.getChannel(), String.class));
|
||||
mapping.put(ma.getVariable(), createChannel(String.class, ma.getChannel()));
|
||||
}
|
||||
else if(ma.getType().equals("Integer")){
|
||||
mapping.add(new JythonParameterMappingChannel(ma.getVariable(), ma.getChannel(), Integer.class));
|
||||
mapping.put(ma.getVariable(), createChannel(Integer.class, ma.getChannel()));
|
||||
}
|
||||
else if(ma.getType().equals("Double")){
|
||||
mapping.add(new JythonParameterMappingChannel(ma.getVariable(), ma.getChannel(), Double.class));
|
||||
mapping.put(ma.getVariable(), createChannel(Double.class, ma.getChannel()));
|
||||
}
|
||||
else{
|
||||
logger.warning("Channel type ["+ma.getType()+"] is not supported for mapping");
|
||||
}
|
||||
}
|
||||
alist.add(new ch.psi.fda.core.actions.JythonAction(cservice, sa.getScript(), mapping));
|
||||
|
||||
Map<String,Object> gobjects = new HashMap<>();
|
||||
gobjects.put("FILENAME", datafile.getName().replaceAll("\\.\\w*$", ""));
|
||||
gobjects.put("DATAFILE", datafile.getAbsoluteFile());
|
||||
ch.psi.fda.core.actions.JythonAction ja = new ch.psi.fda.core.actions.JythonAction(sa.getScript(), mapping, gobjects);
|
||||
|
||||
alist.add(ja);
|
||||
}
|
||||
}
|
||||
return(alist);
|
||||
@@ -693,7 +651,7 @@ public class Acquisition {
|
||||
// Mapping dimension pre-actions
|
||||
aLoop.getPreActions().addAll(mapActions(dimension.getPreAction()));
|
||||
|
||||
Long moveTimeout = AcquisitionEngineConfiguration.getInstance().getActorMoveTimeout();
|
||||
Long moveTimeout = this.configuration.getActorMoveTimeout();
|
||||
|
||||
// Mapping positioners
|
||||
Double stime = 0d;
|
||||
@@ -707,14 +665,14 @@ public class Acquisition {
|
||||
LinearPositioner lp =(LinearPositioner) p;
|
||||
ChannelAccessLinearActuator<?> a;
|
||||
if(lp.getType().equals("String")){
|
||||
a = new ChannelAccessLinearActuator<String>(cservice, lp.getName(), lp.getDone(), lp.getDoneValue(), lp.getDoneDelay(), lp.getStart(), lp.getEnd(), lp.getStepSize(), moveTimeout);
|
||||
a = new ChannelAccessLinearActuator<String>(createChannel(Double.class, lp.getName()), createChannel(String.class, lp.getDone()), lp.getDoneValue(), lp.getDoneDelay(), lp.getStart(), lp.getEnd(), lp.getStepSize(), moveTimeout);
|
||||
}
|
||||
else if(lp.getType().equals("Double")){
|
||||
a = new ChannelAccessLinearActuator<Double>(cservice, lp.getName(), lp.getDone(), Double.parseDouble(lp.getDoneValue()), lp.getDoneDelay(), lp.getStart(), lp.getEnd(), lp.getStepSize(), moveTimeout);
|
||||
a = new ChannelAccessLinearActuator<Double>(createChannel(Double.class, lp.getName()), createChannel(Double.class,lp.getDone()), Double.parseDouble(lp.getDoneValue()), lp.getDoneDelay(), lp.getStart(), lp.getEnd(), lp.getStepSize(), moveTimeout);
|
||||
}
|
||||
else{
|
||||
// Default
|
||||
a = new ChannelAccessLinearActuator<Integer>(cservice, lp.getName(), lp.getDone(), Integer.parseInt(lp.getDoneValue()), lp.getDoneDelay(), lp.getStart(), lp.getEnd(), lp.getStepSize(), moveTimeout);
|
||||
a = new ChannelAccessLinearActuator<Integer>(createChannel(Double.class, lp.getName()), createChannel(Integer.class,lp.getDone()), Integer.parseInt(lp.getDoneValue()), lp.getDoneDelay(), lp.getStart(), lp.getEnd(), lp.getStepSize(), moveTimeout);
|
||||
}
|
||||
|
||||
a.setAsynchronous(lp.isAsynchronous());
|
||||
@@ -727,7 +685,7 @@ public class Acquisition {
|
||||
if(name==null){
|
||||
name = lp.getName();
|
||||
}
|
||||
ChannelAccessDoubleSensor sensor = new ChannelAccessDoubleSensor(cservice, lp.getId(), name);
|
||||
ChannelAccessSensor<Double> sensor = new ChannelAccessSensor<Double>(lp.getId(), createChannel(Double.class, name), configModel.isFailOnSensorError());
|
||||
aLoop.getSensors().add(sensor);
|
||||
}
|
||||
else if(p instanceof FunctionPositioner){
|
||||
@@ -740,14 +698,14 @@ public class Acquisition {
|
||||
// Create actuator
|
||||
ChannelAccessFunctionActuator<?> a;
|
||||
if(lp.getType().equals("String")){
|
||||
a = new ChannelAccessFunctionActuator<String>(cservice, lp.getName(), lp.getDone(), lp.getDoneValue(), lp.getDoneDelay(), function, lp.getStart(), lp.getEnd(), lp.getStepSize(), moveTimeout);
|
||||
a = new ChannelAccessFunctionActuator<String>(createChannel(Double.class,lp.getName()), createChannel(String.class,lp.getDone()), lp.getDoneValue(), lp.getDoneDelay(), function, lp.getStart(), lp.getEnd(), lp.getStepSize(), moveTimeout);
|
||||
}
|
||||
else if(lp.getType().equals("Double")){
|
||||
a = new ChannelAccessFunctionActuator<Double>(cservice, lp.getName(), lp.getDone(), Double.parseDouble(lp.getDoneValue()), lp.getDoneDelay(), function, lp.getStart(), lp.getEnd(), lp.getStepSize(), moveTimeout);
|
||||
a = new ChannelAccessFunctionActuator<Double>(createChannel(Double.class, lp.getName()), createChannel(Double.class, lp.getDone()), Double.parseDouble(lp.getDoneValue()), lp.getDoneDelay(), function, lp.getStart(), lp.getEnd(), lp.getStepSize(), moveTimeout);
|
||||
}
|
||||
else{
|
||||
// Default
|
||||
a = new ChannelAccessFunctionActuator<Integer>(cservice, lp.getName(), lp.getDone(), Integer.parseInt(lp.getDoneValue()), lp.getDoneDelay(), function, lp.getStart(), lp.getEnd(), lp.getStepSize(), moveTimeout);
|
||||
a = new ChannelAccessFunctionActuator<Integer>(createChannel(Double.class, lp.getName()), createChannel(Integer.class, lp.getDone()), Integer.parseInt(lp.getDoneValue()), lp.getDoneDelay(), function, lp.getStart(), lp.getEnd(), lp.getStepSize(), moveTimeout);
|
||||
}
|
||||
|
||||
a.setAsynchronous(lp.isAsynchronous());
|
||||
@@ -760,7 +718,7 @@ public class Acquisition {
|
||||
if(name==null){
|
||||
name = lp.getName();
|
||||
}
|
||||
ChannelAccessDoubleSensor sensor = new ChannelAccessDoubleSensor(cservice, lp.getId(), name);
|
||||
ChannelAccessSensor<Double> sensor = new ChannelAccessSensor<Double>(lp.getId(), createChannel(Double.class, name), configModel.isFailOnSensorError());
|
||||
aLoop.getSensors().add(sensor);
|
||||
}
|
||||
else if (p instanceof ArrayPositioner){
|
||||
@@ -773,14 +731,14 @@ public class Acquisition {
|
||||
|
||||
ChannelAccessTableActuator<?> a;
|
||||
if(p.getType().equals("String")){
|
||||
a = new ChannelAccessTableActuator<String>(cservice, p.getName(), p.getDone(), p.getDoneValue(), p.getDoneDelay(), table, moveTimeout);
|
||||
a = new ChannelAccessTableActuator<String>(createChannel(Double.class, p.getName()), createChannel(String.class, p.getDone()), p.getDoneValue(), p.getDoneDelay(), table, moveTimeout);
|
||||
}
|
||||
else if(p.getType().equals("Double")){
|
||||
a = new ChannelAccessTableActuator<Double>(cservice, p.getName(), p.getDone(), Double.parseDouble(p.getDoneValue()), p.getDoneDelay(), table, moveTimeout);
|
||||
a = new ChannelAccessTableActuator<Double>(createChannel(Double.class, p.getName()), createChannel(Double.class, p.getDone()), Double.parseDouble(p.getDoneValue()), p.getDoneDelay(), table, moveTimeout);
|
||||
}
|
||||
else{
|
||||
// Default
|
||||
a = new ChannelAccessTableActuator<Integer>(cservice, p.getName(), p.getDone(), Integer.parseInt(p.getDoneValue()), p.getDoneDelay(), table, moveTimeout);
|
||||
a = new ChannelAccessTableActuator<Integer>(createChannel(Double.class, p.getName()), createChannel(Integer.class, p.getDone()), Integer.parseInt(p.getDoneValue()), p.getDoneDelay(), table, moveTimeout);
|
||||
}
|
||||
|
||||
a.setAsynchronous(p.isAsynchronous());
|
||||
@@ -793,7 +751,7 @@ public class Acquisition {
|
||||
if(name==null){
|
||||
name = ap.getName();
|
||||
}
|
||||
ChannelAccessDoubleSensor sensor = new ChannelAccessDoubleSensor(cservice, ap.getId(), name);
|
||||
ChannelAccessSensor<Double> sensor = new ChannelAccessSensor<Double>(ap.getId(), createChannel(Double.class, name), configModel.isFailOnSensorError());
|
||||
aLoop.getSensors().add(sensor);
|
||||
}
|
||||
else if (p instanceof RegionPositioner){
|
||||
@@ -826,14 +784,13 @@ public class Acquisition {
|
||||
// Create actuator
|
||||
ChannelAccessLinearActuator<?> act;
|
||||
if(rp.getType().equals("String")){
|
||||
act = new ChannelAccessLinearActuator<String>(cservice, rp.getName(), rp.getDone(), rp.getDoneValue(), rp.getDoneDelay(), start, r.getEnd(), r.getStepSize(), moveTimeout);
|
||||
act = new ChannelAccessLinearActuator<String>(createChannel(Double.class, rp.getName()), createChannel(String.class, rp.getDone()), rp.getDoneValue(), rp.getDoneDelay(), start, r.getEnd(), r.getStepSize(), moveTimeout);
|
||||
}
|
||||
else if(rp.getType().equals("Double")){
|
||||
act = new ChannelAccessLinearActuator<Double>(cservice, rp.getName(), rp.getDone(), Double.parseDouble(rp.getDoneValue()), rp.getDoneDelay(), start, r.getEnd(), r.getStepSize(), moveTimeout);
|
||||
act = new ChannelAccessLinearActuator<Double>(createChannel(Double.class, rp.getName()), createChannel(Double.class, rp.getDone()), Double.parseDouble(rp.getDoneValue()), rp.getDoneDelay(), start, r.getEnd(), r.getStepSize(), moveTimeout);
|
||||
}
|
||||
else{
|
||||
// Default
|
||||
act = new ChannelAccessLinearActuator<Integer>(cservice, rp.getName(), rp.getDone(), Integer.parseInt(rp.getDoneValue()), rp.getDoneDelay(), start, r.getEnd(), r.getStepSize(), moveTimeout);
|
||||
act = new ChannelAccessLinearActuator<Integer>(createChannel(Double.class, rp.getName()), createChannel(Integer.class, rp.getDone()), Integer.parseInt(rp.getDoneValue()), rp.getDoneDelay(), start, r.getEnd(), r.getStepSize(), moveTimeout);
|
||||
}
|
||||
|
||||
act.setAsynchronous(rp.isAsynchronous());
|
||||
@@ -854,14 +811,14 @@ public class Acquisition {
|
||||
JythonFunction function = mapFunction(r.getFunction());
|
||||
ChannelAccessFunctionActuator<?> act;
|
||||
if(rp.getType().equals("String")){
|
||||
act = new ChannelAccessFunctionActuator<String>(cservice, rp.getName(), rp.getDone(), rp.getDoneValue(), rp.getDoneDelay(), function, r.getStart(), r.getEnd(), r.getStepSize(), moveTimeout);
|
||||
act = new ChannelAccessFunctionActuator<String>(createChannel(Double.class,rp.getName()), createChannel(String.class,rp.getDone()), rp.getDoneValue(), rp.getDoneDelay(), function, r.getStart(), r.getEnd(), r.getStepSize(), moveTimeout);
|
||||
}
|
||||
else if(rp.getType().equals("Double")){
|
||||
act = new ChannelAccessFunctionActuator<Double>(cservice, rp.getName(), rp.getDone(), Double.parseDouble(rp.getDoneValue()), rp.getDoneDelay(), function, r.getStart(), r.getEnd(), r.getStepSize(), moveTimeout);
|
||||
act = new ChannelAccessFunctionActuator<Double>(createChannel(Double.class, rp.getName()), createChannel(Double.class, rp.getDone()), Double.parseDouble(rp.getDoneValue()), rp.getDoneDelay(), function, r.getStart(), r.getEnd(), r.getStepSize(), moveTimeout);
|
||||
}
|
||||
else{
|
||||
// Default
|
||||
act = new ChannelAccessFunctionActuator<Integer>(cservice, rp.getName(), rp.getDone(), Integer.parseInt(rp.getDoneValue()), rp.getDoneDelay(), function, r.getStart(), r.getEnd(), r.getStepSize(), moveTimeout);
|
||||
act = new ChannelAccessFunctionActuator<Integer>(createChannel(Double.class, rp.getName()), createChannel(Integer.class, rp.getDone()), Integer.parseInt(rp.getDoneValue()), rp.getDoneDelay(), function, r.getStart(), r.getEnd(), r.getStepSize(), moveTimeout);
|
||||
}
|
||||
|
||||
act.setAsynchronous(rp.isAsynchronous());
|
||||
@@ -881,7 +838,7 @@ public class Acquisition {
|
||||
if(name==null){
|
||||
name = rp.getName();
|
||||
}
|
||||
ChannelAccessDoubleSensor sensor = new ChannelAccessDoubleSensor(cservice, rp.getId(), name);
|
||||
ChannelAccessSensor<Double> sensor = new ChannelAccessSensor<Double>(rp.getId(), createChannel(Double.class, name), configModel.isFailOnSensorError());
|
||||
aLoop.getSensors().add(sensor);
|
||||
}
|
||||
else if(p instanceof PseudoPositioner){
|
||||
@@ -915,20 +872,17 @@ public class Acquisition {
|
||||
Guard g = dimension.getGuard();
|
||||
if(g != null){
|
||||
// Map conditions
|
||||
List<ChannelAccessGuardCondition> conditions = new ArrayList<ChannelAccessGuardCondition>();
|
||||
List<ChannelAccessGuardCondition<?>> conditions = new ArrayList<>();
|
||||
for(GuardCondition con: g.getCondition()){
|
||||
Object value = null;
|
||||
if(con.getType().equals("Integer")){
|
||||
value = new Integer(con.getValue());
|
||||
conditions.add(new ChannelAccessGuardCondition<Integer>(createChannel(Integer.class, con.getChannel()), new Integer(con.getValue())));
|
||||
}
|
||||
else if(con.getType().equals("Double")){
|
||||
value = new Double(con.getValue());
|
||||
conditions.add(new ChannelAccessGuardCondition<Double>(createChannel(Double.class, con.getChannel()), new Double(con.getValue())));
|
||||
}
|
||||
else{
|
||||
value = con.getValue();
|
||||
conditions.add(new ChannelAccessGuardCondition<String>(createChannel(String.class, con.getChannel()), con.getValue()));
|
||||
}
|
||||
|
||||
conditions.add(new ChannelAccessGuardCondition(cservice, con.getChannel(), value));
|
||||
}
|
||||
// Create guard and add to loop
|
||||
ChannelAccessGuard guard = new ChannelAccessGuard(conditions);
|
||||
@@ -955,12 +909,11 @@ public class Acquisition {
|
||||
*/
|
||||
private JythonFunction mapFunction(Function f){
|
||||
HashMap<String, JythonGlobalVariable> map = new HashMap<String, JythonGlobalVariable>();
|
||||
JythonGlobalVariableDictionary dict = JythonGlobalVariableDictionary.getInstance();
|
||||
for(ParameterMapping m: f.getMapping()){
|
||||
if(m instanceof VariableParameterMapping){
|
||||
VariableParameterMapping vp = (VariableParameterMapping)m;
|
||||
Variable v = (Variable)vp.getName();
|
||||
JythonGlobalVariable var = dict.getVariable(v.getName());
|
||||
JythonGlobalVariable var = jVariableDictionary.get(v.getName());
|
||||
var.setValue(v.getValue());
|
||||
map.put(vp.getVariable(), var);
|
||||
}
|
||||
@@ -979,10 +932,10 @@ public class Acquisition {
|
||||
// Add sensor
|
||||
Sensor sensor;
|
||||
if(sd.getType().equals("String")){
|
||||
sensor = new ChannelAccessStringSensor(cservice, sd.getId(), sd.getName());
|
||||
sensor = new ChannelAccessSensor<>(sd.getId(), createChannel(String.class,sd.getName()), configModel.isFailOnSensorError());
|
||||
}
|
||||
else{
|
||||
sensor = new ChannelAccessDoubleSensor(cservice, sd.getId(), sd.getName());
|
||||
sensor = new ChannelAccessSensor<>(sd.getId(), createChannel(Double.class,sd.getName()), configModel.isFailOnSensorError());
|
||||
}
|
||||
|
||||
aLoop.getSensors().add(sensor);
|
||||
@@ -994,7 +947,7 @@ public class Acquisition {
|
||||
aLoop.getPreSensorActions().addAll(mapActions(ad.getPreAction()));
|
||||
|
||||
// Ad sensor
|
||||
ChannelAccessDoubleArraySensor sensor = new ChannelAccessDoubleArraySensor(cservice, ad.getId(), ad.getName(), ad.getArraySize());
|
||||
Sensor sensor = new ChannelAccessSensor<>(ad.getId(), createChannel(double[].class, ad.getName(), ad.getArraySize()), configModel.isFailOnSensorError());
|
||||
aLoop.getSensors().add(sensor);
|
||||
}
|
||||
else if (detector instanceof DetectorOfDetectors){
|
||||
@@ -1012,7 +965,7 @@ public class Acquisition {
|
||||
Timestamp dd = (Timestamp) detector;
|
||||
|
||||
// Ad sensor
|
||||
MillisecondTimestampSensor sensor = new MillisecondTimestampSensor(dd.getId());
|
||||
TimestampSensor sensor = new TimestampSensor(dd.getId());
|
||||
aLoop.getSensors().add(sensor);
|
||||
}
|
||||
else{
|
||||
@@ -1037,7 +990,11 @@ public class Acquisition {
|
||||
// Create loop
|
||||
boolean zigZag = dimension.isZigzag(); // default value is false
|
||||
|
||||
OTFLoop actionLoop = new OTFLoop(cservice, configuration.getOtfChannelPrefix(), configuration.getOtfNfsServer(), configuration.getOtfNfsShare(), configuration.getOtfSmbShare(), zigZag);
|
||||
Map<String,String> macros = new HashMap<>();
|
||||
macros.put("PREFIX", configuration.getOtfChannelPrefix());
|
||||
TemplateOTF template = new TemplateOTF();
|
||||
createTemplateChannels(template, macros);
|
||||
OTFLoop actionLoop = new OTFLoop(template, configuration.getOtfNfsServer(), configuration.getOtfNfsShare(), configuration.getOtfSmbShare(), zigZag);
|
||||
|
||||
actionLoop.getPreActions().addAll(mapActions(dimension.getPreAction()));
|
||||
|
||||
@@ -1047,10 +1004,7 @@ public class Acquisition {
|
||||
if(p.getAdditionalBacklash()!=null){
|
||||
backlash = p.getAdditionalBacklash();
|
||||
}
|
||||
OTFActuator actor = new OTFActuator(p.getId(), p.getName(), p.getReadback(), p.getStart(), p.getEnd(), p.getStepSize(), p.getIntegrationTime(), backlash);
|
||||
actionLoop.setActor(actor);
|
||||
|
||||
actionLoop.getSensors().add(new OTFReadbackSensor(p.getId()));
|
||||
actionLoop.setActuator(p.getId(), p.getName(), p.getReadback(), p.getStart(), p.getEnd(), p.getStepSize(), p.getIntegrationTime(), backlash);
|
||||
|
||||
// Map sensors
|
||||
// ATTENTION: the sequence of the mapping depends on the sequence in the schema file !
|
||||
@@ -1072,7 +1026,7 @@ public class Acquisition {
|
||||
|
||||
Timestamp detector = dimension.getTimestamp();
|
||||
if(detector != null){
|
||||
actionLoop.getSensors().add(new MillisecondTimestampSensor(detector.getId()));
|
||||
actionLoop.getSensors().add(new TimestampSensor(detector.getId()));
|
||||
}
|
||||
|
||||
actionLoop.getPostActions().addAll(mapActions(dimension.getPostAction()));
|
||||
@@ -1107,24 +1061,23 @@ public class Acquisition {
|
||||
if(p.getAdditionalBacklash()!=null){
|
||||
backlash = p.getAdditionalBacklash();
|
||||
}
|
||||
OTFActuator actor = new OTFActuator(p.getId(), p.getName(), p.getReadback(), p.getStart(), p.getEnd(), p.getStepSize(), p.getIntegrationTime(), backlash);
|
||||
actionLoop.setActor(actor);
|
||||
actionLoop.setActuator(p.getId(), p.getName(), p.getReadback(), p.getStart(), p.getEnd(), p.getStepSize(), p.getIntegrationTime(), backlash);
|
||||
|
||||
// Map sensors
|
||||
// ATTENTION: the sequence of the mapping depends on the sequence in the schema file !
|
||||
for(SimpleScalarDetector detector: dimension.getDetector()){
|
||||
if(!detector.isScr()){
|
||||
actionLoop.getSensors().add(new OTFNamedChannelSensor(detector.getId(), detector.getName()));
|
||||
actionLoop.getSensors().add(new CrlogicResource(detector.getId(), detector.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
for(ScalerChannel detector: dimension.getScaler()){
|
||||
actionLoop.getSensors().add(new OTFScalerChannelSensor(detector.getId(), detector.getChannel()));
|
||||
actionLoop.getSensors().add(new CrlogicResource(detector.getId(), "SCALER"+detector.getChannel(), true));
|
||||
}
|
||||
|
||||
Timestamp tdetector = dimension.getTimestamp();
|
||||
if(tdetector != null){
|
||||
actionLoop.getSensors().add(new MillisecondTimestampSensor(tdetector.getId()));
|
||||
actionLoop.getSensors().add(new CrlogicResource(tdetector.getId(), "TIMESTAMP"));
|
||||
}
|
||||
|
||||
actionLoop.getPostActions().addAll(mapActions(dimension.getPostAction()));
|
||||
@@ -1139,14 +1092,17 @@ public class Acquisition {
|
||||
aLoop = actionLoop;
|
||||
}
|
||||
else{
|
||||
List<Sensor> sensors = new ArrayList<Sensor>();
|
||||
List<Channel<DoubleTimestamp>> sensors = new ArrayList<>();
|
||||
List<String> ids = new ArrayList<>();
|
||||
|
||||
for(SimpleScalarDetector detector: dimension.getDetector()){
|
||||
if(detector.isScr()){
|
||||
sensors.add(new ChannelAccessDoubleSensor(cservice, detector.getId(), detector.getName()));
|
||||
ids.add(detector.getId());
|
||||
sensors.add(createChannel(DoubleTimestamp.class, detector.getName()));
|
||||
}
|
||||
}
|
||||
// Create soft(ware) based crlogic
|
||||
ScrlogicLoop scrlogic = new ScrlogicLoop(cservice, sensors);
|
||||
ScrlogicLoop scrlogic = new ScrlogicLoop(ids, sensors);
|
||||
|
||||
// Create parallel logic
|
||||
ParallelCrlogic pcrlogic = new ParallelCrlogic(actionLoop, scrlogic);
|
||||
@@ -1159,4 +1115,51 @@ public class Acquisition {
|
||||
return aLoop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create channel and remember to be able to destroy channels at the end
|
||||
* @param name
|
||||
* @param type
|
||||
* @return null if the name of the channel is null, otherwise the channel
|
||||
*/
|
||||
private <T> Channel<T> createChannel(Class<T> type, String name){
|
||||
try {
|
||||
if(name== null){
|
||||
return null;
|
||||
}
|
||||
|
||||
Channel<T> c = cservice.createChannel(new ChannelDescriptor<T>(type, name) );
|
||||
channels.add(c);
|
||||
return c;
|
||||
} catch (ChannelException | InterruptedException | TimeoutException e) {
|
||||
throw new RuntimeException("Unable to create channel: "+name,e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private <T> Channel<T> createChannel(Class<T> type, String name, int size){
|
||||
try {
|
||||
if(name== null){
|
||||
return null;
|
||||
}
|
||||
|
||||
Channel<T> c = cservice.createChannel(new ChannelDescriptor<T>(type, name, false, size) );
|
||||
channels.add(c);
|
||||
return c;
|
||||
} catch (ChannelException | InterruptedException | TimeoutException e) {
|
||||
throw new RuntimeException("Unable to create channel: "+name,e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void createTemplateChannels(Object o, Map<String,String> macro){
|
||||
try {
|
||||
cservice.createAnnotatedChannels(o, macro);
|
||||
templates.add(o);
|
||||
} catch (ChannelException | InterruptedException | TimeoutException e) {
|
||||
throw new RuntimeException("Unable to initialize template: "+o.getClass().getName(),e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -35,11 +35,12 @@ import ch.psi.fda.install.ApplicationConfigurator;
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class AcquisitionEngineConfiguration {
|
||||
public class AcquisitionConfiguration {
|
||||
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AcquisitionEngineConfiguration.class.getName());
|
||||
private static final AcquisitionEngineConfiguration instance = new AcquisitionEngineConfiguration();
|
||||
private static final Logger logger = Logger.getLogger(AcquisitionConfiguration.class.getName());
|
||||
|
||||
public final static String FDA_CONFIG_FILE = "ch.psi.fda.config.file";
|
||||
|
||||
private String otfChannelPrefix;
|
||||
private String otfNfsServer;
|
||||
@@ -70,37 +71,37 @@ public class AcquisitionEngineConfiguration {
|
||||
|
||||
private String smptServer;
|
||||
|
||||
|
||||
/**
|
||||
* Default Constructor
|
||||
* The constructor will read the configuration from the /fda.properties file (resource) located in the classpath.
|
||||
*/
|
||||
private AcquisitionEngineConfiguration(){
|
||||
public AcquisitionConfiguration(){
|
||||
loadConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get instance of this configuration
|
||||
* @return configuration
|
||||
*/
|
||||
public static AcquisitionEngineConfiguration getInstance(){
|
||||
return(instance);
|
||||
|
||||
public void loadConfiguration(){
|
||||
loadConfiguration(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load configuration from properties file
|
||||
*/
|
||||
private void loadConfiguration() {
|
||||
String config = System.getProperty(ApplicationConfigurator.FDA_CONFIG_FILE_ARGUMENT);
|
||||
|
||||
public void loadConfiguration(String file) {
|
||||
if(file == null){
|
||||
file = System.getProperty(FDA_CONFIG_FILE);
|
||||
}
|
||||
Properties properties = new Properties();
|
||||
|
||||
if(config != null){
|
||||
// Only read in the property file if a file is specified
|
||||
if(file != null){
|
||||
try {
|
||||
properties.load(new FileReader(config));
|
||||
properties.load(new FileReader(file));
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException("Configuration file "+config+" not found", e);
|
||||
throw new RuntimeException("Configuration file "+file+" not found", e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Cannot read configuration file "+config, e);
|
||||
throw new RuntimeException("Cannot read configuration file "+file, e);
|
||||
}
|
||||
}
|
||||
else{
|
||||
@@ -108,125 +109,38 @@ public class AcquisitionEngineConfiguration {
|
||||
}
|
||||
|
||||
// The defaults are set here
|
||||
otfChannelPrefix = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.channelPrefix", "");
|
||||
otfScalerPrefix = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.scalerPrefix", "");
|
||||
otfNfsServer = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.nfsServer", "");
|
||||
otfNfsShare = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.nfsShare", "");
|
||||
otfSmbShare = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.smbShare", "");
|
||||
otfUseCrlogic = new Boolean(properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.useCrlogic", "false"));
|
||||
otfCrlogicPrefix = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.crlogicPrefix", "");
|
||||
otfCrlogicKeepTmpFiles = new Boolean(properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".otf.crlogicKeepTmpFiles", "false"));
|
||||
otfChannelPrefix = properties.getProperty(AcquisitionConfiguration.class.getPackage().getName()+".otf.channelPrefix", "");
|
||||
otfScalerPrefix = properties.getProperty(AcquisitionConfiguration.class.getPackage().getName()+".otf.scalerPrefix", "");
|
||||
otfNfsServer = properties.getProperty(AcquisitionConfiguration.class.getPackage().getName()+".otf.nfsServer", "");
|
||||
otfNfsShare = properties.getProperty(AcquisitionConfiguration.class.getPackage().getName()+".otf.nfsShare", "");
|
||||
otfSmbShare = properties.getProperty(AcquisitionConfiguration.class.getPackage().getName()+".otf.smbShare", "");
|
||||
|
||||
// Workaround
|
||||
// dataBaseDirectory = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".data.baseDirectory", ".");
|
||||
if(System.getProperty(ApplicationConfigurator.FDA_HOME_ARGUMENT)!=null){
|
||||
otfUseCrlogic = new Boolean(properties.getProperty(AcquisitionConfiguration.class.getPackage().getName()+".otf.useCrlogic", "false"));
|
||||
otfCrlogicPrefix = properties.getProperty(AcquisitionConfiguration.class.getPackage().getName()+".otf.crlogicPrefix", "");
|
||||
otfCrlogicKeepTmpFiles = new Boolean(properties.getProperty(AcquisitionConfiguration.class.getPackage().getName()+".otf.crlogicKeepTmpFiles", "false"));
|
||||
|
||||
if(System.getProperty(ApplicationConfigurator.FDA_HOME_ARGUMENT)!=null){ // TODO remove
|
||||
dataBaseDirectory = System.getProperty(ApplicationConfigurator.FDA_HOME_ARGUMENT)+"/data";
|
||||
}
|
||||
else{
|
||||
dataBaseDirectory = "./data";
|
||||
}
|
||||
|
||||
dataFilePrefix = properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".data.filePrefix","");
|
||||
dataFilePrefix = properties.getProperty(AcquisitionConfiguration.class.getPackage().getName()+".data.filePrefix","");
|
||||
|
||||
actorMoveTimeout = new Long(properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".actorMoveTimeout","600000"));
|
||||
actorMoveTimeout = new Long(properties.getProperty(AcquisitionConfiguration.class.getPackage().getName()+".actorMoveTimeout","600000"));
|
||||
|
||||
smptServer= properties.getProperty(AcquisitionEngineConfiguration.class.getPackage().getName()+".notification.host","mail.psi.ch");
|
||||
smptServer= properties.getProperty(AcquisitionConfiguration.class.getPackage().getName()+".notification.host","mail.psi.ch");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload this configuration from the corresponding properties file
|
||||
* @throws IOException
|
||||
* Replace ${name} and ${date} macro given string
|
||||
* @param string
|
||||
* @param date
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public void reloadConfiguration() throws IOException{
|
||||
loadConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the otfChannelPrefix
|
||||
*/
|
||||
public String getOtfChannelPrefix() {
|
||||
return otfChannelPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the otfScalerPrefix
|
||||
*/
|
||||
public String getOtfScalerPrefix() {
|
||||
return otfScalerPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the otfNfsServer
|
||||
*/
|
||||
public String getOtfNfsServer() {
|
||||
return otfNfsServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the otfNfsShare
|
||||
*/
|
||||
public String getOtfNfsShare() {
|
||||
return otfNfsShare;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the otfSmbShare
|
||||
*/
|
||||
public String getOtfSmbShare() {
|
||||
return otfSmbShare;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the otfUseCrlogic
|
||||
*/
|
||||
public boolean isOtfUseCrlogic() {
|
||||
return otfUseCrlogic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dataBaseDirectory
|
||||
*/
|
||||
public String getDataBaseDirectory() {
|
||||
return dataBaseDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dataFilePrefix
|
||||
*/
|
||||
public String getDataFilePrefix() {
|
||||
return dataFilePrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the smptServer
|
||||
*/
|
||||
public String getSmptServer() {
|
||||
return smptServer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the otfCrlogicPrefix
|
||||
*/
|
||||
public String getOtfCrlogicPrefix() {
|
||||
return otfCrlogicPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the otfCrlogicKeepTmpFiles
|
||||
*/
|
||||
public boolean isOtfCrlogicKeepTmpFiles() {
|
||||
return otfCrlogicKeepTmpFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the actorMoveTimeout
|
||||
*/
|
||||
public Long getActorMoveTimeout() {
|
||||
return actorMoveTimeout;
|
||||
}
|
||||
|
||||
public String replaceMacros(String string, Date date, String name){
|
||||
String newString = string;
|
||||
|
||||
@@ -248,50 +162,100 @@ public class AcquisitionEngineConfiguration {
|
||||
return newString;
|
||||
}
|
||||
|
||||
// Getter and setter functions
|
||||
|
||||
public String getOtfChannelPrefix() {
|
||||
return otfChannelPrefix;
|
||||
}
|
||||
|
||||
public void setOtfChannelPrefix(String otfChannelPrefix) {
|
||||
this.otfChannelPrefix = otfChannelPrefix;
|
||||
}
|
||||
|
||||
public String getOtfNfsServer() {
|
||||
return otfNfsServer;
|
||||
}
|
||||
|
||||
public void setOtfNfsServer(String otfNfsServer) {
|
||||
this.otfNfsServer = otfNfsServer;
|
||||
}
|
||||
|
||||
public String getOtfNfsShare() {
|
||||
return otfNfsShare;
|
||||
}
|
||||
|
||||
public void setOtfNfsShare(String otfNfsShare) {
|
||||
this.otfNfsShare = otfNfsShare;
|
||||
}
|
||||
|
||||
public String getOtfSmbShare() {
|
||||
return otfSmbShare;
|
||||
}
|
||||
|
||||
public void setOtfSmbShare(String otfSmbShare) {
|
||||
this.otfSmbShare = otfSmbShare;
|
||||
}
|
||||
|
||||
public String getOtfScalerPrefix() {
|
||||
return otfScalerPrefix;
|
||||
}
|
||||
|
||||
public void setOtfScalerPrefix(String otfScalerPrefix) {
|
||||
this.otfScalerPrefix = otfScalerPrefix;
|
||||
}
|
||||
|
||||
public boolean isOtfUseCrlogic() {
|
||||
return otfUseCrlogic;
|
||||
}
|
||||
|
||||
public void setOtfUseCrlogic(boolean otfUseCrlogic) {
|
||||
this.otfUseCrlogic = otfUseCrlogic;
|
||||
}
|
||||
|
||||
public String getOtfCrlogicPrefix() {
|
||||
return otfCrlogicPrefix;
|
||||
}
|
||||
|
||||
public void setOtfCrlogicPrefix(String otfCrlogicPrefix) {
|
||||
this.otfCrlogicPrefix = otfCrlogicPrefix;
|
||||
}
|
||||
|
||||
public boolean isOtfCrlogicKeepTmpFiles() {
|
||||
return otfCrlogicKeepTmpFiles;
|
||||
}
|
||||
|
||||
public void setOtfCrlogicKeepTmpFiles(boolean otfCrlogicKeepTmpFiles) {
|
||||
this.otfCrlogicKeepTmpFiles = otfCrlogicKeepTmpFiles;
|
||||
}
|
||||
|
||||
public String getDataBaseDirectory() {
|
||||
return dataBaseDirectory;
|
||||
}
|
||||
|
||||
public void setDataBaseDirectory(String dataBaseDirectory) {
|
||||
this.dataBaseDirectory = dataBaseDirectory;
|
||||
}
|
||||
|
||||
public String getDataFilePrefix() {
|
||||
return dataFilePrefix;
|
||||
}
|
||||
|
||||
public void setDataFilePrefix(String dataFilePrefix) {
|
||||
this.dataFilePrefix = dataFilePrefix;
|
||||
}
|
||||
|
||||
public Long getActorMoveTimeout() {
|
||||
return actorMoveTimeout;
|
||||
}
|
||||
|
||||
public void setActorMoveTimeout(Long actorMoveTimeout) {
|
||||
this.actorMoveTimeout = actorMoveTimeout;
|
||||
}
|
||||
|
||||
public String getSmptServer() {
|
||||
return smptServer;
|
||||
}
|
||||
|
||||
public void setSmptServer(String smptServer) {
|
||||
this.smptServer = smptServer;
|
||||
}
|
||||
102
ch.psi.fda/src/main/java/ch/psi/fda/aq/Collector.java
Normal file
102
ch.psi.fda/src/main/java/ch/psi/fda/aq/Collector.java
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.aq;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.Metadata;
|
||||
import ch.psi.fda.core.messages.StreamDelimiterMessage;
|
||||
import ch.psi.fda.core.messages.EndOfStreamMessage;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
|
||||
/**
|
||||
* Collector class that is collecting and merging data from different Queues.
|
||||
*/
|
||||
public class Collector {
|
||||
|
||||
private EventBus bus;
|
||||
private List<MessageListener> listeners = new ArrayList<>();
|
||||
|
||||
private List<Metadata> metadata;
|
||||
private boolean first = true;
|
||||
|
||||
public Collector(EventBus b){
|
||||
this.bus = b;
|
||||
}
|
||||
|
||||
public void addEventBus(EventBus b){
|
||||
MessageListener l = new MessageListener();
|
||||
listeners.add(l);
|
||||
b.register(l);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private class MessageListener{
|
||||
|
||||
private DataMessage message;
|
||||
|
||||
@Subscribe
|
||||
public void onMessage(Message message){
|
||||
int level = listeners.indexOf(this);
|
||||
if(message instanceof DataMessage){
|
||||
this.message = (DataMessage) message;
|
||||
|
||||
if(level==0){
|
||||
if(first){
|
||||
metadata = new ArrayList<>();
|
||||
for(int i=listeners.size()-1;i>=0;i--){
|
||||
// Correct/Add dimension information
|
||||
for(Metadata m: listeners.get(i).getMessage().getMetadata()){
|
||||
m.setDimension(i);
|
||||
}
|
||||
metadata.addAll(listeners.get(i).getMessage().getMetadata());
|
||||
}
|
||||
|
||||
}
|
||||
DataMessage m = new DataMessage(metadata);
|
||||
for(int i=listeners.size()-1;i>=0;i--){
|
||||
m.getData().addAll(listeners.get(i).getMessage().getData());
|
||||
}
|
||||
bus.post(m);
|
||||
}
|
||||
}
|
||||
if(message instanceof EndOfStreamMessage){
|
||||
|
||||
StreamDelimiterMessage ddm = new StreamDelimiterMessage(level, ((EndOfStreamMessage)message).isIflag());
|
||||
bus.post(ddm);
|
||||
if(level==(listeners.size()-1)){ // if highest dimension then send end of stream
|
||||
bus.post(new EndOfStreamMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DataMessage getMessage(){
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
77
ch.psi.fda/src/main/java/ch/psi/fda/aq/Manipulator.java
Normal file
77
ch.psi.fda/src/main/java/ch/psi/fda/aq/Manipulator.java
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.aq;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import ch.psi.fda.core.Manipulation;
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
import ch.psi.fda.core.messages.Metadata;
|
||||
|
||||
/**
|
||||
* Applies manipulations to the data stream
|
||||
*/
|
||||
public class Manipulator {
|
||||
|
||||
private EventBus bus;
|
||||
|
||||
private final List<Manipulation> manipulations;
|
||||
private boolean first = true;
|
||||
private List<Metadata> metadata = new ArrayList<>();
|
||||
|
||||
public Manipulator(EventBus b, List<Manipulation> manipulations){
|
||||
this.bus = b;
|
||||
this.manipulations = manipulations;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMessage(Message message){
|
||||
if(message instanceof DataMessage){
|
||||
if(first){
|
||||
first=false;
|
||||
|
||||
metadata.addAll(((DataMessage) message).getMetadata());
|
||||
|
||||
for(Manipulation manipulation: this.manipulations){
|
||||
manipulation.initialize(this.metadata);
|
||||
|
||||
// Add manipulation id to metadata
|
||||
this.metadata.add(new Metadata(manipulation.getId(),0)); // Calculated component always belongs to lowes dimension
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DataMessage dm = (DataMessage) message;
|
||||
// message = new DataMessage(metadata);
|
||||
for(Manipulation manipulation: manipulations){
|
||||
// ((DataMessage)message).getData().add(manipulation.execute(dm));
|
||||
dm.getData().add(manipulation.execute(dm));
|
||||
}
|
||||
// Need to update the metadata of the message
|
||||
dm.setMetadata(this.metadata);
|
||||
}
|
||||
bus.post(message);
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ch.psi.fda.notification;
|
||||
package ch.psi.fda.aq;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -32,9 +32,7 @@ import javax.mail.internet.MimeMessage;
|
||||
import ch.psi.fda.model.v1.Recipient;
|
||||
|
||||
/**
|
||||
* This is a copy of the NotificationAgent class that should go into the foundation classes
|
||||
* This actually should be extracted to an own project
|
||||
* @author ebner
|
||||
* Agent to send out notifications to specified recipients.
|
||||
*/
|
||||
public class NotificationAgent {
|
||||
|
||||
@@ -55,7 +53,6 @@ public class NotificationAgent {
|
||||
fromAddress = from;
|
||||
|
||||
properties = new Properties();
|
||||
// Setup mail server
|
||||
properties.put("mail.smtp.host", host);
|
||||
}
|
||||
|
||||
271
ch.psi.fda/src/main/java/ch/psi/fda/aq/VisualizationMapper.java
Normal file
271
ch.psi.fda/src/main/java/ch/psi/fda/aq/VisualizationMapper.java
Normal file
@@ -0,0 +1,271 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.aq;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ch.psi.fda.model.v1.ArrayDetector;
|
||||
import ch.psi.fda.model.v1.ContinuousPositioner;
|
||||
import ch.psi.fda.model.v1.Detector;
|
||||
import ch.psi.fda.model.v1.LinearPositioner;
|
||||
import ch.psi.fda.model.v1.Positioner;
|
||||
import ch.psi.fda.model.v1.PseudoPositioner;
|
||||
import ch.psi.fda.model.v1.Visualization;
|
||||
import ch.psi.fda.visualizer.SeriesDataFilter;
|
||||
import ch.psi.fda.visualizer.XYSeriesArrayDataFilter;
|
||||
import ch.psi.fda.visualizer.XYSeriesDataFilter;
|
||||
import ch.psi.fda.visualizer.XYZSeriesArrayDataFilter;
|
||||
import ch.psi.fda.visualizer.XYZSeriesDataFilter;
|
||||
import ch.psi.plot.xyz.MatrixPlot;
|
||||
import ch.psi.plot.xyz.MatrixPlotData;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class VisualizationMapper {
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve id string of the passed object
|
||||
* @param object
|
||||
* @return Id string of object
|
||||
*/
|
||||
private static String getId(Object object){
|
||||
String id;
|
||||
if(object instanceof Positioner){
|
||||
id = ((Positioner)object).getId();
|
||||
}
|
||||
else if (object instanceof Detector){
|
||||
id = ((Detector)object).getId();
|
||||
}
|
||||
else if (object instanceof ch.psi.fda.model.v1.Manipulation){
|
||||
id = ((ch.psi.fda.model.v1.Manipulation)object).getId();
|
||||
}
|
||||
// For testing purposes
|
||||
else if(object instanceof String){
|
||||
id = (String) object;
|
||||
}
|
||||
else{
|
||||
throw new RuntimeException("Unable to identify id of object reference "+object);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public static List<SeriesDataFilter> mapVisualizations(List<Visualization> vl){
|
||||
List<SeriesDataFilter> filters = new ArrayList<SeriesDataFilter>();
|
||||
|
||||
for(Visualization v: vl){
|
||||
if(v instanceof ch.psi.fda.model.v1.LinePlot){
|
||||
ch.psi.fda.model.v1.LinePlot lp = (ch.psi.fda.model.v1.LinePlot) v;
|
||||
|
||||
// Create plot for visualization
|
||||
ch.psi.plot.xy.LinePlot plot = new ch.psi.plot.xy.LinePlot(lp.getTitle());
|
||||
|
||||
// Create data filter for visualization
|
||||
String idX = getId(lp.getX());
|
||||
|
||||
List<Object> l = lp.getY();
|
||||
for(Object o: l){
|
||||
String idY = getId(o);
|
||||
XYSeriesDataFilter filter = new XYSeriesDataFilter(idX, idY, plot);
|
||||
filter.setSeriesName(idY);
|
||||
filters.add(filter);
|
||||
}
|
||||
}
|
||||
else if(v instanceof ch.psi.fda.model.v1.LinePlotArray){
|
||||
// Array visualization
|
||||
ch.psi.fda.model.v1.LinePlotArray lp = (ch.psi.fda.model.v1.LinePlotArray) v;
|
||||
|
||||
// Create plot for visualization
|
||||
ch.psi.plot.xy.LinePlot plot = new ch.psi.plot.xy.LinePlot(lp.getTitle());
|
||||
|
||||
// Create data filter for visualization
|
||||
List<Object> l = lp.getY();
|
||||
for(Object o: l){
|
||||
String idY = getId(o);
|
||||
|
||||
XYSeriesArrayDataFilter filter = new XYSeriesArrayDataFilter(idY, plot);
|
||||
filter.setMaxSeries(lp.getMaxSeries()*lp.getY().size()); // Workaround - keep for each array max series
|
||||
filter.setOffset(lp.getOffset());
|
||||
filter.setSize(lp.getSize());
|
||||
filter.setSeriesName(idY);
|
||||
filters.add(filter);
|
||||
}
|
||||
}
|
||||
else if(v instanceof ch.psi.fda.model.v1.MatrixPlot){
|
||||
|
||||
// MatrixPlot does currently not support RegionPositioners because of the
|
||||
// plotting problems this would cause. If regions of the positioner have different
|
||||
// step sizes it is not easily possible (without (specialized) rasterization) to plot the data.
|
||||
|
||||
ch.psi.fda.model.v1.MatrixPlot mp = (ch.psi.fda.model.v1.MatrixPlot) v;
|
||||
|
||||
|
||||
double minX, maxX;
|
||||
int nX;
|
||||
double minY, maxY;
|
||||
int nY;
|
||||
|
||||
String idX, idY, idZ;
|
||||
|
||||
// X Axis
|
||||
if(mp.getX() instanceof LinearPositioner){
|
||||
LinearPositioner linp = ((LinearPositioner)mp.getX());
|
||||
idX = linp.getId();
|
||||
|
||||
minX = (Math.min(linp.getStart(), linp.getEnd()));
|
||||
maxX = (Math.max(linp.getStart(), linp.getEnd()));
|
||||
nX = ((int) Math.floor((Math.abs(maxX-minX))/linp.getStepSize()) + 1);
|
||||
}
|
||||
else if(mp.getX() instanceof PseudoPositioner){
|
||||
PseudoPositioner pp = ((PseudoPositioner)mp.getX());
|
||||
idX = pp.getId();
|
||||
minX = (1); // Count starts at 1
|
||||
maxX = (pp.getCounts());
|
||||
nX = (pp.getCounts());
|
||||
}
|
||||
else if(mp.getX() instanceof ContinuousPositioner){
|
||||
ContinuousPositioner conp = ((ContinuousPositioner)mp.getX());
|
||||
idX = conp.getId();
|
||||
|
||||
minX = (Math.min(conp.getStart(), conp.getEnd()));
|
||||
maxX = (Math.max(conp.getStart(), conp.getEnd()));
|
||||
nX = ((int) Math.floor((Math.abs(maxX-minX))/conp.getStepSize()) + 1);
|
||||
}
|
||||
else{
|
||||
// Fail as we cannot determine the min, max and number of steps
|
||||
throw new RuntimeException(mp.getX().getClass().getName()+" is not supported as x-axis of a MatrixPlot");
|
||||
}
|
||||
|
||||
// Y Axis
|
||||
if(mp.getY() instanceof LinearPositioner){
|
||||
LinearPositioner linp = ((LinearPositioner)mp.getY());
|
||||
idY = linp.getId();
|
||||
minY = (Math.min(linp.getStart(), linp.getEnd()));
|
||||
maxY = (Math.max(linp.getStart(), linp.getEnd()));
|
||||
nY = ((int) Math.floor((Math.abs(maxY-minY))/linp.getStepSize()) + 1);
|
||||
}
|
||||
else if(mp.getY() instanceof PseudoPositioner){
|
||||
PseudoPositioner pp = ((PseudoPositioner)mp.getY());
|
||||
idY = pp.getId();
|
||||
minY = (1); // Count starts at 1
|
||||
maxY = (pp.getCounts());
|
||||
nY = (pp.getCounts());
|
||||
}
|
||||
else{
|
||||
// Fail as we cannot determine the min, max and number of steps
|
||||
throw new RuntimeException(mp.getY().getClass().getName()+" is not supported as y-axis of a MatrixPlot");
|
||||
}
|
||||
|
||||
// Z Dimension
|
||||
idZ = getId(mp.getZ());
|
||||
|
||||
// Create plot for visualization
|
||||
MatrixPlotData data = new MatrixPlotData(minX, maxX, nX, minY, maxY, nY);
|
||||
MatrixPlot plot = new MatrixPlot(mp.getTitle(), data);
|
||||
|
||||
XYZSeriesDataFilter filter = new XYZSeriesDataFilter(idX, idY, idZ, plot);
|
||||
filters.add(filter);
|
||||
}
|
||||
else if(v instanceof ch.psi.fda.model.v1.MatrixPlotArray){
|
||||
// Support for 2D waveform plots
|
||||
ch.psi.fda.model.v1.MatrixPlotArray mp = (ch.psi.fda.model.v1.MatrixPlotArray) v;
|
||||
|
||||
// Get size of the array detector
|
||||
int arraySize = 0;
|
||||
Object o = mp.getZ();
|
||||
if(o instanceof ArrayDetector){
|
||||
ArrayDetector ad = (ArrayDetector) o;
|
||||
arraySize = ad.getArraySize();
|
||||
}
|
||||
else{
|
||||
// Workaround
|
||||
arraySize = mp.getSize(); // of array is from a manipulation the size is not known. Then the size will indicate the size of the array to display
|
||||
}
|
||||
|
||||
int offset = mp.getOffset();
|
||||
// Determine size for array
|
||||
int size = mp.getSize();
|
||||
if(size>0 && offset+size<arraySize){
|
||||
size = mp.getSize();
|
||||
}
|
||||
else{
|
||||
size=arraySize-offset;
|
||||
}
|
||||
|
||||
|
||||
double minY, maxY;
|
||||
int nY;
|
||||
|
||||
double minX = offset;
|
||||
double maxX = offset+size-1;
|
||||
int nX = size;
|
||||
|
||||
String idY, idZ;
|
||||
|
||||
// Y Axis
|
||||
if(mp.getY() instanceof LinearPositioner){
|
||||
LinearPositioner linp = ((LinearPositioner)mp.getY());
|
||||
idY = linp.getId();
|
||||
|
||||
minY = (Math.min(linp.getStart(), linp.getEnd()));
|
||||
maxY = (Math.max(linp.getStart(), linp.getEnd()));
|
||||
nY = ((int) Math.floor((Math.abs(maxY-minY))/linp.getStepSize()) + 1);
|
||||
}
|
||||
else if(mp.getY() instanceof PseudoPositioner){
|
||||
PseudoPositioner pp = ((PseudoPositioner)mp.getY());
|
||||
idY = pp.getId();
|
||||
minY = (1); // Count starts at 1
|
||||
maxY = (pp.getCounts());
|
||||
nY = (pp.getCounts());
|
||||
}
|
||||
else if(mp.getY() instanceof ContinuousPositioner){
|
||||
ContinuousPositioner conp = ((ContinuousPositioner)mp.getY());
|
||||
idY = conp.getId();
|
||||
|
||||
minY = (Math.min(conp.getStart(), conp.getEnd()));
|
||||
maxY = (Math.max(conp.getStart(), conp.getEnd()));
|
||||
nY = ((int) Math.floor((Math.abs(maxY-minY))/conp.getStepSize()) + 1);
|
||||
}
|
||||
else{
|
||||
// Fail as we cannot determine the min, max and number of steps
|
||||
throw new RuntimeException(mp.getY().getClass().getName()+" is not supported as x-axis of a MatrixPlot");
|
||||
}
|
||||
|
||||
|
||||
// Z Dimension
|
||||
idZ = getId(mp.getZ());
|
||||
|
||||
// Create plot for visualization
|
||||
MatrixPlotData data = new MatrixPlotData(minX, maxX, nX, minY, maxY, nY);
|
||||
MatrixPlot plot = new MatrixPlot(mp.getTitle(), data);
|
||||
|
||||
XYZSeriesArrayDataFilter filter = new XYZSeriesArrayDataFilter(idY, idZ, offset, size, plot);
|
||||
filters.add(filter);
|
||||
}
|
||||
else{
|
||||
// Visualization type (currently) not supported
|
||||
throw new RuntimeException(v.getClass().getName()+" is not supported as visualization type");
|
||||
}
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.aq.ng;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import ch.psi.fda.aq.ng.rdescriptors.ProbeDescriptor;
|
||||
import ch.psi.fda.aq.ng.rdescriptors.ShellDescriptor;
|
||||
import ch.psi.fda.aq.ng.resources.ChannelProbeResource;
|
||||
import ch.psi.fda.aq.ng.resources.ShellResource;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class AcquisitionEngineNG {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AcquisitionEngineNG.class.getName());
|
||||
|
||||
private ChannelService cservice;
|
||||
private BlockingQueue<Message> outQueue;
|
||||
|
||||
public AcquisitionEngineNG(ChannelService cservice) {
|
||||
this.cservice = cservice;
|
||||
this.outQueue = new LinkedBlockingQueue<Message>(1000); // Create bounded queue to prevent running out of memory ...
|
||||
|
||||
// Workaround for Jython memory leak
|
||||
// http://blog.hillbrecht.de/2009/07/11/jython-memory-leakout-of-memory-problem/
|
||||
System.setProperty("python.options.internalTablesImpl", "weak");
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the specified script/logic while using the specified resources and paramters
|
||||
* @param resourceDescriptors
|
||||
* @param script
|
||||
* @param parameter
|
||||
*/
|
||||
public void execute(Map<String, ?> resourceDescriptors, String script, List<String> parameter){
|
||||
|
||||
// TODO Remove debugging messages
|
||||
// For debugging purpose only
|
||||
logger.info("Resources to create: "+resourceDescriptors);
|
||||
logger.info("Script to execute: "+script);
|
||||
|
||||
try {
|
||||
ScriptEngine engine = new ScriptEngineManager().getEngineByName("python");
|
||||
|
||||
// Set logger
|
||||
engine.put("logger", logger);
|
||||
|
||||
// Set parameters
|
||||
engine.put("parameter", parameter);
|
||||
|
||||
// Create/retrieve and set resources
|
||||
Map<String,?> resources = createResources(resourceDescriptors);
|
||||
engine.put("resources", resources);
|
||||
for(String k: resources.keySet()){ // For convenience make resources also available as variable named by the resource id
|
||||
engine.put(k, resources.get(k));
|
||||
}
|
||||
|
||||
// Execute script
|
||||
engine.eval(script);
|
||||
|
||||
|
||||
} catch (ScriptException e) {
|
||||
logger.info(e.getMessage());
|
||||
throw new RuntimeException("Action failed while executing the Jython script",e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create resources based on the passed rDescriptors
|
||||
* Supported descriptor types are:
|
||||
* ChannelDescriptor, ShellDescriptor, ProbeDescriptor
|
||||
*
|
||||
* @param resourceDescriptors
|
||||
* @return
|
||||
*/
|
||||
private Map<String,?> createResources(Map<String, ?> resourceDescriptors){
|
||||
Map<String,Object> resources = new HashMap<>();
|
||||
for(String k: resourceDescriptors.keySet()){
|
||||
if(resourceDescriptors.get(k) instanceof ChannelDescriptor){
|
||||
ChannelDescriptor<?> descriptor = (ChannelDescriptor<?>)resourceDescriptors.get(k);
|
||||
try {
|
||||
resources.put(k, cservice.createChannel(descriptor));
|
||||
// engine.put(k, cservice.createChannel(descriptor));
|
||||
} catch (ChannelException | InterruptedException | TimeoutException e) {
|
||||
throw new RuntimeException("Unable to create resource for channel: "+descriptor.getName(),e);
|
||||
}
|
||||
}
|
||||
else if(resourceDescriptors.get(k) instanceof ShellDescriptor){
|
||||
resources.put(k, new ShellResource());
|
||||
// engine.put(k, new ShellResource());
|
||||
}
|
||||
else if(resourceDescriptors.get(k) instanceof ProbeDescriptor){
|
||||
ProbeDescriptor descriptor = (ProbeDescriptor) resourceDescriptors.get(k);
|
||||
List<Channel<?>> channels = new ArrayList<>();
|
||||
|
||||
for(ChannelDescriptor<?> s: descriptor.getSensors()){
|
||||
try {
|
||||
channels.add(cservice.createChannel(s));
|
||||
|
||||
} catch (ChannelException | InterruptedException | TimeoutException e) {
|
||||
throw new RuntimeException("Unable to create resource for channel: "+s.getName(),e);
|
||||
}
|
||||
}
|
||||
// TODO Remove workaround ...
|
||||
resources.put(k, new ChannelProbeResource(channels, outQueue)); // Configure the probe to use the acquisitions out queue for writing data into
|
||||
// engine.put(k, new ChannelProbeResource(channels, outQueue));
|
||||
}
|
||||
else{
|
||||
throw new RuntimeException("Resource type not supported: "+resourceDescriptors.get(k).getClass().getName());
|
||||
}
|
||||
}
|
||||
return resources;
|
||||
}
|
||||
|
||||
public BlockingQueue<Message> getOutQueue(){
|
||||
return outQueue;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.aq.ng;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import ch.psi.fda.aq.ng.rdescriptors.ShellDescriptor;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
@Path("/")
|
||||
public class AcquisitionEngineNGResource {
|
||||
|
||||
@Inject
|
||||
private AcquisitionEngineNG engine;
|
||||
|
||||
@Inject
|
||||
private LManager lmanager;
|
||||
|
||||
// @PUT
|
||||
// @Path("logic")
|
||||
// public void execute(String logic){
|
||||
// Map<String, ?> map = new HashMap<>();
|
||||
// engine.execute(map, logic);
|
||||
// }
|
||||
|
||||
@GET
|
||||
@Path("logic")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Set<String> getLogics(){
|
||||
return lmanager.getLogics();
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("logic/{id}")
|
||||
public void setLogic(@PathParam("id") String id, String logic){
|
||||
lmanager.addLogic(id, logic);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("logic/{id}")
|
||||
public String getLogic(@PathParam("id") String id){
|
||||
String logic = lmanager.getLogic(id);
|
||||
if(logic==null){
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return logic;
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("logic/{id}")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void executeLogic(@PathParam("id") String id, EDescriptor edescriptor){
|
||||
|
||||
// Before executing the logic first merge the default descriptors and provided descriptors
|
||||
// Where the provided descriptors take precedence over the default onces.
|
||||
Map<String, RDescriptor> rdesc = new HashMap<>();
|
||||
rdesc.putAll(lmanager.getResources(id));
|
||||
if (edescriptor.getResources() != null) {
|
||||
rdesc.putAll(edescriptor.getResources());
|
||||
}
|
||||
|
||||
Map<String, ?> map = createResourceDescriptors(rdesc);
|
||||
|
||||
List<String> parameters = new ArrayList<>();
|
||||
if(edescriptor.getParameter()!=null){
|
||||
parameters = edescriptor.getParameter();
|
||||
}
|
||||
|
||||
engine.execute(map, lmanager.getLogic(id), parameters);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("logic/{id}/resources")
|
||||
public void setLogicResources(@PathParam("id") String id, Map<String, RDescriptor> rprofile){
|
||||
lmanager.addResources(id, rprofile);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("logic/{id}/resources")
|
||||
public Map<String, RDescriptor> getLogicResources(@PathParam("id") String id){
|
||||
Map<String, RDescriptor> rprofile = lmanager.getResources(id);
|
||||
if(rprofile==null){
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return rprofile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create internal resource descriptors based on the rdescriptors passed to the method.
|
||||
*
|
||||
* Currently following rdescriptor types are supported:
|
||||
* - channel
|
||||
* - shell
|
||||
*
|
||||
* @param descriptor
|
||||
* @return
|
||||
*/
|
||||
private Map<String, ?> createResourceDescriptors(Map<String, RDescriptor> resourceDescriptors) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
|
||||
for (String k : resourceDescriptors.keySet()) {
|
||||
RDescriptor r = resourceDescriptors.get(k);
|
||||
if (r.getType().equals("channel")) {
|
||||
Class<?> c;
|
||||
switch (r.getParameter().get("type").toLowerCase()) {
|
||||
case "double":
|
||||
c = Double.class;
|
||||
break;
|
||||
case "integer":
|
||||
c = Integer.class;
|
||||
break;
|
||||
case "boolean":
|
||||
c = Boolean.class;
|
||||
break;
|
||||
case "String":
|
||||
c = String.class;
|
||||
break;
|
||||
default:
|
||||
c = String.class;
|
||||
}
|
||||
;
|
||||
String name = r.getParameter().get("name");
|
||||
boolean monitored = false;
|
||||
if(r.getParameter().get("monitor")!=null){
|
||||
monitored = new Boolean(r.getParameter().get("monitor"));
|
||||
}
|
||||
|
||||
// Create channel descriptor
|
||||
ChannelDescriptor<?> cd = new ChannelDescriptor<>(c, name, monitored);
|
||||
map.put(k, cd);
|
||||
}
|
||||
else if (r.getType().equals("shell")) {
|
||||
map.put(k, new ShellDescriptor());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.aq.ng;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
|
||||
|
||||
/**
|
||||
* Execution descriptor - Describes resources and parameters used to execute a logic
|
||||
*/
|
||||
@XmlRootElement
|
||||
@JsonSerialize(include = Inclusion.NON_NULL) // Do not serialize NULL values
|
||||
public class EDescriptor {
|
||||
|
||||
private Map<String, RDescriptor> resources;
|
||||
private List<String> parameter;
|
||||
|
||||
public Map<String, RDescriptor> getResources() {
|
||||
return resources;
|
||||
}
|
||||
public void setResources(Map<String, RDescriptor> resources) {
|
||||
this.resources = resources;
|
||||
}
|
||||
public List<String> getParameter() {
|
||||
return parameter;
|
||||
}
|
||||
public void setParameter(List<String> parameter) {
|
||||
this.parameter = parameter;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.aq.ng;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Logic Manager
|
||||
* Basically a map holding id->logic pairs
|
||||
*
|
||||
* also holds default resource profiles for logics (rprofiles)
|
||||
*/
|
||||
public class LManager {
|
||||
private final Map<String, String> logics = new HashMap<>();
|
||||
|
||||
/** Default resourses assigned to a logic */
|
||||
private final Map<String, Map<String, RDescriptor>> resources = new HashMap<>();
|
||||
|
||||
public void addLogic(String id, String logic){
|
||||
logics.put(id, logic);
|
||||
resources.put(id, new HashMap<String,RDescriptor>()); // No default resources attached to logic
|
||||
}
|
||||
|
||||
public void addResources(String id, Map<String, RDescriptor> lresources){
|
||||
resources.put(id, lresources);
|
||||
}
|
||||
|
||||
public String getLogic(String id){
|
||||
return logics.get(id);
|
||||
}
|
||||
|
||||
public Set<String> getLogics(){
|
||||
return logics.keySet();
|
||||
}
|
||||
|
||||
public Map<String, RDescriptor> getResources(String id){
|
||||
return resources.get(id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.aq.ng;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriBuilderException;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.GnuParser;
|
||||
import org.apache.commons.cli.HelpFormatter;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.glassfish.grizzly.http.server.HttpServer;
|
||||
import org.glassfish.grizzly.http.server.StaticHttpHandler;
|
||||
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
|
||||
import org.glassfish.jersey.jackson.JacksonFeature;
|
||||
import org.glassfish.jersey.media.sse.SseFeature;
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
|
||||
import sun.misc.Signal;
|
||||
import sun.misc.SignalHandler;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class NGServer {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(NGServer.class.getName());
|
||||
|
||||
/**
|
||||
* @param args
|
||||
* @throws ParseException
|
||||
* @throws UnknownHostException
|
||||
* @throws UriBuilderException
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
public static void main(String[] args) throws ParseException, IllegalArgumentException, UriBuilderException, UnknownHostException {
|
||||
// Option handling
|
||||
int port = 8080;
|
||||
|
||||
Options options = new Options();
|
||||
options.addOption("h", false, "Help");
|
||||
options.addOption("p", true, "Server port (default: " + port + ")");
|
||||
|
||||
GnuParser parser = new GnuParser();
|
||||
CommandLine line = parser.parse(options, args);
|
||||
|
||||
if (line.hasOption("p")) {
|
||||
port = Integer.parseInt(line.getOptionValue("p"));
|
||||
}
|
||||
if (line.hasOption("h")) {
|
||||
HelpFormatter f = new HelpFormatter();
|
||||
f.printHelp("dae", options); // definition dae - http://www.urbandictionary.com/define.php?term=dae
|
||||
return;
|
||||
}
|
||||
|
||||
URI baseUri = UriBuilder.fromUri("http://" + InetAddress.getLocalHost().getHostName() + "/").port(port).build();
|
||||
|
||||
// final ResourceConfig resourceConfig = new
|
||||
// ResourceConfig(ServerSentEventsResource.class, SseFeature.class);
|
||||
ResourceConfig resourceConfig = new ResourceConfig(SseFeature.class, JacksonFeature.class);
|
||||
resourceConfig.packages(AcquisitionEngineNGResource.class.getPackage().getName());
|
||||
resourceConfig.register(new ResourceBinder());
|
||||
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig);
|
||||
|
||||
// Static content
|
||||
String home = System.getenv("DAE_BASE");
|
||||
if (home == null) {
|
||||
home = "src/main/assembly";
|
||||
}
|
||||
home = home + "/www";
|
||||
server.getServerConfiguration().addHttpHandler(new StaticHttpHandler(home), "/static");
|
||||
|
||||
logger.info("dae started");
|
||||
logger.info(String.format("Management interface available at %sstatic/", baseUri));
|
||||
logger.info("Use ctrl+c to stop ...");
|
||||
|
||||
// Signal handling
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
Signal.handle(new Signal("INT"), new SignalHandler() {
|
||||
public void handle(Signal sig) {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
// Wait for termination, i.e. wait for ctrl+c
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
server.stop();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.aq.ng;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
|
||||
|
||||
/**
|
||||
* Resource descriptor - Used to identify and/or create resource on server
|
||||
*/
|
||||
@XmlRootElement
|
||||
@JsonSerialize(include = Inclusion.NON_NULL) // Do not serialize NULL values
|
||||
public class RDescriptor {
|
||||
|
||||
private String ref;
|
||||
private String type;
|
||||
private Map<String,String> parameter;
|
||||
|
||||
public String getRef() {
|
||||
return ref;
|
||||
}
|
||||
public void setRef(String ref) {
|
||||
this.ref = ref;
|
||||
}
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
public Map<String, String> getParameter() {
|
||||
return parameter;
|
||||
}
|
||||
public void setParameter(Map<String, String> parameter) {
|
||||
this.parameter = parameter;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package ch.psi.fda.aq.ng;
|
||||
|
||||
import org.glassfish.hk2.utilities.binding.AbstractBinder;
|
||||
//import org.glassfish.jersey.media.sse.SseBroadcaster;
|
||||
|
||||
//import ch.psi.da.hub.model.Keystore;
|
||||
import ch.psi.jcae.impl.DefaultChannelService;
|
||||
|
||||
public class ResourceBinder extends AbstractBinder {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
// request scope binding
|
||||
// bind(MyInjectablePerRequest.class).to(MyInjectablePerRequest.class).in(RequestScope.class);
|
||||
// singleton binding
|
||||
// bind(MyInjectableSingleton.class).in(Singleton.class);
|
||||
// singleton instance binding
|
||||
|
||||
// KeystoreSerializer serializer = new KeystoreSerializer();
|
||||
// Keystore keystore = serializer.deserialize();
|
||||
|
||||
// bind(new SseBroadcaster()).to(SseBroadcaster.class);
|
||||
// bind(serializer).to(KeystoreSerializer.class);
|
||||
// bind(new KeystoreBroadcaster()).to(KeystoreBroadcaster.class);
|
||||
// bind(keystore).to(Keystore.class);
|
||||
|
||||
bind(new AcquisitionEngineNG(new DefaultChannelService())).to(AcquisitionEngineNG.class);
|
||||
bind(new LManager()).to(LManager.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,405 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.aq.ng;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.aq.ng.rdescriptors.ProbeDescriptor;
|
||||
import ch.psi.fda.aq.ng.rdescriptors.ShellDescriptor;
|
||||
import ch.psi.fda.core.messages.ComponentMetadata;
|
||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
||||
import ch.psi.fda.model.v1.Action;
|
||||
import ch.psi.fda.model.v1.ArrayPositioner;
|
||||
import ch.psi.fda.model.v1.ChannelAction;
|
||||
import ch.psi.fda.model.v1.Configuration;
|
||||
import ch.psi.fda.model.v1.ContinuousDimension;
|
||||
import ch.psi.fda.model.v1.Dimension;
|
||||
import ch.psi.fda.model.v1.DiscreteStepDimension;
|
||||
import ch.psi.fda.model.v1.DiscreteStepPositioner;
|
||||
import ch.psi.fda.model.v1.FunctionPositioner;
|
||||
import ch.psi.fda.model.v1.LinearPositioner;
|
||||
import ch.psi.fda.model.v1.PseudoPositioner;
|
||||
import ch.psi.fda.model.v1.RegionPositioner;
|
||||
import ch.psi.fda.model.v1.Scan;
|
||||
import ch.psi.fda.model.v1.ScriptAction;
|
||||
import ch.psi.fda.model.v1.ShellAction;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.util.ComparatorAND;
|
||||
import ch.psi.jcae.util.ComparatorOR;
|
||||
import ch.psi.jcae.util.ComparatorREGEX;
|
||||
|
||||
/**
|
||||
* Mapper to transform a FDA v1 xml into the new internal model
|
||||
*
|
||||
*/
|
||||
public class ScanMapperNG {
|
||||
|
||||
// Reserved resource id's
|
||||
private static final String PROBE_RESOURCE_ID = "probe";
|
||||
private static final String SHELL_RESOURCE_ID = "shell";
|
||||
// "logger" is also a special variable as it is bound to the logger of the application!
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ScanMapperNG.class.getName());
|
||||
|
||||
private static final String INDENT = " ";
|
||||
|
||||
private StringBuilder script = new StringBuilder();
|
||||
private Set<String> imports = new HashSet<>();
|
||||
private Map<String, Object> resourceDescriptors = new HashMap<>();
|
||||
|
||||
private ProbeDescriptor probeDescriptor = new ProbeDescriptor();
|
||||
private DataMessageMetadata dataMessageMetadata = new DataMessageMetadata();
|
||||
|
||||
|
||||
private String indentation = "";
|
||||
|
||||
public void map(Configuration configuration) {
|
||||
|
||||
// Clear object state
|
||||
script = new StringBuilder();
|
||||
imports = new HashSet<>();
|
||||
resourceDescriptors = new HashMap<>();
|
||||
probeDescriptor = new ProbeDescriptor();
|
||||
|
||||
resourceDescriptors.put(PROBE_RESOURCE_ID, probeDescriptor);
|
||||
|
||||
Scan scan = configuration.getScan();
|
||||
mapActions(scan.getPreAction());
|
||||
|
||||
// Bring the dimensions into the correct order and then map them
|
||||
// to the script
|
||||
List<Dimension> dimensions = new ArrayList<>();
|
||||
int size = scan.getDimension().size();
|
||||
for (int i = size - 1; i >= 0; i--) {
|
||||
dimensions.add(scan.getDimension().get(i));
|
||||
}
|
||||
// Continuous dimensions are always at the very end
|
||||
if (scan.getCdimension() != null) {
|
||||
dimensions.add(scan.getCdimension());
|
||||
}
|
||||
mapDimensions(dimensions, 0);
|
||||
|
||||
// map
|
||||
mapActions(scan.getPostAction());
|
||||
|
||||
// TODO CONSIDER TO PROVIDE RESOURCE MAP AND SCRIPT IN ONE OBJECT AS
|
||||
// RETURN TYPE
|
||||
// WOULD MAKE MORE SENSE
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the generated script
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getScript() {
|
||||
StringBuilder scriptlines = new StringBuilder();
|
||||
for (String s : imports) {
|
||||
scriptlines.append(s + "\n");
|
||||
}
|
||||
scriptlines.append(script);
|
||||
return scriptlines.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get map of required resources
|
||||
* @return
|
||||
*/
|
||||
public Map<String, Object> getResourceDescriptors(){
|
||||
return resourceDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO need to be moved somewhere else
|
||||
* @return
|
||||
*/
|
||||
public DataMessageMetadata getDataMessageMetadata(){
|
||||
return dataMessageMetadata;
|
||||
}
|
||||
|
||||
private void mapDimensions(List<Dimension> dimensions, int index) {
|
||||
|
||||
if(dimensions.size()<1){
|
||||
logger.info("There are no dimensions to map");
|
||||
return;
|
||||
}
|
||||
|
||||
Dimension dimension = dimensions.get(index);
|
||||
if (dimension instanceof DiscreteStepDimension) {
|
||||
DiscreteStepDimension d = (DiscreteStepDimension) dimension;
|
||||
|
||||
mapActions(d.getPreAction());
|
||||
|
||||
List<String> actuators = new ArrayList<>();
|
||||
|
||||
for(DiscreteStepPositioner positioner: d.getPositioner()){
|
||||
Class<?> type = String.class;
|
||||
switch (positioner.getType()) {
|
||||
case "Integer":
|
||||
type = Integer.class;
|
||||
break;
|
||||
case "Double":
|
||||
type = Double.class;
|
||||
break;
|
||||
}
|
||||
|
||||
String var = getChannelResourceVariable(positioner.getName(), type, false);
|
||||
actuators.add(var);
|
||||
|
||||
// Readback
|
||||
if(positioner.getReadback()==null){
|
||||
probeDescriptor.getSensors().add(new ChannelDescriptor<>(type, positioner.getName(), false));
|
||||
}
|
||||
else{
|
||||
// Use readback
|
||||
probeDescriptor.getSensors().add(new ChannelDescriptor<>(type, positioner.getReadback(), false));
|
||||
}
|
||||
// System.out.println(positioner.getId());
|
||||
dataMessageMetadata.getComponents().add(new ComponentMetadata(positioner.getId(), (dimensions.size()-1-index)));
|
||||
|
||||
// TODO Done resource
|
||||
|
||||
|
||||
if(positioner instanceof LinearPositioner){
|
||||
// Calculate steps and add it to position array
|
||||
LinearPositioner lpositioner = (LinearPositioner) positioner;
|
||||
boolean first = true;
|
||||
StringBuffer b = new StringBuffer();
|
||||
b.append("[");
|
||||
for(double i=0;(lpositioner.getStart()+i*lpositioner.getStepSize())<=lpositioner.getEnd();i++){
|
||||
if(first){
|
||||
first=false;
|
||||
}
|
||||
else{
|
||||
b.append(",");
|
||||
}
|
||||
b.append(String.format("%f", (lpositioner.getStart()+i*lpositioner.getStepSize())));
|
||||
}
|
||||
b.append("]");
|
||||
script.append(indentation + var+"_positions="+b.toString()+"\n");
|
||||
}
|
||||
else if(positioner instanceof ArrayPositioner){
|
||||
ArrayPositioner apositioner = (ArrayPositioner) positioner;
|
||||
// Calculate positions
|
||||
String[] positions = apositioner.getPositions().trim().split(" +");
|
||||
boolean first = true;
|
||||
StringBuffer b = new StringBuffer();
|
||||
b.append("[");
|
||||
for(String po: positions){
|
||||
if(first){
|
||||
first=false;
|
||||
}
|
||||
else{
|
||||
b.append(",");
|
||||
}
|
||||
|
||||
b.append(getPythonValue(po, type));
|
||||
}
|
||||
b.append("]");
|
||||
script.append(indentation + var+"_positions="+b.toString()+"\n");
|
||||
}
|
||||
else if(positioner instanceof FunctionPositioner){
|
||||
// TODO take variable mappings into account !
|
||||
}
|
||||
else if(positioner instanceof PseudoPositioner){
|
||||
// TODO implement
|
||||
}
|
||||
else if(positioner instanceof RegionPositioner){
|
||||
// TODO implement
|
||||
}
|
||||
}
|
||||
|
||||
// Create dimension loop
|
||||
String v = getUniqueVariableName();
|
||||
script.append(indentation + "for "+v+"_idx ,"+v+"_pos in enumerate("+actuators.get(0)+"_positions):\n");
|
||||
indentation = indentation + INDENT;
|
||||
|
||||
// Set all actuators of this dimension
|
||||
for(String a: actuators){
|
||||
script.append(indentation + a+".setValue("+a+"_positions["+v+"_idx])\n");
|
||||
}
|
||||
|
||||
// Add all actions executed between actuator and sensors
|
||||
mapActions(d.getAction());
|
||||
|
||||
// TODO map guard and sensors
|
||||
|
||||
|
||||
// Check whether final dimension reached
|
||||
if ((index + 1) < dimensions.size()) {
|
||||
// Map next dimension
|
||||
mapDimensions(dimensions, (index + 1));
|
||||
}
|
||||
else{
|
||||
// Final dimension reached - readout probe
|
||||
script.append(indentation + PROBE_RESOURCE_ID+".read()\n");
|
||||
}
|
||||
|
||||
indentation = indentation.replaceFirst(INDENT, ""); // decrease indentation
|
||||
|
||||
|
||||
script.append(indentation + PROBE_RESOURCE_ID+".delimiter("+(dimensions.size()-1-index)+", "+(d.isDataGroup()?"True":"False")+")\n");
|
||||
// send delimiter for this dimension
|
||||
// if lowest dimension end of stream message
|
||||
// if highest dimension no delimiter
|
||||
if(index==0){
|
||||
script.append(indentation + PROBE_RESOURCE_ID+".terminateStream()\n");
|
||||
}
|
||||
|
||||
mapActions(d.getPostAction());
|
||||
} else if (dimension instanceof ContinuousDimension) {
|
||||
// ContinuousDimension d = (ContinuousDimension) dimension;
|
||||
// TODO Map continuous dimension
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void mapActions(List<Action> actions) {
|
||||
for (Action action : actions) {
|
||||
if (action instanceof ChannelAction) {
|
||||
ChannelAction ca = (ChannelAction) action;
|
||||
Class<?> type = String.class;
|
||||
long waitTimeout=1800000; // Max wait timeout is 30 minutes
|
||||
if(ca.getTimeout()!=null){
|
||||
waitTimeout = ca.getTimeout().longValue()*1000; // wait timeout is currently in seconds
|
||||
}
|
||||
ca.getTimeout();
|
||||
switch (ca.getType()) {
|
||||
case "Integer":
|
||||
type = Integer.class;
|
||||
break;
|
||||
case "Double":
|
||||
type = Double.class;
|
||||
break;
|
||||
}
|
||||
String var = getChannelResourceVariable(ca.getChannel(), type, false);
|
||||
switch (ca.getOperation()) {
|
||||
case "put":
|
||||
if(ca.getTimeout()==null){
|
||||
script.append(var+".setValue("+getPythonValue(ca.getValue(), type)+")\n");
|
||||
} else {
|
||||
imports.add("from java.util.concurrent import TimeUnit");
|
||||
script.append(var+".setValueAsync("+getPythonValue(ca.getValue(), type)+").get("+ca.getTimeout()+", TimeUnit.MILLISECONDS)\n");
|
||||
}
|
||||
break;
|
||||
case "putq":
|
||||
script.append(var+".setValueNoWait("+getPythonValue(ca.getValue(), type)+")\n");
|
||||
break;
|
||||
case "wait":
|
||||
script.append(var+".waitForValue("+getPythonValue(ca.getValue(), type)+", "+waitTimeout+")\n");
|
||||
break;
|
||||
case "waitREGEX":
|
||||
imports.add("from"+ComparatorREGEX.class.getPackage().getName()+" import "+ComparatorREGEX.class.getName());
|
||||
script.append(var+".waitForValue("+getPythonValue(ca.getValue(), type)+", "+ComparatorREGEX.class.getName()+"() "+waitTimeout+")\n");
|
||||
break;
|
||||
case "waitOR":
|
||||
imports.add("from"+ComparatorOR.class.getPackage().getName()+" import "+ComparatorOR.class.getName());
|
||||
script.append(var+".waitForValue("+getPythonValue(ca.getValue(), type)+", "+ComparatorOR.class.getName()+"() "+waitTimeout+")\n");
|
||||
break;
|
||||
case "waitAND":
|
||||
imports.add("from"+ComparatorAND.class.getPackage().getName()+" import "+ComparatorAND.class.getName());
|
||||
script.append(var+".waitForValue("+getPythonValue(ca.getValue(), type)+", "+ComparatorAND.class.getName()+"() "+waitTimeout+")\n");
|
||||
break;
|
||||
default:
|
||||
logger.warning("Operation - "+ca.getOperation()+" - is not supported");
|
||||
// TODO Eventually throw exception - have two modes one logging, one exception?
|
||||
break;
|
||||
}
|
||||
|
||||
// If delay is specified wait specified time
|
||||
if (ca.getDelay() != null) {
|
||||
imports.add("import time");
|
||||
script.append("time.sleep(" + (ca.getDelay()) + ")\n");
|
||||
}
|
||||
|
||||
} else if (action instanceof ShellAction) {
|
||||
ShellAction saction = (ShellAction) action;
|
||||
resourceDescriptors.put(SHELL_RESOURCE_ID, new ShellDescriptor());
|
||||
// TODO Need to indicate that shell resource is required
|
||||
script.append(indentation + String.format(SHELL_RESOURCE_ID+".execute('%s', %d, %s)\n", saction.getCommand(), saction.getExitValue(), saction.isCheckExitValue()?"True":"False"));
|
||||
} else if (action instanceof ScriptAction) {
|
||||
ScriptAction saction = (ScriptAction) action;
|
||||
|
||||
// TODO Need to indicate that that mapped resources are required
|
||||
// Read script line by line and prepend the current indentation
|
||||
// level
|
||||
String[] lines = saction.getScript().split(System.getProperty("line.separator"));
|
||||
for (String s : lines) {
|
||||
script.append(indentation + s+"\n");
|
||||
}
|
||||
script.append(indentation + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unique variable names that do not collide with others. (at least have
|
||||
* an extreme unlikeness to do so)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getUniqueVariableName() {
|
||||
return "v" + UUID.randomUUID().toString().replaceAll("-", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string representation for a variable in python
|
||||
* i.e. surrounds String with '', ensures that double has a . in the value, ...
|
||||
* @param value
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
private String getPythonValue(String value, Class<?> type){
|
||||
if(type.equals(String.class)){
|
||||
return "'"+value+"'";
|
||||
}
|
||||
else if(type.equals(Double.class)){
|
||||
return String.format("%f", new Double(value));
|
||||
}
|
||||
else if(type.equals(Integer.class)){
|
||||
return String.format("%d", new Integer(value));
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Request resource
|
||||
*
|
||||
* @param resourceId
|
||||
* @return variable name for resource
|
||||
*
|
||||
* TODO Eventually we need to add type of resource here to be able
|
||||
* to generate the resource before the script is executed.
|
||||
*/
|
||||
private String getChannelResourceVariable(String channelName, Class<?> type, boolean monitor) {
|
||||
// Right now each a new channel object will be created for each requirested channel resource (even it is the same channel)
|
||||
// TODO Optimize the resource consumption by checking whether the resource already exists and return only one reference.
|
||||
String varname = getUniqueVariableName();
|
||||
resourceDescriptors.put(varname, new ChannelDescriptor<>(type, channelName, monitor));
|
||||
return varname;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.aq.ng.resources;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.EndOfStreamMessage;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
import ch.psi.fda.core.messages.StreamDelimiterMessage;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ChannelProbeResource {
|
||||
|
||||
private final List<Channel<?>> channels;
|
||||
private BlockingQueue<Message> queue;
|
||||
|
||||
public ChannelProbeResource(List<Channel<?>> channels, BlockingQueue<Message> queue){
|
||||
this.channels = channels;
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read configured channels and send out data message
|
||||
*/
|
||||
public void read(){
|
||||
try{
|
||||
DataMessage message = new DataMessage();
|
||||
for(Channel<?> sensor: channels){
|
||||
// Readout sensor
|
||||
Object o = sensor.getValue();
|
||||
// Add sensor data item to message
|
||||
message.getData().add(o);
|
||||
}
|
||||
System.out.println("MESSAGE: "+message);
|
||||
queue.put(message);
|
||||
} catch (InterruptedException | TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a stream delimiter message for the given index
|
||||
* @param index
|
||||
* @param iflag
|
||||
*/
|
||||
public void delimiter(int index, boolean iflag){
|
||||
try {
|
||||
StreamDelimiterMessage message = new StreamDelimiterMessage(index, iflag);
|
||||
System.out.println(message);
|
||||
queue.put(message);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to send delimiter message", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send end of stream message
|
||||
*/
|
||||
public void terminateStream(){
|
||||
try {
|
||||
EndOfStreamMessage message = new EndOfStreamMessage();
|
||||
System.out.println(message);
|
||||
queue.put(message);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to send end of stream message", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.aq.ng.resources;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ShellResource {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ShellResource.class.getName());
|
||||
|
||||
/**
|
||||
* Execute script/command in shell
|
||||
* @param script
|
||||
*/
|
||||
public void execute(String script){
|
||||
execute(script, 0, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute script/command in shell
|
||||
* @param script
|
||||
* @param returnValue
|
||||
* @param checkReturnValue
|
||||
*/
|
||||
public void execute(String script, int returnValue, boolean checkReturnValue){
|
||||
ProcessBuilder pb = new ProcessBuilder(new String[]{"/bin/bash","-c",script});
|
||||
pb.redirectErrorStream(true);
|
||||
|
||||
try {
|
||||
Process p = pb.start();
|
||||
int rvalue = p.waitFor();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line = null;
|
||||
while((line=reader.readLine()) != null){
|
||||
logger.info(line);
|
||||
}
|
||||
|
||||
// Check return value if need to be checked
|
||||
if(checkReturnValue){
|
||||
if(rvalue != returnValue){
|
||||
throw new RuntimeException("Executing script "+script+" failed");
|
||||
}
|
||||
}
|
||||
} catch (IOException | InterruptedException e) {
|
||||
throw new RuntimeException("Unable to execute script", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,10 +19,6 @@
|
||||
|
||||
package ch.psi.fda.core;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public interface Action {
|
||||
|
||||
/**
|
||||
@@ -34,13 +30,4 @@ public interface Action {
|
||||
* Abort the execution logic of the action
|
||||
*/
|
||||
public void abort();
|
||||
|
||||
/**
|
||||
* Destroy action.
|
||||
* Can be used for the cleanup of used resources of the action (e.g. to close connections, ...) if
|
||||
* this cannot be done automatically by the GarbageCollector.
|
||||
*
|
||||
* After calling this method the action must not be executed any more!
|
||||
*/
|
||||
public void destroy();
|
||||
}
|
||||
|
||||
@@ -21,14 +21,11 @@ package ch.psi.fda.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Loop of actions to accomplish a task. Depending on the loop
|
||||
* actions may be executed in a different way.
|
||||
*
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public interface ActionLoop extends Action {
|
||||
|
||||
@@ -65,5 +62,5 @@ public interface ActionLoop extends Action {
|
||||
*/
|
||||
public void setDataGroup(boolean dataGroup);
|
||||
|
||||
public DataQueue getDataQueue();
|
||||
public EventBus getEventBus();
|
||||
}
|
||||
|
||||
@@ -19,11 +19,6 @@
|
||||
|
||||
package ch.psi.fda.core;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public interface Actor {
|
||||
/**
|
||||
* Set actor value
|
||||
@@ -51,14 +46,4 @@ public interface Actor {
|
||||
* Reset the actuator to its initial configuration
|
||||
*/
|
||||
public void reset();
|
||||
|
||||
|
||||
/**
|
||||
* Destroy action.
|
||||
* Can be used for the cleanup of used resources of the actor (e.g. to close connections, ...) if
|
||||
* this cannot be done automatically by the GarbageCollector.
|
||||
*
|
||||
* After calling this method the actor must not be used any more!
|
||||
*/
|
||||
public void destroy();
|
||||
}
|
||||
|
||||
@@ -23,25 +23,18 @@ import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Callable used for parallel execution of the set method of an actor
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ActorSetCallable implements Callable<Object> {
|
||||
|
||||
// Callable actor
|
||||
private Actor actor;
|
||||
|
||||
public ActorSetCallable(Actor actor){
|
||||
this.actor = actor;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.util.concurrent.Callable#call()
|
||||
*/
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
actor.set();
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core;
|
||||
|
||||
/**
|
||||
* Singleton object for holing the core engine configuration
|
||||
*
|
||||
* @author ebner
|
||||
*/
|
||||
public class EngineConfiguration {
|
||||
|
||||
/**
|
||||
* Flag to indicate whether the engine should fail if there is an error while reading out a sensor.
|
||||
*/
|
||||
private boolean failOnSensorError = true;
|
||||
|
||||
/**
|
||||
* Flag to indicate whether the set value of the actor should be verified after the set operation.
|
||||
* Having this flag on true will enable detecting for example that a motor hit the end switch or
|
||||
* did not move correctly.
|
||||
*/
|
||||
private boolean checkActorSet = true;
|
||||
|
||||
/**
|
||||
* Singleton instance
|
||||
*/
|
||||
private final static EngineConfiguration instance = new EngineConfiguration();
|
||||
|
||||
|
||||
|
||||
private EngineConfiguration(){
|
||||
}
|
||||
|
||||
/**
|
||||
* Get singleton instance of this class
|
||||
* @return Engine configuration
|
||||
*/
|
||||
public static EngineConfiguration getInstance(){
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the failOnSensorError
|
||||
*/
|
||||
public boolean isFailOnSensorError() {
|
||||
return failOnSensorError;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param failOnSensorError the failOnSensorError to set
|
||||
*/
|
||||
public void setFailOnSensorError(boolean failOnSensorError) {
|
||||
this.failOnSensorError = failOnSensorError;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the checkActorSet
|
||||
*/
|
||||
public boolean isCheckActorSet() {
|
||||
return checkActorSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param checkActorSet the checkActorSet to set
|
||||
*/
|
||||
public void setCheckActorSet(boolean checkActorSet) {
|
||||
this.checkActorSet = checkActorSet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,9 +25,6 @@ package ch.psi.fda.core;
|
||||
*
|
||||
* Example:
|
||||
* An Guard can be used to check whether an injection happened while the the detector were read.
|
||||
*
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public interface Guard {
|
||||
|
||||
@@ -41,13 +38,4 @@ public interface Guard {
|
||||
* @return Returns true if the guard condition was not constrainted since the last init call. False otherwise.
|
||||
*/
|
||||
public boolean check();
|
||||
|
||||
/**
|
||||
* Destroy guard.
|
||||
* Can be used for the cleanup of used resources of the guard (e.g. to close connections, ...) if
|
||||
* this cannot be done automatically by the GarbageCollector.
|
||||
*
|
||||
* After calling this method the guard must not be used any more!
|
||||
*/
|
||||
public void destroy();
|
||||
}
|
||||
|
||||
@@ -17,15 +17,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.manipulator;
|
||||
package ch.psi.fda.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
||||
import ch.psi.fda.core.messages.Metadata;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public interface Manipulation {
|
||||
|
||||
/**
|
||||
@@ -38,7 +36,7 @@ public interface Manipulation {
|
||||
* Initialize the manipulation
|
||||
* @param metadata Metadata of the incomming data message
|
||||
*/
|
||||
public void initialize(DataMessageMetadata metadata);
|
||||
public void initialize(List<Metadata> metadata);
|
||||
|
||||
/**
|
||||
* Execute the manipulation on the passed data message
|
||||
@@ -23,8 +23,6 @@ package ch.psi.fda.core;
|
||||
* The sensor interface describes an entity that can be read out like a
|
||||
* simple channel or (image) detector. Depending on the sensor type the
|
||||
* returned data is of a certain type.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public interface Sensor {
|
||||
/**
|
||||
@@ -38,13 +36,4 @@ public interface Sensor {
|
||||
* @return id of sensor
|
||||
*/
|
||||
public String getId();
|
||||
|
||||
/**
|
||||
* Destroy sensor.
|
||||
* Can be used for the cleanup of used resources of the sensor (e.g. to close connections, ...) if
|
||||
* this cannot be done automatically by the GarbageCollector.
|
||||
*
|
||||
* After calling this method the sensor must not be used any more!
|
||||
*/
|
||||
public void destroy();
|
||||
}
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
@@ -19,145 +19,106 @@
|
||||
|
||||
package ch.psi.fda.core.actions;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.Action;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* Perform a put on the specified Channel Access channel. The put can be done
|
||||
* synchronous or asynchronously.
|
||||
*
|
||||
* @author ebner
|
||||
*
|
||||
* Perform a put on the specified Channel Access channel. The put can be done synchronous or
|
||||
* asynchronously.
|
||||
*/
|
||||
public class ChannelAccessCondition<E> implements Action {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessCondition.class.getName());
|
||||
|
||||
/**
|
||||
* Channel to set
|
||||
*/
|
||||
|
||||
private final Channel<E> channel;
|
||||
/**
|
||||
* Value to wait for
|
||||
*/
|
||||
private final E expectedValue;
|
||||
|
||||
private Long timeout;
|
||||
|
||||
private final Comparator<E> comparator;
|
||||
private final Long timeout;
|
||||
|
||||
private volatile boolean abort = false;
|
||||
private volatile Thread waitT = null;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param channel Channel to wait value for
|
||||
* @param expectedValue Value to wait for
|
||||
* @param timeout Timeout of the condition in milliseconds (null accepted - will take default wait timeout for channels ch.psi.jcae.ChannelBeanFactory.waitTimeout)
|
||||
*
|
||||
* @param channelName
|
||||
* Name of the channel to set the value
|
||||
* @param expectedValue
|
||||
* Value to wait for
|
||||
* @param timeout
|
||||
* Timeout of the condition in milliseconds (null accepted - will
|
||||
* take default wait timeout for channels
|
||||
* ch.psi.jcae.ChannelBeanFactory.waitTimeout)
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* Unable to initialize channel, Timeout specified is not >=0
|
||||
* @throws IllegalArgumentException Timeout specified is not >=0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChannelAccessCondition(ChannelService s, String channelName, E expectedValue, Long timeout) {
|
||||
public ChannelAccessCondition(Channel<E> channel, E expectedValue, Long timeout){
|
||||
|
||||
if (timeout != null && timeout <= 0) {
|
||||
if(timeout != null && timeout<=0){
|
||||
throw new IllegalArgumentException("Timeout must be > 0");
|
||||
}
|
||||
|
||||
try {
|
||||
this.channel = (Channel<E>) s.createChannel(new ChannelDescriptor<>(expectedValue.getClass(), channelName, false));
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
throw new IllegalArgumentException("Unable to initialize actuator channel [name:" + channelName + "]", e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize actuator channel [name:" + channelName + "]", e);
|
||||
}
|
||||
|
||||
|
||||
this.channel = channel;
|
||||
this.expectedValue = expectedValue;
|
||||
this.comparator = null;
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public ChannelAccessCondition(Channel<E> channel, E expectedValue, Comparator<E> comparator, Long timeout){
|
||||
|
||||
if (timeout == null) {
|
||||
// this.timeout = channel.get.getWaitTimeout();
|
||||
this.timeout=1L;
|
||||
} else {
|
||||
this.timeout = timeout;
|
||||
if(timeout != null && timeout<=0){
|
||||
throw new IllegalArgumentException("Timeout must be > 0");
|
||||
}
|
||||
|
||||
this.channel = channel;
|
||||
this.expectedValue = expectedValue;
|
||||
this.comparator = comparator;
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see ch.psi.fda.core.Action#execute()
|
||||
*/
|
||||
|
||||
/**
|
||||
* @throws InterruptedException
|
||||
* @throws RuntimeException
|
||||
* Channel value did not reach expected value (within the
|
||||
* specified timeout period)
|
||||
* @throws RuntimeException Channel value did not reach expected value (within the specified timeout period)
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws InterruptedException {
|
||||
abort = false;
|
||||
logger.finest("Checking channel " + channel.getName() + " for value " + expectedValue + " [timeout: " + timeout + "]");
|
||||
try {
|
||||
abort=false;
|
||||
logger.finest("Checking channel "+channel.getName()+" for value "+expectedValue+" [timeout: "+timeout+"]" );
|
||||
try{
|
||||
waitT = Thread.currentThread();
|
||||
channel.waitForValueAsync(expectedValue).get(timeout, TimeUnit.MILLISECONDS); // Workaround use
|
||||
// 10seconds default
|
||||
// set timeout to
|
||||
// check several
|
||||
// times whether the
|
||||
// channel has
|
||||
// reached the value
|
||||
} catch (InterruptedException e) {
|
||||
if (!abort) {
|
||||
throw e;
|
||||
try {
|
||||
if(comparator==null){
|
||||
if(timeout == null){
|
||||
channel.waitForValue(expectedValue);
|
||||
}
|
||||
else{
|
||||
channel.waitForValue(expectedValue, timeout);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(timeout == null){
|
||||
channel.waitForValue(expectedValue, comparator);
|
||||
}
|
||||
else{
|
||||
channel.waitForValue(expectedValue, comparator, timeout);
|
||||
}
|
||||
}
|
||||
} catch (ExecutionException | ChannelException | TimeoutException | InterruptedException e) {
|
||||
if(abort && e instanceof InterruptedException){
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException("Channel [name:"+channel.getName()+"] did not reach expected value "+expectedValue+" ", e);
|
||||
}
|
||||
} catch (ExecutionException | TimeoutException | ChannelException e) {
|
||||
throw new RuntimeException("Channel [name:" + channel.getName() + "] did not reach expected value " + expectedValue + " ", e);
|
||||
} finally {
|
||||
waitT = null;
|
||||
}
|
||||
finally{
|
||||
waitT=null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see ch.psi.fda.core.Action#abort()
|
||||
*/
|
||||
@Override
|
||||
public void abort() {
|
||||
abort = true;
|
||||
if (waitT != null) {
|
||||
abort=true;
|
||||
if(waitT!=null){
|
||||
waitT.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see ch.psi.fda.core.Action#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy channel
|
||||
logger.finest("Destroy action channel: " + channel.getName());
|
||||
try {
|
||||
channel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel [" + channel.getName() + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.actions;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.Action;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* Perform a put on the specified Channel Access channel. The put can be done synchronous or
|
||||
* asynchronously.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ChannelAccessConditionAnd<E extends Integer> implements Action {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessConditionAnd.class.getName());
|
||||
|
||||
/**
|
||||
* Channel to set
|
||||
*/
|
||||
private final Channel<E> channel;
|
||||
/**
|
||||
* Value to wait for
|
||||
*/
|
||||
private final E expectedValue;
|
||||
|
||||
private final Long timeout;
|
||||
|
||||
private volatile boolean abort = false;
|
||||
private volatile Thread waitT = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param channelName Name of the channel to set the value
|
||||
* @param expectedValue Value to wait for
|
||||
* @param timeout Timeout of the condition in milliseconds (null accepted - will take default wait timeout for channels ch.psi.jcae.ChannelBeanFactory.waitTimeout)
|
||||
*
|
||||
* @throws IllegalArgumentException Unable to initialize channel,
|
||||
* Timeout specified is not >=0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChannelAccessConditionAnd(ChannelService s, String channelName, E expectedValue, Long timeout){
|
||||
|
||||
if(timeout !=null && timeout<=0){
|
||||
throw new IllegalArgumentException("Timeout must be > 0");
|
||||
}
|
||||
|
||||
try {
|
||||
this.channel = s.createChannel(new ChannelDescriptor<>( (Class<E>) expectedValue.getClass(), channelName, false));
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
}
|
||||
|
||||
this.expectedValue = expectedValue;
|
||||
|
||||
if(timeout==null){
|
||||
// this.timeout = channel.getWaitTimeout();
|
||||
this.timeout = 0L;
|
||||
}
|
||||
else{
|
||||
this.timeout = timeout;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#execute()
|
||||
*/
|
||||
/**
|
||||
* @throws InterruptedException
|
||||
* @throws RuntimeException Channel value did not reach expected value (within the specified timeout period)
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws InterruptedException {
|
||||
abort=false;
|
||||
logger.finest("Checking channel "+channel.getName()+" for value "+expectedValue+" [timeout: "+timeout+"]" );
|
||||
try{
|
||||
waitT = Thread.currentThread();
|
||||
channel.waitForValue(expectedValue, new Comparator<E>() {
|
||||
|
||||
@Override
|
||||
public int compare(E o1, E o2) {
|
||||
int one = o1;
|
||||
int two = o2;
|
||||
if((one & two) != 0){
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
, timeout); // Workaround use 10seconds default set timeout to check several times whether the channel has reached the value
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException("Channel [name:"+channel.getName()+"] did not reach expected value "+expectedValue+" ", e);
|
||||
} catch(InterruptedException e){
|
||||
if(!abort){
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
finally{
|
||||
waitT=null;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#abort()
|
||||
*/
|
||||
@Override
|
||||
public void abort() {
|
||||
abort=true;
|
||||
if(waitT!=null){
|
||||
waitT.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy channel
|
||||
try {
|
||||
logger.finest("Destroy action channel: "+channel.getName());
|
||||
channel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.actions;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.Action;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* Perform a put on the specified Channel Access channel. The put can be done synchronous or
|
||||
* asynchronously.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ChannelAccessConditionOr<E extends Integer> implements Action {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessConditionOr.class.getName());
|
||||
|
||||
/**
|
||||
* Channel to set
|
||||
*/
|
||||
private final Channel<E> channel;
|
||||
/**
|
||||
* Value to wait for
|
||||
*/
|
||||
private final E expectedValue;
|
||||
|
||||
private final Long timeout;
|
||||
|
||||
private volatile boolean abort = false;
|
||||
private volatile Thread waitT = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param channelName Name of the channel to set the value
|
||||
* @param expectedValue Value to wait for
|
||||
* @param timeout Timeout of the condition in milliseconds (null accepted - will take default wait timeout for channels ch.psi.jcae.ChannelBeanFactory.waitTimeout)
|
||||
*
|
||||
* @throws IllegalArgumentException Unable to initialize channel,
|
||||
* Timeout specified is not >=0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChannelAccessConditionOr(ChannelService s, String channelName, E expectedValue, Long timeout){
|
||||
|
||||
if(timeout !=null && timeout<=0){
|
||||
throw new IllegalArgumentException("Timeout must be > 0");
|
||||
}
|
||||
|
||||
try {
|
||||
this.channel = s.createChannel(new ChannelDescriptor<>( (Class<E>) expectedValue.getClass(), channelName, false));
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
}
|
||||
|
||||
this.expectedValue = expectedValue;
|
||||
|
||||
if(timeout==null){
|
||||
// this.timeout = channel.getWaitTimeout();
|
||||
this.timeout = 0L;
|
||||
}
|
||||
else{
|
||||
this.timeout = timeout;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#execute()
|
||||
*/
|
||||
/**
|
||||
* @throws InterruptedException
|
||||
* @throws RuntimeException Channel value did not reach expected value (within the specified timeout period)
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws InterruptedException {
|
||||
abort=false;
|
||||
logger.finest("Checking channel "+channel.getName()+" for value "+expectedValue+" [timeout: "+timeout+"]" );
|
||||
try{
|
||||
waitT = Thread.currentThread();
|
||||
channel.waitForValue(expectedValue, new Comparator<E>() {
|
||||
|
||||
@Override
|
||||
public int compare(E o1, E o2) {
|
||||
int one = o1;
|
||||
int two = o2;
|
||||
if((one | two) != 0){
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
, timeout); // Workaround use 10seconds default set timeout to check several times whether the channel has reached the value
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException("Channel [name:"+channel.getName()+"] did not reach expected value "+expectedValue+" ", e);
|
||||
} catch(InterruptedException e){
|
||||
if(!abort){
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
finally{
|
||||
waitT=null;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#abort()
|
||||
*/
|
||||
@Override
|
||||
public void abort() {
|
||||
abort=true;
|
||||
if(waitT!=null){
|
||||
waitT.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy channel
|
||||
try {
|
||||
logger.finest("Destroy action channel: "+channel.getName());
|
||||
channel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.actions;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.Action;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* Perform a put on the specified Channel Access channel. The put can be done synchronous or
|
||||
* asynchronously.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ChannelAccessConditionRegex<E extends String> implements Action {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessConditionRegex.class.getName());
|
||||
|
||||
/**
|
||||
* Channel to set
|
||||
*/
|
||||
private final Channel<E> channel;
|
||||
/**
|
||||
* Value to wait for
|
||||
*/
|
||||
private final E expectedValue;
|
||||
|
||||
private final Long timeout;
|
||||
|
||||
private volatile boolean abort = false;
|
||||
private volatile Thread waitT = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param channelName Name of the channel to set the value
|
||||
* @param expectedValue Value to wait for
|
||||
* @param timeout Timeout of the condition in milliseconds (null accepted - will take default wait timeout for channels ch.psi.jcae.ChannelBeanFactory.waitTimeout)
|
||||
*
|
||||
* @throws IllegalArgumentException Unable to initialize channel,
|
||||
* Timeout specified is not >=0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChannelAccessConditionRegex(ChannelService s, String channelName, E expectedValue, Long timeout){
|
||||
|
||||
if(timeout !=null && timeout<=0){
|
||||
throw new IllegalArgumentException("Timeout must be > 0");
|
||||
}
|
||||
|
||||
try {
|
||||
this.channel = s.createChannel(new ChannelDescriptor<>( (Class<E>) expectedValue.getClass(), channelName, false));
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
}
|
||||
|
||||
this.expectedValue = expectedValue;
|
||||
|
||||
if(timeout==null){
|
||||
// this.timeout = channel.getWaitTimeout();
|
||||
this.timeout = 0L;
|
||||
}
|
||||
else{
|
||||
this.timeout = timeout;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#execute()
|
||||
*/
|
||||
/**
|
||||
* @throws InterruptedException
|
||||
* @throws RuntimeException Channel value did not reach expected value (within the specified timeout period)
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws InterruptedException {
|
||||
abort=false;
|
||||
logger.finest("Checking channel "+channel.getName()+" for value "+expectedValue+" [timeout: "+timeout+"]" );
|
||||
try{
|
||||
waitT = Thread.currentThread();
|
||||
channel.waitForValue(expectedValue, new Comparator<E>() {
|
||||
|
||||
@Override
|
||||
public int compare(E o1, E o2) {
|
||||
return o1.matches(o2) ? 0:1;
|
||||
}
|
||||
}, timeout); // Workaround use 10seconds default set timeout to check several times whether the channel has reached the value
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException("Channel [name:"+channel.getName()+"] did not reach expected value "+expectedValue+" ", e);
|
||||
} catch(InterruptedException e){
|
||||
if(!abort){
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
finally{
|
||||
waitT=null;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#abort()
|
||||
*/
|
||||
@Override
|
||||
public void abort() {
|
||||
abort=true;
|
||||
if(waitT!=null){
|
||||
waitT.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy channel
|
||||
try {
|
||||
logger.finest("Destroy action channel: "+channel.getName());
|
||||
channel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,57 +26,31 @@ import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.Action;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* Perform a put on the specified Channel Access channel. The put can be done synchronous or
|
||||
* asynchronously.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ChannelAccessPut<E> implements Action {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessPut.class.getName());
|
||||
|
||||
/**
|
||||
* Channel to set
|
||||
*/
|
||||
private final Channel<E> channel;
|
||||
/**
|
||||
* Value to set
|
||||
*/
|
||||
private final E value;
|
||||
/**
|
||||
* Put mode, true = fire and forget, false = wait for response
|
||||
*/
|
||||
private final boolean asynchronous;
|
||||
|
||||
private final Long timeout;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param channelName Name of the channel to set the value
|
||||
* @param channel
|
||||
* @param value Value to set
|
||||
* @param asynchronous Flag whether to set the value synchronous (wait for response) or asynchronously (fire and forget)
|
||||
* @param timeout Timeout used for set operation (time that set need to come back)
|
||||
*
|
||||
* @throws IllegalArgumentException Unable to initialize channel
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChannelAccessPut(ChannelService s, String channelName, E value, boolean asynchronous, Long timeout){
|
||||
public ChannelAccessPut(Channel<E> channel, E value, boolean asynchronous, Long timeout){
|
||||
|
||||
try {
|
||||
this.channel = s.createChannel(new ChannelDescriptor<>((Class<E>)value.getClass(), channelName, false));
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
}
|
||||
|
||||
this.channel = channel;
|
||||
this.value = value;
|
||||
this.asynchronous = asynchronous;
|
||||
this.timeout = timeout;
|
||||
@@ -84,20 +58,14 @@ public class ChannelAccessPut<E> implements Action {
|
||||
|
||||
/**
|
||||
* Additional constructor for convenience. This constructor defaults the operation type to synchronous put.
|
||||
* @param channelName Name of the channel to set the value
|
||||
* @param channel
|
||||
* @param value Value to set
|
||||
*
|
||||
* @throws RuntimeException Unable to initialize channel
|
||||
*/
|
||||
public ChannelAccessPut(ChannelService s, String channelName, E value){
|
||||
this(s, channelName, value, false, null);
|
||||
public ChannelAccessPut(Channel<E> channel, E value){
|
||||
this(channel, value, false, null);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#execute()
|
||||
*/
|
||||
/**
|
||||
* @throws InterruptedException
|
||||
* @throws RuntimeException Cannot set value on channel
|
||||
*/
|
||||
@Override
|
||||
@@ -115,32 +83,12 @@ public class ChannelAccessPut<E> implements Action {
|
||||
channel.setValueAsync(value).get(timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
} catch (ChannelException | ExecutionException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
} catch (ExecutionException | TimeoutException | ChannelException e) {
|
||||
throw new RuntimeException("Unable to set channel [name:"+channel.getName()+"] to value "+value, e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#abort()
|
||||
*/
|
||||
@Override
|
||||
public void abort() {
|
||||
// This action cannot be aborted, therefore this method is not implemented
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy channel
|
||||
try {
|
||||
logger.finest("Destroy action channel: "+channel.getName());
|
||||
channel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,19 +23,13 @@ import ch.psi.fda.core.Action;
|
||||
|
||||
/**
|
||||
* Wait a specific time until executing the next action ...
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class Delay implements Action {
|
||||
|
||||
/**
|
||||
* Time to wait
|
||||
*/
|
||||
private final long time;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param time Time to wait (in milliseconds)
|
||||
* @param time Time to wait in milliseconds
|
||||
*/
|
||||
public Delay(long time){
|
||||
|
||||
@@ -47,28 +41,12 @@ public class Delay implements Action {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#execute()
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws InterruptedException {
|
||||
Thread.sleep(time);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#abort()
|
||||
*/
|
||||
@Override
|
||||
public void abort() {
|
||||
// Not implemented because not needed
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Nothing to be done
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
|
||||
package ch.psi.fda.core.actions;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -30,20 +31,12 @@ import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import ch.psi.fda.core.Action;
|
||||
import ch.psi.fda.core.scripting.JythonParameterMapping;
|
||||
import ch.psi.fda.core.scripting.JythonParameterMappingChannel;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
* Executes a python script inside a Jython interpreter
|
||||
*/
|
||||
public class JythonAction implements Action {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(JythonAction.class.getName());
|
||||
|
||||
/**
|
||||
@@ -52,17 +45,19 @@ public class JythonAction implements Action {
|
||||
private static final String entryFunction = "process";
|
||||
private static final String entryFunctionPattern = "def "+entryFunction+"\\((.*)\\):";
|
||||
|
||||
/**
|
||||
* Script engine of the manipulator
|
||||
*/
|
||||
private ScriptEngine engine;
|
||||
|
||||
/**
|
||||
* Jython entry call
|
||||
*/
|
||||
private String jythonCall;
|
||||
private String jythonCall; // entry call to script - including all parameters, etc.
|
||||
|
||||
private final Map<String,Object> globalObjects;
|
||||
|
||||
public JythonAction(String script, Map<String, ?> mapping){
|
||||
this(script, mapping, new HashMap<String,Object>());
|
||||
}
|
||||
|
||||
public JythonAction(String script, Map<String, ?> mapping, Map<String,Object> globalObjects){
|
||||
|
||||
public JythonAction(ChannelService s, String script, List<JythonParameterMappingChannel> mapping){
|
||||
this.globalObjects = globalObjects;
|
||||
|
||||
// Workaround for Jython memory leak
|
||||
// http://blog.hillbrecht.de/2009/07/11/jython-memory-leakout-of-memory-problem/
|
||||
@@ -77,7 +72,13 @@ public class JythonAction implements Action {
|
||||
String[] functionParameters = null;
|
||||
if(matcher.find() && matcher.groupCount()==1){
|
||||
logger.finest("Entry function '"+entryFunctionPattern+"' found - Identified parameters: "+matcher.group(1));
|
||||
functionParameters = matcher.group(1).split(" *, *");
|
||||
jythonCall = entryFunction+"("+matcher.group(1)+")";
|
||||
if(matcher.group(1).matches(" *")){
|
||||
functionParameters = new String[0];
|
||||
}
|
||||
else{
|
||||
functionParameters = matcher.group(1).split(" *, *");
|
||||
}
|
||||
}
|
||||
else{
|
||||
throw new IllegalArgumentException("Cannot determine entry function: "+entryFunctionPattern);
|
||||
@@ -88,8 +89,8 @@ public class JythonAction implements Action {
|
||||
String p = functionParameters[i];
|
||||
p = p.trim();
|
||||
boolean found = false;
|
||||
for(JythonParameterMapping pm: mapping){
|
||||
if(pm.getVariable().equals(p)){
|
||||
for(String pm: mapping.keySet()){
|
||||
if(pm.equals(p)){
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
@@ -111,60 +112,31 @@ public class JythonAction implements Action {
|
||||
throw new RuntimeException("Unable to load manipulation script", e);
|
||||
}
|
||||
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append(entryFunction);
|
||||
buffer.append("(");
|
||||
for(JythonParameterMappingChannel b: mapping){
|
||||
// Create channel
|
||||
|
||||
Channel<?> cb;
|
||||
try {
|
||||
cb = s.createChannel(new ChannelDescriptor<>(b.getType(), b.getChannel(), true));
|
||||
} catch (TimeoutException | ChannelException e) {
|
||||
throw new IllegalArgumentException("Unable to establish channel: "+b.getChannel(), e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to establish channel: "+b.getChannel(), e);
|
||||
}
|
||||
|
||||
for(String b: mapping.keySet()){
|
||||
// Assign channel bean to variable
|
||||
engine.put(b.getVariable(), cb);
|
||||
|
||||
buffer.append(b.getVariable());
|
||||
buffer.append(",");
|
||||
engine.put(b, mapping.get(b));
|
||||
}
|
||||
buffer.setCharAt(buffer.length()-1, ')');
|
||||
|
||||
jythonCall = buffer.toString();
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#execute()
|
||||
*/
|
||||
@Override
|
||||
public void execute() {
|
||||
|
||||
// Set global objects
|
||||
// This block is not in initialization as we want to assure that all invocations
|
||||
// of this manipulation will get the same value (i.e. to prevent inconsistent behavior
|
||||
// if variable was changed during an execution of the manipulation)
|
||||
for(String k: globalObjects.keySet()){
|
||||
engine.put(k, globalObjects.get(k));
|
||||
}
|
||||
|
||||
try {
|
||||
engine.eval(jythonCall);
|
||||
engine.eval(jythonCall+"\n");
|
||||
} catch (ScriptException e) {
|
||||
throw new RuntimeException("Action failed while executing the Jython script",e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#abort()
|
||||
*/
|
||||
@Override
|
||||
public void abort() {
|
||||
// TODO need to find a way to abort script execution
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Nothing to be done
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,13 +29,10 @@ import java.util.logging.Logger;
|
||||
import ch.psi.fda.core.Action;
|
||||
|
||||
/**
|
||||
* Action that executes a specified script when it is executed.
|
||||
* @author ebner
|
||||
*
|
||||
* Action that executes a specified command when it is executed.
|
||||
*/
|
||||
public class ShellAction implements Action{
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ShellAction.class.getName());
|
||||
|
||||
private volatile Process process;
|
||||
@@ -50,8 +47,7 @@ public class ShellAction implements Action{
|
||||
private final String script;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param script Name of the script to execute when this action is invoked
|
||||
* @param script Name of the command to execute when this action is invoked
|
||||
*
|
||||
* @throws IllegalArgumentException Specified script does not exist
|
||||
*/
|
||||
@@ -64,15 +60,6 @@ public class ShellAction implements Action{
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#execute()
|
||||
*/
|
||||
/**
|
||||
* @throws InterruptedException
|
||||
* @throws RuntimeException Script did not exit with 0,
|
||||
* Execution was interrupted,
|
||||
* IO problem occurred
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws InterruptedException {
|
||||
try{
|
||||
@@ -84,7 +71,7 @@ public class ShellAction implements Action{
|
||||
// Log output of the shell script if loglevel is finest
|
||||
if(logger.isLoggable(Level.FINEST)){
|
||||
logger.finest("STDOUT [BEGIN]");
|
||||
// TODO The readout of the stream should be in parallel to the processing of the script! I.e. the output appears in the log as it is generated by the script!
|
||||
// Ideally the readout of the stream should be in parallel to the processing of the script! I.e. the output appears in the log as it is generated by the script!
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
String line = null;
|
||||
while((line=reader.readLine()) != null){
|
||||
@@ -93,7 +80,7 @@ public class ShellAction implements Action{
|
||||
logger.finest("STDOUT [END]");
|
||||
|
||||
logger.finest("STDERR [BEGIN]");
|
||||
// TODO The readout of the stream should be in parallel to the processing of the script! I.e. the output appears in the log as it is generated by the script!
|
||||
// Ideally the readout of the stream should be in parallel to the processing of the script! I.e. the output appears in the log as it is generated by the script!
|
||||
reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
||||
line = null;
|
||||
while((line=reader.readLine()) != null){
|
||||
@@ -113,61 +100,33 @@ public class ShellAction implements Action{
|
||||
throw new RuntimeException("Script ["+script+"] returned with an exit value not equal to 0");
|
||||
}
|
||||
}
|
||||
process = null; // Ensure that the process is null
|
||||
process = null;
|
||||
}
|
||||
catch(IOException e){
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new RuntimeException("Unable to execute script: "+script,e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#abort()
|
||||
*/
|
||||
@Override
|
||||
public void abort() {
|
||||
abort=true;
|
||||
// This action cannot be aborted, therefore this function is not implemented.
|
||||
if(process!=null){
|
||||
// Terminate process via kill
|
||||
process.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Nothing to be done
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the checkExitValue
|
||||
*/
|
||||
public boolean isCheckExitValue() {
|
||||
return checkExitValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param checkExitValue the checkExitValue to set
|
||||
*/
|
||||
public void setCheckExitValue(boolean checkExitValue) {
|
||||
this.checkExitValue = checkExitValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the exitValue
|
||||
*/
|
||||
public int getExitValue() {
|
||||
return exitValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exitValue the exitValue to set
|
||||
*/
|
||||
public void setExitValue(int exitValue) {
|
||||
this.exitValue = exitValue;
|
||||
}
|
||||
|
||||
@@ -25,43 +25,18 @@ import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.Actor;
|
||||
import ch.psi.fda.core.EngineConfiguration;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* This actuator sets an Channel Access channel from a start to an end value by doing discrete steps.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ChannelAccessFunctionActuator<T> implements Actor {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessFunctionActuator.class.getName());
|
||||
|
||||
private boolean asynchronous = false;
|
||||
|
||||
/**
|
||||
* Start value of the actuator
|
||||
*/
|
||||
private double start;
|
||||
|
||||
/**
|
||||
* End value of the actuator
|
||||
*/
|
||||
private double end;
|
||||
|
||||
/**
|
||||
* Step size of the move
|
||||
*/
|
||||
private double stepSize;
|
||||
|
||||
/**
|
||||
* Move direction (start<end = 1, start>end = -1)
|
||||
*/
|
||||
private int direction;
|
||||
private int direction; // Move direction (start<end = 1, start>end = -1)
|
||||
|
||||
/**
|
||||
* Execution count of actuator. This variable is used to minimize the floating point
|
||||
@@ -87,14 +62,9 @@ public class ChannelAccessFunctionActuator<T> implements Actor {
|
||||
private double accuracy;
|
||||
|
||||
/**
|
||||
* Channel Access channel of the actuator
|
||||
* Move timeout
|
||||
*/
|
||||
private Channel<Double> channel;
|
||||
|
||||
/**
|
||||
* Channel Access channel of the actuator
|
||||
*/
|
||||
private Channel<T> doneChannel = null;
|
||||
private Long timeout;
|
||||
|
||||
private final T doneValue;
|
||||
private final long doneDelay;
|
||||
@@ -103,13 +73,11 @@ public class ChannelAccessFunctionActuator<T> implements Actor {
|
||||
private final double originalEnd;
|
||||
private final int originalDirection;
|
||||
|
||||
|
||||
/**
|
||||
* Move timeout
|
||||
*/
|
||||
private Long timeout;
|
||||
private Channel<Double> channel;
|
||||
private Channel<T> doneChannel = null;
|
||||
|
||||
private final Function function;
|
||||
private boolean checkActorSet = true;
|
||||
|
||||
/**
|
||||
* Constructor - Initialize actor
|
||||
@@ -119,14 +87,14 @@ public class ChannelAccessFunctionActuator<T> implements Actor {
|
||||
* @param stepSize
|
||||
* @param timeout Maximum move time (in milliseconds)
|
||||
*/
|
||||
public ChannelAccessFunctionActuator(ChannelService s, String channelName, Function function, double start, double end, double stepSize, Long timeout){
|
||||
this(s, channelName, null, null, 0, function, start, end, stepSize, timeout);
|
||||
public ChannelAccessFunctionActuator(Channel<Double> channel, Function function, double start, double end, double stepSize, Long timeout){
|
||||
this(channel, null, null, 0, function, start, end, stepSize, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param channelName
|
||||
* @param doneChannelName If null actor will not wait (for this channel) to continue
|
||||
* @param channel
|
||||
* @param doneChannel If null actor will not wait (for this channel) to continue
|
||||
* @param doneValue
|
||||
* @param doneDelay Delay in seconds before checking the done channel
|
||||
* @param start
|
||||
@@ -134,8 +102,7 @@ public class ChannelAccessFunctionActuator<T> implements Actor {
|
||||
* @param stepSize
|
||||
* @param timeout Maximum move time (in milliseconds)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChannelAccessFunctionActuator(ChannelService s, String channelName, String doneChannelName, T doneValue, double doneDelay, Function function, double start, double end, double stepSize, Long timeout){
|
||||
public ChannelAccessFunctionActuator(Channel<Double> channel, Channel<T> doneChannel, T doneValue, double doneDelay, Function function, double start, double end, double stepSize, Long timeout){
|
||||
|
||||
this.doneValue = doneValue;
|
||||
this.doneDelay = (long) Math.floor((doneDelay*1000));
|
||||
@@ -170,31 +137,10 @@ public class ChannelAccessFunctionActuator<T> implements Actor {
|
||||
this.originalEnd = end;
|
||||
this.originalDirection = direction;
|
||||
|
||||
|
||||
// Initialize/create Channel Access channel
|
||||
try {
|
||||
channel = s.createChannel(new ChannelDescriptor<>(Double.class, channelName, false));
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
}
|
||||
if(doneChannelName != null){
|
||||
try {
|
||||
doneChannel = s.createChannel(new ChannelDescriptor<>((Class<T>)doneValue.getClass(), doneChannelName, false));
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+doneChannelName+"]",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize actuator channel [name:"+doneChannelName+"]",e);
|
||||
}
|
||||
}
|
||||
this.channel = channel;
|
||||
this.doneChannel = doneChannel;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.engine.Actor#set()
|
||||
*/
|
||||
@Override
|
||||
public void set() throws InterruptedException {
|
||||
|
||||
@@ -226,7 +172,7 @@ public class ChannelAccessFunctionActuator<T> implements Actor {
|
||||
}
|
||||
|
||||
// Check whether the set value is really on the value that was set before.
|
||||
if(EngineConfiguration.getInstance().isCheckActorSet()){
|
||||
if(checkActorSet){
|
||||
double c = channel.getValue(true);
|
||||
double a = Math.abs( c - fvalue );
|
||||
if ( a > accuracy ){
|
||||
@@ -234,8 +180,7 @@ public class ChannelAccessFunctionActuator<T> implements Actor {
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ChannelException | ExecutionException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
} catch (ExecutionException | TimeoutException | ChannelException e) {
|
||||
throw new RuntimeException("Unable to move actuator [channel: "+channel.getName()+"] to value "+value,e);
|
||||
}
|
||||
|
||||
@@ -258,17 +203,11 @@ public class ChannelAccessFunctionActuator<T> implements Actor {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.engine.Actor#hasNext()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#init()
|
||||
*/
|
||||
@Override
|
||||
public void init() {
|
||||
this.count = 0;
|
||||
@@ -278,16 +217,12 @@ public class ChannelAccessFunctionActuator<T> implements Actor {
|
||||
if(start>end){
|
||||
direction=-1; // Move in negative direction
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Set first set value to the start value
|
||||
this.value = start;
|
||||
this.next = true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#reverse()
|
||||
*/
|
||||
@Override
|
||||
public synchronized void reverse() {
|
||||
double oldStart = start;
|
||||
@@ -302,9 +237,6 @@ public class ChannelAccessFunctionActuator<T> implements Actor {
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#reset()
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
this.start = this.originalStart;
|
||||
@@ -312,42 +244,10 @@ public class ChannelAccessFunctionActuator<T> implements Actor {
|
||||
this.direction = this.originalDirection;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy channel
|
||||
try {
|
||||
logger.finest("Destroy actor channel: "+channel.getName());
|
||||
channel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
|
||||
// Destroy done channel if exists
|
||||
if(doneChannel != null){
|
||||
try {
|
||||
logger.finest("Destroy actor done channel: "+doneChannel.getName());
|
||||
doneChannel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the asynchronous
|
||||
*/
|
||||
public boolean isAsynchronous() {
|
||||
return asynchronous;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param asynchronous the asynchronous to set
|
||||
*/
|
||||
public void setAsynchronous(boolean asynchronous) {
|
||||
this.asynchronous = asynchronous;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,42 +25,21 @@ import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.Actor;
|
||||
import ch.psi.fda.core.EngineConfiguration;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* This actuator sets an Channel Access channel from a start to an end value by doing discrete steps.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ChannelAccessLinearActuator<T> implements Actor {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessLinearActuator.class.getName());
|
||||
|
||||
private boolean asynchronous = false;
|
||||
|
||||
/**
|
||||
* Start value of the actuator
|
||||
*/
|
||||
private double start;
|
||||
|
||||
/**
|
||||
* End value of the actuator
|
||||
*/
|
||||
private double end;
|
||||
|
||||
/**
|
||||
* Step size of the move
|
||||
*/
|
||||
private double stepSize;
|
||||
|
||||
/**
|
||||
* Move direction (start<end = 1, start>end = -1)
|
||||
*/
|
||||
private int direction;
|
||||
|
||||
/**
|
||||
@@ -86,15 +65,7 @@ public class ChannelAccessLinearActuator<T> implements Actor {
|
||||
*/
|
||||
private double accuracy;
|
||||
|
||||
/**
|
||||
* Channel Access channel of the actuator
|
||||
*/
|
||||
private Channel<Double> channel;
|
||||
|
||||
/**
|
||||
* Channel Access channel of the actuator
|
||||
*/
|
||||
private Channel<T> doneChannel = null;
|
||||
|
||||
private final T doneValue;
|
||||
private final long doneDelay;
|
||||
@@ -103,17 +74,17 @@ public class ChannelAccessLinearActuator<T> implements Actor {
|
||||
private final double originalEnd;
|
||||
private final int originalDirection;
|
||||
|
||||
private Long timeout; // Set timeout
|
||||
|
||||
/**
|
||||
* Move timeout
|
||||
*/
|
||||
private Long timeout;
|
||||
private final Channel<Double> channel;
|
||||
private final Channel<T> doneChannel;
|
||||
|
||||
private boolean checkActorSet = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param channelName
|
||||
* @param doneChannelName If null actor will not wait (for this channel) to continue
|
||||
* @param channel
|
||||
* @param doneChannel If null actor will not wait (for this channel) to continue
|
||||
* @param doneValue
|
||||
* @param doneDelay Delay in seconds before checking the done channel
|
||||
* @param start
|
||||
@@ -121,8 +92,7 @@ public class ChannelAccessLinearActuator<T> implements Actor {
|
||||
* @param stepSize
|
||||
* @param timeout Maximum move time (in milliseconds)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChannelAccessLinearActuator(ChannelService s, String channelName, String doneChannelName, T doneValue, double doneDelay, double start, double end, double stepSize, Long timeout){
|
||||
public ChannelAccessLinearActuator(Channel<Double> channel, Channel<T> doneChannel, T doneValue, double doneDelay, double start, double end, double stepSize, Long timeout){
|
||||
|
||||
this.doneValue = doneValue;
|
||||
this.doneDelay = (long) Math.floor((doneDelay*1000));
|
||||
@@ -152,31 +122,10 @@ public class ChannelAccessLinearActuator<T> implements Actor {
|
||||
this.originalEnd = end;
|
||||
this.originalDirection = direction;
|
||||
|
||||
|
||||
// Initialize/create Channel Access channel
|
||||
try {
|
||||
channel = s.createChannel(new ChannelDescriptor<>(Double.class, channelName, false));
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
}
|
||||
if(doneChannelName != null){
|
||||
try {
|
||||
doneChannel = s.createChannel(new ChannelDescriptor<>((Class<T>) doneValue.getClass(), doneChannelName, false));
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+doneChannelName+"]",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize actuator channel [name:"+doneChannelName+"]",e);
|
||||
}
|
||||
}
|
||||
this.channel = channel;
|
||||
this.doneChannel = doneChannel;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.engine.Actor#set()
|
||||
*/
|
||||
@Override
|
||||
public void set() throws InterruptedException {
|
||||
|
||||
@@ -207,7 +156,7 @@ public class ChannelAccessLinearActuator<T> implements Actor {
|
||||
}
|
||||
|
||||
// Check whether the set value is really on the value that was set before.
|
||||
if(EngineConfiguration.getInstance().isCheckActorSet()){
|
||||
if(checkActorSet){
|
||||
double c = channel.getValue(true);
|
||||
double a = Math.abs( c - value );
|
||||
if ( a > accuracy ){
|
||||
@@ -215,8 +164,7 @@ public class ChannelAccessLinearActuator<T> implements Actor {
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ChannelException | TimeoutException | ExecutionException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
} catch (ExecutionException | TimeoutException | ChannelException e) {
|
||||
throw new RuntimeException("Unable to move actuator [channel: "+channel.getName()+"] to value "+value,e);
|
||||
}
|
||||
|
||||
@@ -235,17 +183,11 @@ public class ChannelAccessLinearActuator<T> implements Actor {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.engine.Actor#hasNext()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#init()
|
||||
*/
|
||||
@Override
|
||||
public void init() {
|
||||
this.count = 0;
|
||||
@@ -262,9 +204,6 @@ public class ChannelAccessLinearActuator<T> implements Actor {
|
||||
this.next = true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#reverse()
|
||||
*/
|
||||
@Override
|
||||
public synchronized void reverse() {
|
||||
double oldStart = start;
|
||||
@@ -279,9 +218,6 @@ public class ChannelAccessLinearActuator<T> implements Actor {
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#reset()
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
this.start = this.originalStart;
|
||||
@@ -289,44 +225,10 @@ public class ChannelAccessLinearActuator<T> implements Actor {
|
||||
this.direction = this.originalDirection;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy channel
|
||||
try {
|
||||
logger.finest("Destroy actor channel: "+channel.getName());
|
||||
channel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
|
||||
// Destroy done channel if exists
|
||||
if(doneChannel != null){
|
||||
try {
|
||||
logger.finest("Destroy actor done channel: "+doneChannel.getName());
|
||||
doneChannel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the asynchronous
|
||||
*/
|
||||
public boolean isAsynchronous() {
|
||||
return asynchronous;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param asynchronous the asynchronous to set
|
||||
*/
|
||||
public void setAsynchronous(boolean asynchronous) {
|
||||
this.asynchronous = asynchronous;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -25,11 +25,8 @@ import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.Actor;
|
||||
import ch.psi.fda.core.EngineConfiguration;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* This actuator sets an Channel Access channel by using the positions from the given table.
|
||||
@@ -38,7 +35,6 @@ import ch.psi.jcae.ChannelService;
|
||||
*/
|
||||
public class ChannelAccessTableActuator<T> implements Actor {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessTableActuator.class.getName());
|
||||
|
||||
private boolean asynchronous = false;
|
||||
@@ -66,14 +62,7 @@ public class ChannelAccessTableActuator<T> implements Actor {
|
||||
private boolean next;
|
||||
|
||||
|
||||
/**
|
||||
* Channel Access channel of the actuator
|
||||
*/
|
||||
private Channel<Double> channel;
|
||||
|
||||
/**
|
||||
* Channel Access channel of the actuator
|
||||
*/
|
||||
private Channel<T> doneChannel = null;
|
||||
|
||||
private final T doneValue;
|
||||
@@ -90,6 +79,7 @@ public class ChannelAccessTableActuator<T> implements Actor {
|
||||
*/
|
||||
private Long timeout = null;
|
||||
|
||||
private boolean checkActorSet = true;
|
||||
|
||||
/**
|
||||
* Constructor - Initialize actor
|
||||
@@ -97,21 +87,20 @@ public class ChannelAccessTableActuator<T> implements Actor {
|
||||
* @param table Position table with the explicit positions for each step
|
||||
* @param timeout Maximum move time (in milliseconds)
|
||||
*/
|
||||
public ChannelAccessTableActuator(ChannelService s, String channelName, double[] table, Long timeout){
|
||||
this(s, channelName, null, null, 0, table, timeout);
|
||||
public ChannelAccessTableActuator(Channel<Double> channel, double[] table, Long timeout){
|
||||
this(channel, null, null, 0, table, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param channelName
|
||||
* @param doneChannelName
|
||||
* @param channel
|
||||
* @param doneChannel
|
||||
* @param doneValue
|
||||
* @param doneDelay
|
||||
* @param table
|
||||
* @param timeout Maximum move time (in milliseconds)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChannelAccessTableActuator(ChannelService s, String channelName, String doneChannelName, T doneValue, double doneDelay, double[] table, Long timeout){
|
||||
public ChannelAccessTableActuator(Channel<Double> channel, Channel<T> doneChannel, T doneValue, double doneDelay, double[] table, Long timeout){
|
||||
|
||||
this.doneValue = doneValue;
|
||||
this.doneDelay = (long) Math.floor((doneDelay*1000));
|
||||
@@ -138,31 +127,10 @@ public class ChannelAccessTableActuator<T> implements Actor {
|
||||
// Save the initial direction
|
||||
this.originalPositiveDirection = positiveDirection;
|
||||
|
||||
// Initialize/create Channel Access channel
|
||||
try {
|
||||
channel = s.createChannel(new ChannelDescriptor<>(Double.class, channelName, false));
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize actuator channel [name:"+channelName+"]",e);
|
||||
}
|
||||
|
||||
if(doneChannelName != null){
|
||||
try {
|
||||
doneChannel = s.createChannel(new ChannelDescriptor<>((Class<T>)doneValue.getClass(), doneChannelName, false));
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+doneChannelName+"]",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize actuator channel [name:"+doneChannelName+"]",e);
|
||||
}
|
||||
}
|
||||
this.channel = channel;
|
||||
this.doneChannel = doneChannel;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.engine.Actor#set()
|
||||
*/
|
||||
@Override
|
||||
public void set() throws InterruptedException {
|
||||
|
||||
@@ -193,14 +161,13 @@ public class ChannelAccessTableActuator<T> implements Actor {
|
||||
}
|
||||
|
||||
// Check whether the set value is really on the value that was set before.
|
||||
if(doneChannel==null && !asynchronous && EngineConfiguration.getInstance().isCheckActorSet()){
|
||||
if(doneChannel==null && !asynchronous && checkActorSet){
|
||||
if ( Math.abs( channel.getValue() - table[count] ) > accuracy ){
|
||||
throw new RuntimeException("Actor could not be set to the value "+table[count]+" The readback of the set value does not match the value that was set");
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ChannelException | ExecutionException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
} catch (ExecutionException | ChannelException | TimeoutException e) {
|
||||
throw new RuntimeException("Move actuator [channel: "+channel.getName()+"] to value "+table[count],e);
|
||||
}
|
||||
|
||||
@@ -226,17 +193,11 @@ public class ChannelAccessTableActuator<T> implements Actor {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.engine.Actor#hasNext()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#init()
|
||||
*/
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
@@ -253,9 +214,6 @@ public class ChannelAccessTableActuator<T> implements Actor {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#reverse()
|
||||
*/
|
||||
@Override
|
||||
public void reverse() {
|
||||
if(positiveDirection){
|
||||
@@ -266,52 +224,15 @@ public class ChannelAccessTableActuator<T> implements Actor {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#reset()
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
this.positiveDirection = this.originalPositiveDirection;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy channel
|
||||
try {
|
||||
logger.finest("Destroy actor channel: "+channel.getName());
|
||||
channel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
|
||||
// Destroy done channel if exists
|
||||
if(doneChannel != null){
|
||||
try {
|
||||
logger.finest("Destroy actor done channel: "+doneChannel.getName());
|
||||
doneChannel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the asynchronous
|
||||
*/
|
||||
public boolean isAsynchronous() {
|
||||
return asynchronous;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param asynchronous the asynchronous to set
|
||||
*/
|
||||
public void setAsynchronous(boolean asynchronous) {
|
||||
this.asynchronous = asynchronous;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -31,13 +31,9 @@ import ch.psi.fda.core.Actor;
|
||||
* steps of the actors that this actuator consists of.
|
||||
* First all the steps of the first actor are used, after that the steps of the next actor are done.
|
||||
* Before the first step of an actor pre actions are available and after the last step of an actor a post action is available.
|
||||
*
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ComplexActuator implements Actor {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ComplexActuator.class.getName());
|
||||
|
||||
/**
|
||||
@@ -76,9 +72,6 @@ public class ComplexActuator implements Actor {
|
||||
*/
|
||||
private boolean firstrun;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ComplexActuator(){
|
||||
this.actors = new ArrayList<Actor>();
|
||||
this.preActions = new ArrayList<Action>();
|
||||
@@ -90,12 +83,8 @@ public class ComplexActuator implements Actor {
|
||||
this.firstrun = true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#set()
|
||||
*/
|
||||
@Override
|
||||
public void set() throws InterruptedException {
|
||||
// Throw an IllegalStateException in the case that set is called although there is no next step.
|
||||
if(!next){
|
||||
throw new IllegalStateException("The actuator does not have any next step.");
|
||||
}
|
||||
@@ -139,20 +128,13 @@ public class ComplexActuator implements Actor {
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#hasNext()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#init()
|
||||
*/
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
// Initialize all actors this actor consist of
|
||||
for(Actor a: actors){
|
||||
a.init();
|
||||
@@ -191,9 +173,6 @@ public class ComplexActuator implements Actor {
|
||||
this.firstrun = true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#reverse()
|
||||
*/
|
||||
@Override
|
||||
public void reverse() {
|
||||
// Reverse all actors this actor consist of
|
||||
@@ -202,9 +181,6 @@ public class ComplexActuator implements Actor {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#reset()
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
// Reset all actors this actor consist of
|
||||
@@ -213,49 +189,13 @@ public class ComplexActuator implements Actor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of actors of this ComplexActor
|
||||
* @return the actors
|
||||
*/
|
||||
public List<Actor> getActors() {
|
||||
return actors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the preActions
|
||||
*/
|
||||
public List<Action> getPreActions() {
|
||||
return preActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the postActions
|
||||
*/
|
||||
public List<Actor> getActors() {
|
||||
return actors;
|
||||
}
|
||||
public List<Action> getPostActions() {
|
||||
return postActions;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy preActions
|
||||
for(Action a: preActions){
|
||||
a.destroy();
|
||||
}
|
||||
|
||||
// Destroy actors
|
||||
for(Actor a: actors){
|
||||
a.destroy();
|
||||
}
|
||||
|
||||
// Destroy postActions
|
||||
for(Action a: postActions){
|
||||
a.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -19,10 +19,6 @@
|
||||
|
||||
package ch.psi.fda.core.actors;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public interface Function {
|
||||
public double calculate(double parameter);
|
||||
}
|
||||
|
||||
@@ -30,28 +30,23 @@ import javax.script.ScriptException;
|
||||
|
||||
import ch.psi.fda.core.scripting.JythonGlobalVariable;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class JythonFunction implements Function {
|
||||
|
||||
// Get Logger
|
||||
private static final Logger logger = Logger.getLogger(JythonFunction.class.getName());
|
||||
|
||||
public static final String ENTRY_FUNCTION_NAME = "calculate";
|
||||
private static final String ENTRY_FUNCTION_PATTERN = "def "+ENTRY_FUNCTION_NAME+"\\((.*)\\):";
|
||||
|
||||
/**
|
||||
* Script engine of the manipulator
|
||||
*/
|
||||
private ScriptEngine engine;
|
||||
|
||||
private String additionalParameter = "";
|
||||
|
||||
|
||||
public JythonFunction(String script, Map<String, JythonGlobalVariable> map){
|
||||
// Create new script engine
|
||||
|
||||
// Workaround for Jython memory leak
|
||||
// http://blog.hillbrecht.de/2009/07/11/jython-memory-leakout-of-memory-problem/
|
||||
System.setProperty("python.options.internalTablesImpl","weak");
|
||||
|
||||
this.engine = new ScriptEngineManager().getEngineByName("python");
|
||||
|
||||
// Determine script entry function and the function parameters
|
||||
@@ -95,9 +90,6 @@ public class JythonFunction implements Function {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.actors.Function#calculate(double)
|
||||
*/
|
||||
@Override
|
||||
public double calculate(double parameter) {
|
||||
logger.fine("Function called");
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.actors;
|
||||
|
||||
import ch.psi.fda.core.Actor;
|
||||
|
||||
/**
|
||||
* Special actuator for the OTFLoop. This type of actor must not be used in any other
|
||||
* type of loop than OTFLoop. If it is used it will, depending on the loop, immediately stop the loop
|
||||
* as it no single step.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class OTFActuator implements Actor {
|
||||
|
||||
/**
|
||||
* Name of the motor channel
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Channel name of the encoder;
|
||||
*/
|
||||
private final String readback;
|
||||
|
||||
private double start;
|
||||
private double end;
|
||||
private final double stepSize;
|
||||
private final double integrationTime;
|
||||
|
||||
private final String id;
|
||||
|
||||
/**
|
||||
* Additional backlash for the motor
|
||||
*/
|
||||
private final double additionalBacklash;
|
||||
|
||||
|
||||
public OTFActuator(String id, String name, String readback, double start, double end, double stepSize, double integrationTime, double additionalBacklash){
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.readback = readback;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.stepSize = stepSize;
|
||||
this.integrationTime = integrationTime;
|
||||
this.additionalBacklash = additionalBacklash;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#set()
|
||||
*/
|
||||
@Override
|
||||
public void set() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#hasNext()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the readback
|
||||
*/
|
||||
public String getReadback() {
|
||||
return readback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the start
|
||||
*/
|
||||
public double getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the end
|
||||
*/
|
||||
public double getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the stepSize
|
||||
*/
|
||||
public double getStepSize() {
|
||||
return stepSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the integrationTime
|
||||
*/
|
||||
public double getIntegrationTime() {
|
||||
return integrationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the additionalBacklash
|
||||
*/
|
||||
public double getAdditionalBacklash() {
|
||||
return additionalBacklash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#init()
|
||||
*/
|
||||
@Override
|
||||
public void init() {
|
||||
// Not implemented
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#reverse()
|
||||
*/
|
||||
@Override
|
||||
public void reverse() {
|
||||
// Not implemented
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#reset()
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
// Not implemented
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Nothing to be done
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param start the start to set
|
||||
*/
|
||||
public void setStart(double start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param end the end to set
|
||||
*/
|
||||
public void setEnd(double end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,8 +24,6 @@ import ch.psi.fda.core.Sensor;
|
||||
|
||||
/**
|
||||
* Pseudo actor that is literally doing nothing for n times
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class PseudoActuatorSensor implements Actor, Sensor {
|
||||
|
||||
@@ -42,7 +40,6 @@ public class PseudoActuatorSensor implements Actor, Sensor {
|
||||
private final String id;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param counts
|
||||
* @param id Id of the Actor/Sensor
|
||||
*/
|
||||
@@ -57,13 +54,8 @@ public class PseudoActuatorSensor implements Actor, Sensor {
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#set()
|
||||
*/
|
||||
@Override
|
||||
public void set() {
|
||||
|
||||
// Throw an IllegalStateException in the case that set is called although there is no next step.
|
||||
if(!hasNext()){
|
||||
throw new IllegalStateException("The actuator does not have any next step.");
|
||||
}
|
||||
@@ -71,65 +63,31 @@ public class PseudoActuatorSensor implements Actor, Sensor {
|
||||
count++;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#hasNext()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return (count<counts);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#init()
|
||||
*/
|
||||
@Override
|
||||
public void init() {
|
||||
count=0; // Set count back to 0
|
||||
count=0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#reverse()
|
||||
*/
|
||||
@Override
|
||||
public void reverse() {
|
||||
// Not implemented
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#reset()
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
// NOt implemented
|
||||
}
|
||||
|
||||
|
||||
// Sensor implementation
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#read()
|
||||
*/
|
||||
@Override
|
||||
public Object read() {
|
||||
return new Double(count); // Return actual count
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#getId()
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Actor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Nothing to be done
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.collector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.messages.ComponentMetadata;
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import ch.psi.fda.core.messages.StreamDelimiterMessage;
|
||||
import ch.psi.fda.core.messages.EndOfStreamMessage;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
|
||||
/**
|
||||
* Collector class that is collecting and merging data from different Queues.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class Collector implements Runnable{
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(Collector.class.getName());
|
||||
|
||||
/**
|
||||
* List of queues and their metadata this collector is responsible to readout.
|
||||
* The logic is as follows:
|
||||
* Read out the last queue until the first queue in the list has the EndOfLoopMessage.
|
||||
*/
|
||||
private List<DataQueue> queues;
|
||||
|
||||
/**
|
||||
* Outgoing queue of this collector
|
||||
*/
|
||||
private BlockingQueue<Message> outQueue;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public Collector(){
|
||||
queues = new ArrayList<DataQueue>();
|
||||
outQueue = new LinkedBlockingQueue<Message>(1000); // Create bounded queue to prevent running out of memory ...
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if(queues.size()>0){
|
||||
try{
|
||||
readQueue(0, null);
|
||||
}
|
||||
catch(InterruptedException e){
|
||||
// Readout aborted through interrupt
|
||||
}
|
||||
}
|
||||
else{
|
||||
// No queue registered for reading
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
outQueue.put(new EndOfStreamMessage());
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Stop loop and exit logic instead of throwing an Exception
|
||||
throw new RuntimeException("Unable to terminate stream with and End of Stream Message",e);
|
||||
}
|
||||
|
||||
logger.info("END");
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void readQueue(int index, DataMessage m) throws InterruptedException{
|
||||
|
||||
BlockingQueue<Message> q = queues.get(index).getQueue();
|
||||
|
||||
// Read Message
|
||||
Message message = q.take();
|
||||
while(message instanceof DataMessage){
|
||||
// Create new data message
|
||||
DataMessage dm = new DataMessage();
|
||||
if(m!=null){
|
||||
dm.getData().addAll(m.getData());
|
||||
}
|
||||
|
||||
dm.getData().addAll(((DataMessage)message).getData());
|
||||
|
||||
if(index<(queues.size()-1)){
|
||||
readQueue(index+1, dm);
|
||||
}
|
||||
else{
|
||||
// Write message to outgoing queue
|
||||
outQueue.put(dm);
|
||||
}
|
||||
|
||||
// Read next message
|
||||
message = q.take();
|
||||
}
|
||||
|
||||
if(message instanceof EndOfStreamMessage){
|
||||
// Translate EndOfStream to StreamDelimiter message
|
||||
StreamDelimiterMessage ddm = new StreamDelimiterMessage(queues.size()-1-index, ((EndOfStreamMessage)message).isIflag());
|
||||
// Write message to outgoing queue
|
||||
outQueue.put(ddm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the queues
|
||||
*/
|
||||
public List<DataQueue> getQueues() {
|
||||
return queues;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the outgoing data queue.
|
||||
* Attention, only call this method after all ingoing queues were registered! Otherwise the data returned
|
||||
* by this method is not accurate.
|
||||
* @return output queue of collector
|
||||
*/
|
||||
public DataQueue getOutQueue(){
|
||||
DataMessageMetadata dataMessageMetadata = new DataMessageMetadata();
|
||||
dataMessageMetadata.getComponents();
|
||||
|
||||
// Generate new combined metadata and add dimension information to the components
|
||||
int nq = queues.size();
|
||||
for(int i=0;i<nq;i++){
|
||||
DataQueue q = queues.get(i);
|
||||
for(ComponentMetadata cm: q.getDataMessageMetadata().getComponents()){
|
||||
// The dimension number is the number of queues minus the index of the current queue minus 1 (because dimension index starts at 0)
|
||||
dataMessageMetadata.getComponents().add(new ComponentMetadata(cm.getId(), nq-i-1));
|
||||
}
|
||||
}
|
||||
|
||||
return(new DataQueue(outQueue, dataMessageMetadata));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.collector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import ch.psi.fda.core.messages.EndOfStreamMessage;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
|
||||
/**
|
||||
* Serialize data received by a DataQueue
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class DataDispatcher implements Runnable{
|
||||
|
||||
private DataQueue queue;
|
||||
private List<DataQueue> outQueues;
|
||||
|
||||
public DataDispatcher(DataQueue queue){
|
||||
this.queue = queue;
|
||||
this.outQueues = new ArrayList<DataQueue>();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try{
|
||||
|
||||
// TODO Need to synchronize message metadata
|
||||
// for(DataQueue q: outQueues){
|
||||
// }
|
||||
|
||||
// Dispatch Messages
|
||||
Message message = queue.getQueue().take();
|
||||
while(!(message instanceof EndOfStreamMessage)){
|
||||
|
||||
// Clone message ...
|
||||
for(DataQueue q: outQueues){
|
||||
q.getQueue().put(message);
|
||||
}
|
||||
|
||||
// Read next message
|
||||
message = queue.getQueue().take();
|
||||
}
|
||||
|
||||
// Write end of stream message
|
||||
for(DataQueue q: outQueues){
|
||||
q.getQueue().put(message);
|
||||
}
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Stop loop and exit logic instead of throwing an Exception
|
||||
throw new RuntimeException("Data serializer was interrupted while writing data to file",e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the outQueues
|
||||
*/
|
||||
public List<DataQueue> getOutQueues() {
|
||||
return outQueues;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -32,33 +32,24 @@ import ch.psi.jcae.ChannelException;
|
||||
|
||||
/**
|
||||
* Guard checking channels to meet a certain condition
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ChannelAccessGuard implements Guard {
|
||||
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessGuard.class.getName());
|
||||
|
||||
/**
|
||||
* Flag to indicate whether a guard condition failed since the last init call
|
||||
* true: all conditions met, false: at least one condition failed
|
||||
*/
|
||||
private boolean check = true;
|
||||
private volatile boolean check = true;
|
||||
|
||||
private final List<ChannelAccessGuardCondition> conditions;
|
||||
private final List<ChannelAccessGuardCondition<?>> conditions;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param conditions
|
||||
*/
|
||||
public ChannelAccessGuard(List<ChannelAccessGuardCondition> conditions){
|
||||
public ChannelAccessGuard(List<ChannelAccessGuardCondition<?>> conditions){
|
||||
|
||||
this.conditions = conditions;
|
||||
|
||||
// Create channel that contribute to the status of the guard
|
||||
for(final ChannelAccessGuardCondition condition: conditions){
|
||||
for(final ChannelAccessGuardCondition<?> condition: conditions){
|
||||
condition.getChannel().addPropertyChangeListener(new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
@@ -70,49 +61,29 @@ public class ChannelAccessGuard implements Guard {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Guard#init()
|
||||
*/
|
||||
@Override
|
||||
public void init() {
|
||||
check = true;
|
||||
|
||||
// Check one time if all conditions are met
|
||||
for(ChannelAccessGuardCondition condition: conditions){
|
||||
for(ChannelAccessGuardCondition<?> condition: conditions){
|
||||
try{
|
||||
if(! (condition.getChannel().getValue(true)).equals(condition.getValue()) ){
|
||||
check=false;
|
||||
// Early exit
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(ChannelException | TimeoutException | ExecutionException e){
|
||||
catch (InterruptedException e) {
|
||||
throw new RuntimeException("Guard interrupted ",e);
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
logger.log(Level.WARNING, "Unable ", e);
|
||||
check=false;
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Guard interrupted ",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Guard#check()
|
||||
*/
|
||||
@Override
|
||||
public boolean check() {
|
||||
return check;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Guard#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy Guard Conditions
|
||||
for(ChannelAccessGuardCondition condition: conditions){
|
||||
condition.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,80 +19,23 @@
|
||||
|
||||
package ch.psi.fda.core.guard;
|
||||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* Channel and condition that need to be met.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ChannelAccessGuardCondition {
|
||||
public class ChannelAccessGuardCondition<T> {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessGuardCondition.class.getName());
|
||||
|
||||
/**
|
||||
* Channel name
|
||||
*/
|
||||
private final Channel<?> channel;
|
||||
|
||||
/**
|
||||
* Value of the channel to meet condition
|
||||
*/
|
||||
private final Object value;
|
||||
private final Channel<T> channel;
|
||||
private final T value; // Value of the channel to meet condition
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param channel Name of the channel that contributes to a guard
|
||||
* @param value
|
||||
*/
|
||||
public ChannelAccessGuardCondition(ChannelService s, String channel, Object value){
|
||||
try {
|
||||
this.channel = s.createChannel(new ChannelDescriptor<>(value.getClass(), channel, true));
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new IllegalArgumentException("Unable to initialize actuator channel [name:"+channel+"]",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize actuator channel [name:"+channel+"]",e);
|
||||
}
|
||||
public ChannelAccessGuardCondition(Channel<T> channel, T value){
|
||||
this.channel = channel;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the channel
|
||||
*/
|
||||
public Channel<?> getChannel() {
|
||||
public Channel<T> getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value
|
||||
*/
|
||||
public Object getValue() {
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy guard condition.
|
||||
* Can be used for the cleanup of used resources of the guard condition (e.g. to close connections, ...) if
|
||||
* this cannot be done automatically by the GarbageCollector.
|
||||
*
|
||||
* After calling this method the guard condition must not be used any more!
|
||||
*/
|
||||
public void destroy(){
|
||||
// Destroy channel
|
||||
try {
|
||||
logger.finest("Destroy guard condition channel: "+channel.getName());
|
||||
channel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,35 +21,29 @@ package ch.psi.fda.core.loops;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ch.psi.fda.core.Action;
|
||||
import ch.psi.fda.core.ActionLoop;
|
||||
import ch.psi.fda.core.Actor;
|
||||
import ch.psi.fda.core.ActorSetCallable;
|
||||
import ch.psi.fda.core.Guard;
|
||||
import ch.psi.fda.core.Sensor;
|
||||
import ch.psi.fda.core.messages.ComponentMetadata;
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import ch.psi.fda.core.messages.EndOfStreamMessage;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
import ch.psi.fda.core.messages.Metadata;
|
||||
|
||||
/**
|
||||
* Loop of actions to accomplish a task or test.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ActorSensorLoop implements ActionLoop {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ActorSensorLoop.class.getName());
|
||||
|
||||
/**
|
||||
@@ -101,12 +95,6 @@ public class ActorSensorLoop implements ActionLoop {
|
||||
*/
|
||||
private List<Sensor> sensors;
|
||||
|
||||
/**
|
||||
* Data queue sensor data is posted to. A message consists of a list of data objects
|
||||
* that are read out of the sensors of this loop.
|
||||
*/
|
||||
private BlockingQueue<Message> dataQueue;
|
||||
|
||||
/**
|
||||
* Guard used to check whether the environment was ok while reading out the sensors
|
||||
*/
|
||||
@@ -119,17 +107,13 @@ public class ActorSensorLoop implements ActionLoop {
|
||||
|
||||
private List<ActorSetCallable> pactors;
|
||||
|
||||
private EventBus eventBus = new EventBus();
|
||||
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public ActorSensorLoop(){
|
||||
this(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create instance of the
|
||||
*/
|
||||
public ActorSensorLoop(boolean zigZag){
|
||||
this.zigZag = zigZag;
|
||||
this.actionLoops = new ArrayList<ActionLoop>();
|
||||
@@ -143,14 +127,9 @@ public class ActorSensorLoop implements ActionLoop {
|
||||
this.actors = new ArrayList<Actor>();
|
||||
this.pactors = new ArrayList<ActorSetCallable>();
|
||||
this.sensors = new ArrayList<Sensor>();
|
||||
|
||||
this.dataQueue = new LinkedBlockingQueue<Message>(1000);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.engine.ActionLoop#execute()
|
||||
*/
|
||||
/**
|
||||
* Executes the actor sensor loop. The actor sensor loop is build up as follows:
|
||||
* preActions
|
||||
@@ -171,6 +150,14 @@ public class ActorSensorLoop implements ActionLoop {
|
||||
public void execute() throws InterruptedException {
|
||||
abort = false;
|
||||
|
||||
List<Metadata> metadata = new ArrayList<>();
|
||||
|
||||
// Build up data message metadata based on the sensors currently registered.
|
||||
for(Sensor s: sensors){
|
||||
metadata.add(new Metadata(s.getId()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thread pool for parallel execution of tasks
|
||||
*/
|
||||
@@ -294,7 +281,7 @@ public class ActorSensorLoop implements ActionLoop {
|
||||
}
|
||||
|
||||
// Read sensors
|
||||
DataMessage message = new DataMessage();
|
||||
DataMessage message = new DataMessage(metadata);
|
||||
for(Sensor sensor: sensors){
|
||||
// Readout sensor
|
||||
Object o = sensor.read();
|
||||
@@ -319,7 +306,7 @@ public class ActorSensorLoop implements ActionLoop {
|
||||
if(guardOK){
|
||||
|
||||
// Post a message with the sensor data
|
||||
dataQueue.put(message);
|
||||
eventBus.post(message);
|
||||
|
||||
// Loop all configured ActionLoop objects
|
||||
for(ActionLoop actionLoop: actionLoops){
|
||||
@@ -339,7 +326,7 @@ public class ActorSensorLoop implements ActionLoop {
|
||||
|
||||
// Issue end of loop control message
|
||||
// Set iflag of the EndOfStreamMessage according to dataGroup flag of this loop
|
||||
dataQueue.put(new EndOfStreamMessage(dataGroup));
|
||||
eventBus.post(new EndOfStreamMessage(dataGroup));
|
||||
}
|
||||
|
||||
if(zigZag){
|
||||
@@ -353,9 +340,6 @@ public class ActorSensorLoop implements ActionLoop {
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.engine.ActionLoop#abort()
|
||||
*/
|
||||
@Override
|
||||
public void abort(){
|
||||
abort = true;
|
||||
@@ -372,13 +356,8 @@ public class ActorSensorLoop implements ActionLoop {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#prepare()
|
||||
*/
|
||||
@Override
|
||||
public void prepare() {
|
||||
// Put in prepare code here
|
||||
|
||||
// Create callable for all actors
|
||||
pactors.clear();
|
||||
for(final Actor a: actors){
|
||||
@@ -396,195 +375,62 @@ public class ActorSensorLoop implements ActionLoop {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#cleanup()
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
// Put in cleanup code here
|
||||
|
||||
// Recursively call cleanup() method of all registered action loops
|
||||
for(ActionLoop actionLoop: actionLoops){
|
||||
actionLoop.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
|
||||
// Call destroy method of sub components
|
||||
for(Action a: preActions){
|
||||
logger.finest("Destroy pre-action");
|
||||
a.destroy();
|
||||
}
|
||||
|
||||
for(Action a: postActions){
|
||||
logger.finest("Destroy post-action");
|
||||
a.destroy();
|
||||
}
|
||||
|
||||
for(Action a: preActorActions){
|
||||
logger.finest("Destroy pre-actor action");
|
||||
a.destroy();
|
||||
}
|
||||
|
||||
for(Action a: postActorActions){
|
||||
logger.finest("Destroy post-actor action");
|
||||
a.destroy();
|
||||
}
|
||||
|
||||
for(Action a: preSensorActions){
|
||||
logger.finest("Destroy pre-sensor action");
|
||||
a.destroy();
|
||||
}
|
||||
|
||||
for(Action a: postSensorActions){
|
||||
logger.finest("Destroy post-sensor action");
|
||||
a.destroy();
|
||||
}
|
||||
|
||||
for(Actor a: actors){
|
||||
logger.finest("Destroy actor");
|
||||
a.destroy();
|
||||
}
|
||||
|
||||
for(Sensor s: sensors){
|
||||
logger.finest("Destroy sensor");
|
||||
s.destroy();
|
||||
}
|
||||
|
||||
if(guard != null){
|
||||
logger.finest("Destroy guard");
|
||||
guard.destroy();
|
||||
}
|
||||
|
||||
// Recursively call cleanup() method of all registered action loops
|
||||
for(ActionLoop actionLoop: actionLoops){
|
||||
logger.finest("Destroy action loop");
|
||||
actionLoop.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#getPreActions()
|
||||
*/
|
||||
@Override
|
||||
public List<Action> getPreActions() {
|
||||
return preActions;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#getPostActions()
|
||||
*/
|
||||
@Override
|
||||
public List<Action> getPostActions() {
|
||||
return postActions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The structure of the data message depends on the sensors registered at this loop
|
||||
* at the time this method is called.
|
||||
* @return the data queue and the metadata of the data messages
|
||||
*/
|
||||
public DataQueue getDataQueue() {
|
||||
DataMessageMetadata m = new DataMessageMetadata();
|
||||
|
||||
// Build up data message metadata based on the sensors currently registered.
|
||||
for(Sensor s: sensors){
|
||||
m.getComponents().add(new ComponentMetadata(s.getId()));
|
||||
}
|
||||
return new DataQueue(dataQueue, m);
|
||||
@Override
|
||||
public EventBus getEventBus(){
|
||||
return eventBus;
|
||||
}
|
||||
|
||||
// Getter functions for variable parts
|
||||
|
||||
/**
|
||||
* @return the actionLoops
|
||||
*/
|
||||
public List<ActionLoop> getActionLoops() {
|
||||
return actionLoops;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the preActorActions
|
||||
*/
|
||||
public List<Action> getPreActorActions() {
|
||||
return preActorActions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the postActorActions
|
||||
*/
|
||||
public List<Action> getPostActorActions() {
|
||||
return postActorActions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the preSensorActions
|
||||
*/
|
||||
public List<Action> getPreSensorActions() {
|
||||
return preSensorActions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the postSensorActions
|
||||
*/
|
||||
public List<Action> getPostSensorActions() {
|
||||
return postSensorActions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the actors
|
||||
*/
|
||||
public List<Actor> getActors() {
|
||||
return actors;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the sensors
|
||||
*/
|
||||
public List<Sensor> getSensors() {
|
||||
return sensors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the guard
|
||||
*/
|
||||
public Guard getGuard() {
|
||||
return guard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param guard the guard to set
|
||||
*/
|
||||
public void setGuard(Guard guard) {
|
||||
this.guard = guard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dataGroup
|
||||
*/
|
||||
public boolean isDataGroup() {
|
||||
return dataGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dataGroup the dataGroup to set
|
||||
*/
|
||||
public void setDataGroup(boolean dataGroup) {
|
||||
this.dataGroup = dataGroup;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
package ch.psi.fda.core.loops.cr;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
* Filter calculating the delta of two subsequent values
|
||||
*/
|
||||
public class CrlogicDeltaDataFilter {
|
||||
|
||||
|
||||
@@ -34,26 +34,18 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import jcifs.smb.SmbFile;
|
||||
import ch.psi.fda.core.Action;
|
||||
import ch.psi.fda.core.ActionLoop;
|
||||
import ch.psi.fda.core.Sensor;
|
||||
import ch.psi.fda.core.actors.OTFActuator;
|
||||
import ch.psi.fda.core.messages.ComponentMetadata;
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import ch.psi.fda.core.messages.EndOfStreamMessage;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
import ch.psi.fda.core.sensors.MillisecondTimestampSensor;
|
||||
import ch.psi.fda.core.sensors.OTFNamedChannelSensor;
|
||||
import ch.psi.fda.core.sensors.OTFScalerChannelSensor;
|
||||
import ch.psi.fda.core.messages.Metadata;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
* While using Crlogic the IOC system clock rate should/must be set to 1000 (default 60)
|
||||
*
|
||||
* sysClkRateSet 1000
|
||||
@@ -61,7 +53,6 @@ import ch.psi.jcae.ChannelService;
|
||||
*/
|
||||
public class CrlogicLoop implements ActionLoop {
|
||||
|
||||
// Get Logger
|
||||
private static final Logger logger = Logger.getLogger(CrlogicLoop.class.getName());
|
||||
|
||||
/**
|
||||
@@ -76,8 +67,6 @@ public class CrlogicLoop implements ActionLoop {
|
||||
private volatile boolean stopReadoutThread = false;
|
||||
private Thread readoutThread;
|
||||
|
||||
// Constants
|
||||
|
||||
/**
|
||||
* Default timeout (in milliseconds) for wait operations
|
||||
*/
|
||||
@@ -118,33 +107,23 @@ public class CrlogicLoop implements ActionLoop {
|
||||
*/
|
||||
private String prefix;
|
||||
|
||||
private CrlogicChannelsTemplate template;
|
||||
private MotorChannelsTemplate motortemplate;
|
||||
private TemplateCrlogic template;
|
||||
private TemplateMotor motortemplate;
|
||||
|
||||
/**
|
||||
* Semaphore to ensure that data is read in correct sequence
|
||||
*/
|
||||
private Semaphore semaphore = new Semaphore(1);
|
||||
|
||||
/**
|
||||
* Special OTF Actuator
|
||||
*/
|
||||
private OTFActuator actuator = null;
|
||||
|
||||
/**
|
||||
* List of sensors of this loop
|
||||
*/
|
||||
private List<Sensor> sensors;
|
||||
private List<CrlogicResource> sensors;
|
||||
|
||||
private List<String> readoutResources;
|
||||
private Map<Integer, CrlogicDeltaDataFilter> scalerIndices;
|
||||
private CrlogicRangeDataFilter crlogicDataFilter;
|
||||
|
||||
/**
|
||||
* Data queue sensor data is posted to. A message consists of a list of data objects
|
||||
* that are read out of the sensors of this loop.
|
||||
*/
|
||||
private BlockingQueue<Message> dataQueue;
|
||||
|
||||
/**
|
||||
* Abort status
|
||||
@@ -153,9 +132,25 @@ public class CrlogicLoop implements ActionLoop {
|
||||
private boolean abortForce = false;
|
||||
private Thread executionThread = null;
|
||||
|
||||
private ChannelService cservice;
|
||||
public CrlogicLoop(ChannelService s, String prefix, String server, String share, String smbShare, boolean zigZag){
|
||||
cservice = s;
|
||||
private final ChannelService cservice;
|
||||
|
||||
|
||||
private String id;
|
||||
private String name; // name of the motor channel
|
||||
private String readback; // name of the encoder channel
|
||||
private double start;
|
||||
private double end;
|
||||
private double stepSize;
|
||||
private double integrationTime;
|
||||
private double additionalBacklash;
|
||||
|
||||
|
||||
private final EventBus eventbus;
|
||||
private List<Metadata> metadata;
|
||||
|
||||
public CrlogicLoop(ChannelService cservice, String prefix, String server, String share, String smbShare, boolean zigZag){
|
||||
eventbus = new EventBus();
|
||||
this.cservice = cservice;
|
||||
this.prefix = prefix;
|
||||
this.server = server;
|
||||
this.share = share;
|
||||
@@ -165,15 +160,25 @@ public class CrlogicLoop implements ActionLoop {
|
||||
// Initialize lists used by the loop
|
||||
this.preActions = new ArrayList<Action>();
|
||||
this.postActions = new ArrayList<Action>();
|
||||
this.sensors = new ArrayList<Sensor>();
|
||||
this.sensors = new ArrayList<>();
|
||||
this.readoutResources = new ArrayList<String>();
|
||||
this.scalerIndices = new HashMap<Integer, CrlogicDeltaDataFilter>();
|
||||
|
||||
this.crlogicDataFilter = new CrlogicRangeDataFilter();
|
||||
this.dataQueue = new LinkedBlockingQueue<Message>(2000);
|
||||
}
|
||||
|
||||
|
||||
public void setActuator(String id, String name, String readback, double start, double end, double stepSize, double integrationTime, double additionalBacklash){
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.readback = readback;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.stepSize = stepSize;
|
||||
this.integrationTime = integrationTime;
|
||||
this.additionalBacklash = additionalBacklash;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collect data from share
|
||||
* @param tmpFileName Name of the temporary file
|
||||
@@ -234,7 +239,7 @@ public class CrlogicLoop implements ActionLoop {
|
||||
// logger.info(line);
|
||||
|
||||
// Write into queue
|
||||
DataMessage message = new DataMessage();
|
||||
DataMessage message = new DataMessage(metadata);
|
||||
String[] tokens = line.split("\t");
|
||||
boolean use = true;
|
||||
|
||||
@@ -285,7 +290,7 @@ public class CrlogicLoop implements ActionLoop {
|
||||
|
||||
// Filter data
|
||||
if(use && !discardAnyway){
|
||||
dataQueue.put(message);
|
||||
eventbus.post(message);
|
||||
mcounter++;
|
||||
}
|
||||
|
||||
@@ -308,7 +313,7 @@ public class CrlogicLoop implements ActionLoop {
|
||||
}
|
||||
|
||||
// Issue end of loop control message
|
||||
dataQueue.put(new EndOfStreamMessage(dataGroup));
|
||||
eventbus.post(new EndOfStreamMessage(dataGroup));
|
||||
semaphore.release();
|
||||
}
|
||||
|
||||
@@ -321,15 +326,9 @@ public class CrlogicLoop implements ActionLoop {
|
||||
public void execute() throws InterruptedException {
|
||||
try{
|
||||
|
||||
double stepSize = actuator.getStepSize();
|
||||
double start = actuator.getStart();
|
||||
double end = actuator.getEnd();
|
||||
double integrationTime = actuator.getIntegrationTime();
|
||||
double ubacklash = actuator.getAdditionalBacklash();
|
||||
|
||||
// Set values for the datafilter
|
||||
crlogicDataFilter.setStart(actuator.getStart());
|
||||
crlogicDataFilter.setEnd(actuator.getEnd());
|
||||
crlogicDataFilter.setStart(start);
|
||||
crlogicDataFilter.setEnd(end);
|
||||
|
||||
// Reset data filter
|
||||
for(Integer k: scalerIndices.keySet()){
|
||||
@@ -356,20 +355,20 @@ public class CrlogicLoop implements ActionLoop {
|
||||
Long timeout = 600000l; // 10 minutes move timeout
|
||||
|
||||
// Check if logic is inactive, otherwise return early
|
||||
if(!template.getStatus().getValue().equals(CrlogicChannelsTemplate.Status.INACTIVE.toString())){
|
||||
if(!template.getStatus().getValue().equals(TemplateCrlogic.Status.INACTIVE.toString())){
|
||||
logger.info("CRLOGIC is not inactive!");
|
||||
// TODO Decide what to do in this situation
|
||||
|
||||
if(template.getStatus().getValue().equals(CrlogicChannelsTemplate.Status.FAULT.toString())){
|
||||
if(template.getStatus().getValue().equals(TemplateCrlogic.Status.FAULT.toString())){
|
||||
// If in fault show message and recover
|
||||
logger.info("CRLOGIC in FAULT state");
|
||||
logger.info("Error message: "+template.getMessage().getValue());
|
||||
logger.info("Recover logic and set it to INACTIVE");
|
||||
template.getStatus().setValue(CrlogicChannelsTemplate.Status.INACTIVE.toString());
|
||||
template.getStatus().setValue(TemplateCrlogic.Status.INACTIVE.toString());
|
||||
}
|
||||
else if(template.getStatus().getValue().equals(CrlogicChannelsTemplate.Status.ACTIVE.toString())){
|
||||
template.getStatus().setValue(CrlogicChannelsTemplate.Status.STOP.toString());
|
||||
template.getStatus().waitForValue(CrlogicChannelsTemplate.Status.INACTIVE.toString(), startStopTimeout);
|
||||
else if(template.getStatus().getValue().equals(TemplateCrlogic.Status.ACTIVE.toString())){
|
||||
template.getStatus().setValue(TemplateCrlogic.Status.STOP.toString());
|
||||
template.getStatus().waitForValue(TemplateCrlogic.Status.INACTIVE.toString(), startStopTimeout);
|
||||
}
|
||||
else{
|
||||
throw new RuntimeException("CRLOGIC is not inactive");
|
||||
@@ -459,7 +458,7 @@ public class CrlogicLoop implements ActionLoop {
|
||||
|
||||
// TODO Calculate and set motor speed, backlash, etc.
|
||||
double motorSpeed = stepSize/integrationTime;
|
||||
double backlash = (0.5*motorSpeed*motortemplate.getAccelerationTime().getValue())+motorBacklash+ubacklash;
|
||||
double backlash = (0.5*motorSpeed*motortemplate.getAccelerationTime().getValue())+motorBacklash+additionalBacklash;
|
||||
double realEnd = end+(backlash*direction);
|
||||
double realStart = start-(backlash*direction);
|
||||
|
||||
@@ -500,17 +499,17 @@ public class CrlogicLoop implements ActionLoop {
|
||||
|
||||
// Start crlogic logic
|
||||
logger.info("Start CRLOGIC");
|
||||
template.getStatus().setValue(CrlogicChannelsTemplate.Status.INITIALIZE.toString());
|
||||
template.getStatus().setValue(TemplateCrlogic.Status.INITIALIZE.toString());
|
||||
try{
|
||||
template.getStatus().waitForValue(CrlogicChannelsTemplate.Status.ACTIVE.toString(), startStopTimeout);
|
||||
template.getStatus().waitForValue(TemplateCrlogic.Status.ACTIVE.toString(), startStopTimeout);
|
||||
}
|
||||
catch(ChannelException e){
|
||||
catch(ChannelException | ExecutionException | TimeoutException e){
|
||||
logger.info( "Failed to start CRLOGIC. Logic in status: "+template.getStatus().getValue() );
|
||||
if(template.getStatus().getValue().equals(CrlogicChannelsTemplate.Status.FAULT.toString())){
|
||||
if(template.getStatus().getValue().equals(TemplateCrlogic.Status.FAULT.toString())){
|
||||
logger.info("Error message: "+template.getMessage().getValue());
|
||||
}
|
||||
// Recover to inactive
|
||||
template.getStatus().setValue(CrlogicChannelsTemplate.Status.INACTIVE.toString());
|
||||
template.getStatus().setValue(TemplateCrlogic.Status.INACTIVE.toString());
|
||||
// TODO Improve error handling
|
||||
throw new RuntimeException("Failed to start CRLOGIC. Logic in status: "+template.getStatus().getValue()+ " Error message: "+template.getMessage().getValue(), e);
|
||||
|
||||
@@ -524,8 +523,8 @@ public class CrlogicLoop implements ActionLoop {
|
||||
catch (InterruptedException e) {
|
||||
if(abort & (!abortForce)){
|
||||
// Abort motor move
|
||||
motortemplate.getCommand().setValue(MotorChannelsTemplate.Commands.Stop.ordinal());
|
||||
motortemplate.getCommand().setValue(MotorChannelsTemplate.Commands.Go.ordinal());
|
||||
motortemplate.getCommand().setValue(TemplateMotor.Commands.Stop.ordinal());
|
||||
motortemplate.getCommand().setValue(TemplateMotor.Commands.Go.ordinal());
|
||||
}
|
||||
else{
|
||||
throw e;
|
||||
@@ -535,13 +534,13 @@ public class CrlogicLoop implements ActionLoop {
|
||||
|
||||
// Stop crlogic logic
|
||||
logger.info("Stop CRLOGIC");
|
||||
template.getStatus().setValue(CrlogicChannelsTemplate.Status.STOP.toString());
|
||||
template.getStatus().setValue(TemplateCrlogic.Status.STOP.toString());
|
||||
// Wait until stopped
|
||||
logger.info("Wait until stopped");
|
||||
try{
|
||||
template.getStatus().waitForValue(CrlogicChannelsTemplate.Status.INACTIVE.toString(), startStopTimeout);
|
||||
template.getStatus().waitForValue(TemplateCrlogic.Status.INACTIVE.toString(), startStopTimeout);
|
||||
}
|
||||
catch(ChannelException | ExecutionException e){
|
||||
catch(ChannelException | ExecutionException | TimeoutException e){
|
||||
logger.info( "Failed to stop CRLOGIC. Logic in status: "+template.getStatus().getValue() );
|
||||
// TODO Improve error handling
|
||||
throw new RuntimeException("Failed to stop CRLOGIC. Logic in status: "+template.getStatus().getValue(), e);
|
||||
@@ -566,27 +565,11 @@ public class CrlogicLoop implements ActionLoop {
|
||||
// Request read of data file
|
||||
readQueue.put(tmpFileName);
|
||||
|
||||
// // Read data
|
||||
// Thread t = new Thread(new Runnable() {
|
||||
//
|
||||
// @Override
|
||||
// public void run() {
|
||||
// try {
|
||||
// collectData(smbShare, tmpFileName);
|
||||
// } catch (InterruptedException e) {
|
||||
// throw new RuntimeException("Unable to read CRLOGIC raw data file",e);
|
||||
// } catch (IOException e) {
|
||||
// throw new RuntimeException("Unable to read CRLOGIC raw data file",e);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// t.start();
|
||||
|
||||
if(zigZag){
|
||||
// Swap start and end
|
||||
double aend = actuator.getEnd();
|
||||
actuator.setEnd(actuator.getStart());
|
||||
actuator.setStart(aend);
|
||||
// reverse start/end
|
||||
double aend = end;
|
||||
end=start;
|
||||
start=aend;
|
||||
}
|
||||
|
||||
synchronized(this){
|
||||
@@ -598,18 +581,11 @@ public class CrlogicLoop implements ActionLoop {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#abort()
|
||||
*/
|
||||
@Override
|
||||
public void abort() {
|
||||
abort(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort logic
|
||||
* @param force
|
||||
*/
|
||||
public synchronized void abort(boolean force){
|
||||
abort = true;
|
||||
abortForce = force;
|
||||
@@ -620,35 +596,18 @@ public class CrlogicLoop implements ActionLoop {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
stopReadoutThread = true;
|
||||
readoutThread.interrupt();
|
||||
// TODO eventually interrupt readout thread
|
||||
|
||||
try {
|
||||
|
||||
cservice.destroyAnnotatedChannels(template);
|
||||
cservice.destroyAnnotatedChannels(motortemplate);
|
||||
template = null;
|
||||
motortemplate = null;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to destroy CrlogicLoop", e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#prepare()
|
||||
*/
|
||||
@Override
|
||||
public void prepare() {
|
||||
|
||||
metadata = new ArrayList<>();
|
||||
|
||||
// Build up metadata
|
||||
metadata.add(new Metadata(this.id));
|
||||
for(CrlogicResource s: sensors){
|
||||
metadata.add(new Metadata(s.getId()));
|
||||
}
|
||||
|
||||
|
||||
stopReadoutThread = false;
|
||||
// Start readout Thread
|
||||
readoutThread = new Thread(new Runnable() {
|
||||
@@ -679,22 +638,22 @@ public class CrlogicLoop implements ActionLoop {
|
||||
|
||||
try{
|
||||
// Connect crlogic channels
|
||||
template = new CrlogicChannelsTemplate();
|
||||
template = new TemplateCrlogic();
|
||||
logger.info("Connect channels");
|
||||
Map<String, String> m = new HashMap<>();
|
||||
m.put("PREFIX", prefix);
|
||||
cservice.createAnnotatedChannels(template, m);
|
||||
Map<String,String> map = new HashMap<>();
|
||||
map.put("PREFIX", prefix);
|
||||
cservice.createAnnotatedChannels(template, map);
|
||||
|
||||
// Connect motor channels
|
||||
motortemplate = new MotorChannelsTemplate();
|
||||
m = new HashMap<>();
|
||||
m.put("PREFIX", actuator.getName());
|
||||
cservice.createAnnotatedChannels(motortemplate, m);
|
||||
motortemplate = new TemplateMotor();
|
||||
map = new HashMap<>();
|
||||
map.put("PREFIX", this.name);
|
||||
cservice.createAnnotatedChannels(motortemplate, map);
|
||||
|
||||
useReadback = motortemplate.getUseReadback().getValue();
|
||||
useEncoder = motortemplate.getUseEncoder().getValue();
|
||||
|
||||
logger.info("Motor type: "+ MotorChannelsTemplate.Type.values()[motortemplate.getType().getValue()]);
|
||||
logger.info("Motor type: "+ TemplateMotor.Type.values()[motortemplate.getType().getValue()]);
|
||||
logger.info("Motor use readback: "+useReadback);
|
||||
logger.info("Motor use encoder: "+useEncoder);
|
||||
|
||||
@@ -705,20 +664,20 @@ public class CrlogicLoop implements ActionLoop {
|
||||
// Determine mode of motor
|
||||
if((!useReadback) && (!useEncoder)){
|
||||
// Open loop
|
||||
if(actuator.getReadback()!=null){
|
||||
if(this.readback!=null){
|
||||
throw new IllegalArgumentException("Readback not supported if motor is configured in open loop");
|
||||
}
|
||||
else{
|
||||
readoutResources.add(actuator.getName());
|
||||
readoutResources.add(this.name);
|
||||
}
|
||||
|
||||
}
|
||||
else if(useReadback && (!useEncoder)){
|
||||
String readback;
|
||||
// use readback link
|
||||
if(actuator.getReadback()!=null){
|
||||
if(this.readback!=null){
|
||||
// Use specified readback
|
||||
readback = (actuator.getReadback());
|
||||
readback = this.readback;
|
||||
}
|
||||
else{
|
||||
// Set resouce to readback link
|
||||
@@ -730,13 +689,13 @@ public class CrlogicLoop implements ActionLoop {
|
||||
|
||||
// Fill readback encoder settings
|
||||
// Connect to encoder
|
||||
EncoderChannelsTemplate encodertemplate = new EncoderChannelsTemplate();
|
||||
m = new HashMap<>();
|
||||
m.put("PREFIX", readback);
|
||||
cservice.createAnnotatedChannels(encodertemplate, m);
|
||||
TemplateEncoder encodertemplate = new TemplateEncoder();
|
||||
map = new HashMap<>();
|
||||
map.put("PREFIX", readback);
|
||||
cservice.createAnnotatedChannels(encodertemplate, map);
|
||||
|
||||
// Read encoder settings
|
||||
if(encodertemplate.getDirection().getValue()==EncoderChannelsTemplate.Direction.Positive.ordinal()){
|
||||
if(encodertemplate.getDirection().getValue()==TemplateEncoder.Direction.Positive.ordinal()){
|
||||
crlogicDataFilter.setEncoderDirection(1);
|
||||
}
|
||||
else{
|
||||
@@ -751,12 +710,12 @@ public class CrlogicLoop implements ActionLoop {
|
||||
}
|
||||
else if (useEncoder && (!useReadback)){
|
||||
// use readback link
|
||||
if(actuator.getReadback()!=null){
|
||||
if(this.readback!=null){
|
||||
throw new IllegalArgumentException("Readback not supported if motor is configured to use encoder");
|
||||
}
|
||||
else{
|
||||
// Set resouce to readback link
|
||||
readoutResources.add(actuator.getName()+"_ENC");
|
||||
readoutResources.add(this.name+"_ENC");
|
||||
}
|
||||
}
|
||||
else{
|
||||
@@ -764,7 +723,7 @@ public class CrlogicLoop implements ActionLoop {
|
||||
}
|
||||
|
||||
// Fill Motor specific settings
|
||||
if(motortemplate.getDirection().getValue()==MotorChannelsTemplate.Direction.Positive.ordinal()){
|
||||
if(motortemplate.getDirection().getValue()==TemplateMotor.Direction.Positive.ordinal()){
|
||||
crlogicDataFilter.setMotorDirection(1);
|
||||
}
|
||||
else{
|
||||
@@ -779,23 +738,11 @@ public class CrlogicLoop implements ActionLoop {
|
||||
scalerIndices.clear();
|
||||
|
||||
int c = 1; // We start at 1 because the actuator right now is an implicit sensor
|
||||
for(Sensor s: sensors){
|
||||
if(s instanceof OTFNamedChannelSensor){
|
||||
// Monitored channel (MUST be configured MODULE ID'S)
|
||||
OTFNamedChannelSensor so = (OTFNamedChannelSensor) s;
|
||||
readoutResources.add(so.getName());
|
||||
}
|
||||
else if (s instanceof OTFScalerChannelSensor){
|
||||
OTFScalerChannelSensor so = (OTFScalerChannelSensor) s;
|
||||
readoutResources.add("SCALER"+so.getIndex());
|
||||
for(CrlogicResource s: sensors){
|
||||
readoutResources.add(s.getKey());
|
||||
if(s.isDelta()){
|
||||
scalerIndices.put(c, new CrlogicDeltaDataFilter());
|
||||
}
|
||||
else if (s instanceof MillisecondTimestampSensor){
|
||||
readoutResources.add("TIMESTAMP");
|
||||
}
|
||||
else{
|
||||
throw new IllegalArgumentException("Sensor type "+s.getClass()+" is not supported by this loop");
|
||||
}
|
||||
c++;
|
||||
}
|
||||
|
||||
@@ -808,101 +755,55 @@ public class CrlogicLoop implements ActionLoop {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#cleanup()
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
// TODO Auto-generated method stub
|
||||
stopReadoutThread = true;
|
||||
readoutThread.interrupt();
|
||||
|
||||
try {
|
||||
cservice.destroyAnnotatedChannels(template);
|
||||
cservice.destroyAnnotatedChannels(motortemplate);
|
||||
template = null;
|
||||
motortemplate = null;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to destroy CrlogicLoop", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#getPreActions()
|
||||
*/
|
||||
@Override
|
||||
public List<Action> getPreActions() {
|
||||
return preActions;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#getPostActions()
|
||||
*/
|
||||
@Override
|
||||
public List<Action> getPostActions() {
|
||||
return postActions;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#isDataGroup()
|
||||
*/
|
||||
@Override
|
||||
public boolean isDataGroup() {
|
||||
// TODO Auto-generated method stub
|
||||
return dataGroup;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#setDataGroup(boolean)
|
||||
*/
|
||||
@Override
|
||||
public void setDataGroup(boolean dataGroup) {
|
||||
this.dataGroup = dataGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the sensors
|
||||
*/
|
||||
public List<Sensor> getSensors() {
|
||||
public List<CrlogicResource> getSensors() {
|
||||
return sensors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the actor
|
||||
*/
|
||||
public OTFActuator getActor() {
|
||||
return actuator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param actor the actor to set
|
||||
*/
|
||||
public void setActor(OTFActuator actor) {
|
||||
this.actuator = actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* The structure of the data message depends on the sensors registered at this loop
|
||||
* at the time this method is called.
|
||||
* @return the data queue and the metadata of the data messages
|
||||
*/
|
||||
public DataQueue getDataQueue() {
|
||||
DataMessageMetadata m = new DataMessageMetadata();
|
||||
|
||||
// Build up data message metadata based on the sensors currently registered.
|
||||
m.getComponents().add(new ComponentMetadata(actuator.getId()));
|
||||
for(Sensor s: sensors){
|
||||
m.getComponents().add(new ComponentMetadata(s.getId()));
|
||||
}
|
||||
return new DataQueue(dataQueue, m);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the keepTmpFiles
|
||||
*/
|
||||
public boolean isKeepTmpFiles() {
|
||||
return keepTmpFiles;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param keepTmpFiles the keepTmpFiles to set
|
||||
*/
|
||||
public void setKeepTmpFiles(boolean keepTmpFiles) {
|
||||
this.keepTmpFiles = keepTmpFiles;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public EventBus getEventBus(){
|
||||
return eventbus;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.core.loops.cr;
|
||||
|
||||
/**
|
||||
* Readout resource of crlogic
|
||||
*/
|
||||
public class CrlogicResource {
|
||||
|
||||
/**
|
||||
* Id of the data
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* Id of the crlogic resource to be read out. As configured in the CRLOGIC part of the IOC startup script
|
||||
*/
|
||||
private String key;
|
||||
/**
|
||||
* Flag whether to read back the delta of the values of this resource. (delta is done in software)
|
||||
*/
|
||||
private boolean delta = false;
|
||||
|
||||
public CrlogicResource(){
|
||||
}
|
||||
|
||||
public CrlogicResource(String id, String key){
|
||||
this.id = id;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public CrlogicResource(String id, String key, boolean delta){
|
||||
this.id = id;
|
||||
this.key = key;
|
||||
this.delta = delta;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
public boolean isDelta() {
|
||||
return delta;
|
||||
}
|
||||
public void setDelta(boolean delta) {
|
||||
this.delta = delta;
|
||||
}
|
||||
}
|
||||
@@ -21,28 +21,27 @@ package ch.psi.fda.core.loops.cr;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import ch.psi.fda.core.Action;
|
||||
import ch.psi.fda.core.ActionLoop;
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import ch.psi.fda.core.sensors.MillisecondTimestampSensor;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ParallelCrlogic implements ActionLoop {
|
||||
|
||||
// Get Logger
|
||||
private static final Logger logger = Logger.getLogger(ParallelCrlogic.class.getName());
|
||||
|
||||
/**
|
||||
@@ -66,6 +65,8 @@ public class ParallelCrlogic implements ActionLoop {
|
||||
private ParallelCrlogicStreamMerge merger;
|
||||
|
||||
|
||||
private final EventBus eventbus;
|
||||
|
||||
public ParallelCrlogic(CrlogicLoop crlogic, ScrlogicLoop scrlogic){
|
||||
|
||||
if(crlogic==null){
|
||||
@@ -75,32 +76,42 @@ public class ParallelCrlogic implements ActionLoop {
|
||||
throw new IllegalArgumentException("No Scrloop specified");
|
||||
}
|
||||
|
||||
|
||||
this.eventbus = new EventBus();
|
||||
|
||||
this.crlogic = crlogic;
|
||||
// Add timestamp to sensor at the beginning of the sensor list as this is required for merging the data
|
||||
// Timestamp will be at the second position of a message in the queue!
|
||||
this.crlogic.getSensors().add(0, new MillisecondTimestampSensor("tmp_timestamp"));
|
||||
this.crlogic.getSensors().add(0, new CrlogicResource("tmp_timestamp","TIMESTAMP"));
|
||||
this.scrlogic = scrlogic;
|
||||
|
||||
// Initialize lists used by the loop
|
||||
this.preActions = new ArrayList<Action>();
|
||||
this.postActions = new ArrayList<Action>();
|
||||
|
||||
this.merger = new ParallelCrlogicStreamMerge(crlogic.getDataQueue(), scrlogic.getDataQueue());
|
||||
final BlockingQueue<Message> q1 = new LinkedBlockingQueue<>();
|
||||
final BlockingQueue<Message> q2 = new LinkedBlockingQueue<>();
|
||||
|
||||
crlogic.getEventBus().register(new Object(){
|
||||
@Subscribe
|
||||
public void onMessage(Message m){
|
||||
q1.add(m);
|
||||
}
|
||||
});
|
||||
scrlogic.getEventBus().register(new Object(){
|
||||
@Subscribe
|
||||
public void onMessage(Message m){
|
||||
q2.add(m);
|
||||
}
|
||||
});
|
||||
|
||||
this.merger = new ParallelCrlogicStreamMerge(q1, q2, eventbus);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.logic.Logic#prepare()
|
||||
*/
|
||||
@Override
|
||||
public void prepare() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.logic.Logic#execute()
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws InterruptedException {
|
||||
|
||||
@@ -191,78 +202,36 @@ public class ParallelCrlogic implements ActionLoop {
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#abort()
|
||||
*/
|
||||
@Override
|
||||
public void abort() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
crlogic.destroy();
|
||||
scrlogic.destroy();
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#cleanup()
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#getPreActions()
|
||||
*/
|
||||
@Override
|
||||
public List<Action> getPreActions() {
|
||||
return preActions;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#getPostActions()
|
||||
*/
|
||||
@Override
|
||||
public List<Action> getPostActions() {
|
||||
return postActions;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#isDataGroup()
|
||||
*/
|
||||
@Override
|
||||
public boolean isDataGroup() {
|
||||
return dataGroup;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#setDataGroup(boolean)
|
||||
*/
|
||||
@Override
|
||||
public void setDataGroup(boolean dataGroup) {
|
||||
this.dataGroup = dataGroup;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#getDataQueue()
|
||||
*/
|
||||
@Override
|
||||
public DataQueue getDataQueue() {
|
||||
return(merger.getDataQueue());
|
||||
public EventBus getEventBus(){
|
||||
return eventbus;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,40 +19,41 @@
|
||||
|
||||
package ch.psi.fda.core.loops.cr;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import ch.psi.fda.core.messages.EndOfStreamMessage;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
import ch.psi.fda.core.messages.Metadata;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
* Class to merge two data streams into one. The secondary queues data is added to the primary queues data.
|
||||
* The resulting queue therefor will hold the same amount of elements as the primary queue does.
|
||||
* The datagroup flag set in the end of stream message will be set according to the flag set in the primary queue.
|
||||
*/
|
||||
public class ParallelCrlogicStreamMerge {
|
||||
|
||||
private BlockingQueue<Message> dataQueue;
|
||||
|
||||
private DataQueue primaryQueue;
|
||||
private DataQueue secondaryQueue;
|
||||
private BlockingQueue<Message> primaryQueue;
|
||||
private BlockingQueue<Message> secondaryQueue;
|
||||
|
||||
private final EventBus eventbus;
|
||||
|
||||
private List<Metadata> metadata;
|
||||
|
||||
/**
|
||||
* Class to merge two data streams into one. The secondary queues data is added to the primary queues data.
|
||||
* The resulting queue therefor will hold the same amount of elements as the primary queue does.
|
||||
* The datagroup flag set in the end of stream message will be set according to the flag set in the primary queue.
|
||||
*
|
||||
* @param pqueue Primary/master queue
|
||||
* @param squeue Secondary queue
|
||||
*/
|
||||
public ParallelCrlogicStreamMerge(DataQueue pqueue, DataQueue squeue){
|
||||
public ParallelCrlogicStreamMerge(BlockingQueue<Message> pqueue, BlockingQueue<Message> squeue, EventBus ebus){
|
||||
this.primaryQueue = pqueue;
|
||||
this.secondaryQueue = squeue;
|
||||
|
||||
this.dataQueue = new LinkedBlockingQueue<Message>();
|
||||
|
||||
this.eventbus = ebus;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,11 +62,16 @@ public class ParallelCrlogicStreamMerge {
|
||||
*/
|
||||
public void merge() throws InterruptedException{
|
||||
|
||||
metadata = new ArrayList<>();
|
||||
|
||||
boolean firstPrimary = true;
|
||||
boolean firstSecondary = true;
|
||||
|
||||
// Actual data of the secondary queue
|
||||
List<Object> currData = null;
|
||||
|
||||
// Take first element of the primary queue (wait until message is available)
|
||||
Message m = primaryQueue.getQueue().take();
|
||||
Message m = primaryQueue.take();
|
||||
|
||||
while(! (m instanceof EndOfStreamMessage)){
|
||||
|
||||
@@ -73,18 +79,26 @@ public class ParallelCrlogicStreamMerge {
|
||||
|
||||
DataMessage dm = (DataMessage) m;
|
||||
|
||||
if(firstPrimary){
|
||||
firstPrimary = false;
|
||||
List<Metadata> pqm = dm.getMetadata();
|
||||
metadata.add(pqm.get(0)); // add first component (this is the actuator)
|
||||
// Skip the next component as this is the timestamp used to merge the data
|
||||
for(int i=2;i<pqm.size();i++){
|
||||
metadata.add(pqm.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get and remove merge timestamp from the data of the message
|
||||
Double timestamp = (Double) dm.getData().remove(1);
|
||||
long milliseconds = (long) (timestamp*1000);
|
||||
long nanoOffset = (long)((timestamp*1000-milliseconds)*1000000);
|
||||
|
||||
// System.out.println("timestamp: "+new Date(milliseconds)+" "+milliseconds+" ."+nanoOffset);
|
||||
|
||||
while(true){
|
||||
// Assumption: the secondary Queue holds at least the data up to the
|
||||
// timestamp of the primary queue
|
||||
Message mess = secondaryQueue.getQueue().peek();
|
||||
// Message mess = secondaryQueue.getQueue().take();
|
||||
Message mess = secondaryQueue.peek();
|
||||
|
||||
if(mess instanceof EndOfStreamMessage){
|
||||
break;
|
||||
@@ -95,23 +109,29 @@ public class ParallelCrlogicStreamMerge {
|
||||
}
|
||||
|
||||
if(mess instanceof DataMessage){
|
||||
|
||||
// Check whether timestamp of the next message is bigger than the timestamp of the
|
||||
// message from the primary queue - if the timestamp is bigger do not take message out of the queue
|
||||
DataMessage msCheck = (DataMessage) mess;
|
||||
|
||||
// System.out.println("Mess: "+mess);
|
||||
if(firstSecondary){
|
||||
firstSecondary = false;
|
||||
|
||||
List<Metadata> sqm = msCheck.getMetadata();
|
||||
// Skip first two components of the message as this is the timestamp
|
||||
for(int i=2;i<sqm.size();i++){
|
||||
metadata.add(sqm.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
long currMilliCheck = ((Double) msCheck.getData().get(0)).longValue();
|
||||
long currNanoCheck = ((Double) msCheck.getData().get(1)).longValue();
|
||||
|
||||
// Check
|
||||
if(currMilliCheck>milliseconds || (currMilliCheck==milliseconds && currNanoCheck>nanoOffset)){
|
||||
break;
|
||||
}
|
||||
|
||||
DataMessage ms = (DataMessage) secondaryQueue.getQueue().take();
|
||||
|
||||
// System.out.println("Ms: "+ms);
|
||||
DataMessage ms = (DataMessage) secondaryQueue.take();
|
||||
|
||||
currData = ms.getData();
|
||||
// Remove timestamps
|
||||
@@ -126,44 +146,18 @@ public class ParallelCrlogicStreamMerge {
|
||||
|
||||
// Add data to primary data queue message and put it into the out queue
|
||||
dm.getData().addAll(currData);
|
||||
|
||||
dataQueue.add(dm);
|
||||
dm.setMetadata(metadata);
|
||||
eventbus.post(dm);
|
||||
}
|
||||
|
||||
|
||||
m = primaryQueue.getQueue().take();
|
||||
m = primaryQueue.take();
|
||||
}
|
||||
|
||||
// Add the end of stream message of the primary queue
|
||||
dataQueue.add(m);
|
||||
eventbus.post(m);
|
||||
|
||||
// Clear all remaining messages in secondary queue
|
||||
secondaryQueue.getQueue().clear();
|
||||
secondaryQueue.clear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The structure of the data message depends on the sensors registered at this loop
|
||||
* at the time this method is called.
|
||||
* @return the data queue and the metadata of the data messages
|
||||
*/
|
||||
public DataQueue getDataQueue() {
|
||||
DataMessageMetadata m = new DataMessageMetadata();
|
||||
|
||||
DataMessageMetadata pqm = primaryQueue.getDataMessageMetadata();
|
||||
m.getComponents().add(pqm.getComponents().get(0)); // add first component (this is the actuator)
|
||||
// Skip the next component as this is the timestamp used to merge the data
|
||||
for(int i=2;i<pqm.getComponents().size();i++){
|
||||
m.getComponents().add(pqm.getComponents().get(i));
|
||||
}
|
||||
|
||||
DataMessageMetadata sqm = secondaryQueue.getDataMessageMetadata();
|
||||
// Skip first two components of the message as this is the timestamp
|
||||
for(int i=2;i<sqm.getComponents().size();i++){
|
||||
m.getComponents().add(sqm.getComponents().get(i));
|
||||
}
|
||||
|
||||
return new DataQueue(dataQueue, m);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,39 +19,26 @@
|
||||
|
||||
package ch.psi.fda.core.loops.cr;
|
||||
|
||||
import gov.aps.jca.Monitor;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ch.psi.fda.core.Action;
|
||||
import ch.psi.fda.core.ActionLoop;
|
||||
import ch.psi.fda.core.Sensor;
|
||||
import ch.psi.fda.core.messages.ComponentMetadata;
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import ch.psi.fda.core.messages.EndOfStreamMessage;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
import ch.psi.fda.core.sensors.ChannelAccessDoubleSensor;
|
||||
import ch.psi.fda.core.messages.Metadata;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
import ch.psi.jcae.impl.type.DoubleTimestamp;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
* Assumptions: - The delay between the monitor writing the value to the
|
||||
* monitor queue and the readout of all the queues is sufficient to
|
||||
* prevent the situation that some monitors of events close to each
|
||||
@@ -81,16 +68,14 @@ public class ScrlogicLoop implements ActionLoop {
|
||||
* Data queue sensor data is posted to. A message consists of a list of data
|
||||
* objects that are read out of the sensors of this loop.
|
||||
*/
|
||||
private final BlockingQueue<Message> dataQueue = new LinkedBlockingQueue<Message>();
|
||||
// private final BlockingQueue<Message> dataQueue = new LinkedBlockingQueue<Message>();
|
||||
|
||||
private boolean dataGroup = false;
|
||||
private final List<Action> preActions = new ArrayList<Action>();
|
||||
private final List<Action> postActions = new ArrayList<Action>();
|
||||
|
||||
/**
|
||||
* Sensors to read out
|
||||
*/
|
||||
// private List<Sensor> sensors;
|
||||
private List<String> sensorIds;
|
||||
private List<Channel<DoubleTimestamp>> sensors;
|
||||
|
||||
/**
|
||||
* List of monitors that were attached to the sensor channels (i.e
|
||||
@@ -105,27 +90,15 @@ public class ScrlogicLoop implements ActionLoop {
|
||||
|
||||
private CountDownLatch latch;
|
||||
|
||||
private List<Channel<DoubleTimestamp>> sensors = new ArrayList<>();
|
||||
private List<String> sensorIds = new ArrayList<>();
|
||||
private ChannelService cservice;
|
||||
private final EventBus eventbus;
|
||||
private List<Metadata> metadata;
|
||||
|
||||
public ScrlogicLoop(ChannelService s, List<Sensor> sensors) {
|
||||
try{
|
||||
for(Sensor ss: sensors){
|
||||
this.sensors.add(s.createChannel(new ChannelDescriptor<DoubleTimestamp>(DoubleTimestamp.class, ((ChannelAccessDoubleSensor)ss).getChannel().getName(), true)));
|
||||
sensorIds.add(ss.getId());
|
||||
}
|
||||
this.cservice = s;
|
||||
} catch (ChannelException | InterruptedException | TimeoutException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
public ScrlogicLoop(List<String> sensorIds, List<Channel<DoubleTimestamp>> sensors) {
|
||||
this.eventbus = new EventBus();
|
||||
this.sensorIds = sensorIds;
|
||||
this.sensors = sensors;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see ch.psi.fda.core.Action#execute()
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws InterruptedException {
|
||||
|
||||
@@ -135,26 +108,21 @@ public class ScrlogicLoop implements ActionLoop {
|
||||
|
||||
// Attach monitors to the channels (this is actually a workaround)
|
||||
for (Channel<DoubleTimestamp> sensor : sensors) {
|
||||
// if (sensor instanceof ChannelAccessDoubleSensor) {
|
||||
// ChannelAccessDoubleSensor s = (ChannelAccessDoubleSensor) sensor;
|
||||
// Channel<Double> b = s.getChannel();
|
||||
// Create data queue for the channel
|
||||
final BlockingQueue<TimestampedValue> q = new LinkedBlockingQueue<TimestampedValue>();
|
||||
queues.add(q);
|
||||
final BlockingQueue<TimestampedValue> q = new LinkedBlockingQueue<TimestampedValue>();
|
||||
queues.add(q);
|
||||
PropertyChangeListener listener = new PropertyChangeListener() {
|
||||
|
||||
PropertyChangeListener b = new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
DoubleTimestamp value = (DoubleTimestamp) evt.getNewValue();
|
||||
q.add(new TimestampedValue(value.getValue(), value.getTimestamp().getTime(), value.getNanosecondOffset()));
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if(evt.getPropertyName().equals("value")){
|
||||
DoubleTimestamp v = (DoubleTimestamp) evt.getNewValue();
|
||||
q.add(new TimestampedValue(v.getValue(), v.getTimestamp().getTime(), v.getNanosecondOffset()));
|
||||
}
|
||||
};
|
||||
|
||||
sensor.addPropertyChangeListener("value", b);
|
||||
|
||||
monitors.add(b);
|
||||
// }
|
||||
}
|
||||
};
|
||||
sensor.addPropertyChangeListener(listener);
|
||||
monitors.add(listener);
|
||||
|
||||
}
|
||||
|
||||
logger.info("Start data acquisition");
|
||||
@@ -162,15 +130,10 @@ public class ScrlogicLoop implements ActionLoop {
|
||||
latch.await();
|
||||
|
||||
// Remove monitors
|
||||
try{
|
||||
for (int i = 0; i < sensors.size(); i++) {
|
||||
Channel<DoubleTimestamp> sensor = sensors.get(i);
|
||||
sensor.removePropertyChangeListener(monitors.get(i));
|
||||
}
|
||||
}
|
||||
finally{
|
||||
// Clear all monitors in the list
|
||||
monitors.clear();
|
||||
|
||||
for (int i = 0; i < sensors.size(); i++) {
|
||||
Channel<DoubleTimestamp> sensor = sensors.get(i);
|
||||
sensor.removePropertyChangeListener(monitors.get(i));
|
||||
}
|
||||
|
||||
// Merge data
|
||||
@@ -181,122 +144,58 @@ public class ScrlogicLoop implements ActionLoop {
|
||||
q.clear();
|
||||
}
|
||||
queues.clear();
|
||||
|
||||
|
||||
// Put end of stream to the queue
|
||||
dataQueue.add(new EndOfStreamMessage(dataGroup));
|
||||
eventbus.post(new EndOfStreamMessage(dataGroup));
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see ch.psi.fda.core.Action#abort()
|
||||
*/
|
||||
@Override
|
||||
public void abort() {
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see ch.psi.fda.core.Action#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy all sensors
|
||||
for (Channel<DoubleTimestamp> s : sensors) {
|
||||
try {
|
||||
s.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
sensors.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see ch.psi.fda.core.ActionLoop#prepare()
|
||||
*/
|
||||
@Override
|
||||
public void prepare() {
|
||||
// do nothing
|
||||
|
||||
metadata = new ArrayList<>();
|
||||
|
||||
// Build up data message metadata based on the channels registered.
|
||||
metadata.add(new Metadata(ID_TIMESTAMP_MILLISECONDS));
|
||||
metadata.add(new Metadata(ID_TIMESTAMP_OFFSET_NANOSECONDS));
|
||||
for (String id : sensorIds) {
|
||||
metadata.add(new Metadata(id));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see ch.psi.fda.core.ActionLoop#cleanup()
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see ch.psi.fda.core.ActionLoop#getPreActions()
|
||||
*/
|
||||
@Override
|
||||
public List<Action> getPreActions() {
|
||||
return preActions;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see ch.psi.fda.core.ActionLoop#getPostActions()
|
||||
*/
|
||||
@Override
|
||||
public List<Action> getPostActions() {
|
||||
return postActions;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see ch.psi.fda.core.ActionLoop#isDataGroup()
|
||||
*/
|
||||
@Override
|
||||
public boolean isDataGroup() {
|
||||
return dataGroup;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see ch.psi.fda.core.ActionLoop#setDataGroup(boolean)
|
||||
*/
|
||||
@Override
|
||||
public void setDataGroup(boolean dataGroup) {
|
||||
this.dataGroup = dataGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* The structure of the data message depends on the sensors registered at
|
||||
* this loop at the time this method is called.
|
||||
*
|
||||
* @return the data queue and the metadata of the data messages
|
||||
*/
|
||||
public DataQueue getDataQueue() {
|
||||
DataMessageMetadata m = new DataMessageMetadata();
|
||||
|
||||
// Build up data message metadata based on the channels registered.
|
||||
m.getComponents().add(new ComponentMetadata(ID_TIMESTAMP_MILLISECONDS));
|
||||
m.getComponents().add(
|
||||
new ComponentMetadata(ID_TIMESTAMP_OFFSET_NANOSECONDS));
|
||||
for (String id : sensorIds) {
|
||||
m.getComponents().add(new ComponentMetadata(id));
|
||||
}
|
||||
return new DataQueue(dataQueue, m);
|
||||
}
|
||||
|
||||
private boolean hasNext(){
|
||||
for (int i = 0; i < queues.size(); i++) {
|
||||
if(!queues.get(i).isEmpty()){
|
||||
for (BlockingQueue<TimestampedValue> q: queues) {
|
||||
if(!q.isEmpty()){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -309,7 +208,6 @@ public class ScrlogicLoop implements ActionLoop {
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
private void merge() throws InterruptedException {
|
||||
|
||||
// Array to hold temporary channel values
|
||||
TimestampedValue[] cvalues = new TimestampedValue[queues.size()];
|
||||
TimestampedValueComparator comparator = new TimestampedValueComparator();
|
||||
@@ -319,8 +217,6 @@ public class ScrlogicLoop implements ActionLoop {
|
||||
List<Integer> indexes = new ArrayList<Integer>();
|
||||
|
||||
while (hasNext()) {
|
||||
|
||||
// semaphore.acquire();
|
||||
Thread.sleep(10); // Ensure that close by monitors have time to
|
||||
// catch up / also ensure context switch
|
||||
|
||||
@@ -384,7 +280,7 @@ public class ScrlogicLoop implements ActionLoop {
|
||||
}
|
||||
|
||||
// Assemble data message ...
|
||||
DataMessage message = new DataMessage();
|
||||
DataMessage message = new DataMessage(metadata);
|
||||
|
||||
message.getData().add(new Double(timestamp));
|
||||
message.getData().add(new Double(nanoOffset));
|
||||
@@ -397,9 +293,13 @@ public class ScrlogicLoop implements ActionLoop {
|
||||
}
|
||||
}
|
||||
// System.out.println(message);
|
||||
dataQueue.add(message);
|
||||
eventbus.post(message);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public EventBus getEventBus(){
|
||||
return eventbus;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,17 +22,8 @@ package ch.psi.fda.core.loops.cr;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.annotation.CaChannel;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class CrlogicChannelsTemplate {
|
||||
public class TemplateCrlogic {
|
||||
|
||||
/**
|
||||
* Status of the OTFSCAN IOC logic
|
||||
*/
|
||||
public enum Status { SETUP, INACTIVE, INITIALIZE, ACTIVE, STOP, FAULT, ERROR };
|
||||
|
||||
/**
|
||||
* Ticks per second - IOC setting
|
||||
* ATTENTION - This field must only be set bu the IOC - ATTENTION
|
||||
@@ -43,6 +34,7 @@ public class CrlogicChannelsTemplate {
|
||||
/**
|
||||
* Status of the OTFSCAN IOC logic
|
||||
*/
|
||||
public enum Status { SETUP, INACTIVE, INITIALIZE, ACTIVE, STOP, FAULT, ERROR };
|
||||
@CaChannel(type=String.class, name ="${PREFIX}:STATUS")
|
||||
private Channel<String> status;
|
||||
|
||||
@@ -83,7 +75,6 @@ public class CrlogicChannelsTemplate {
|
||||
@CaChannel(type=Boolean.class, name ="${PREFIX}:FAPPE")
|
||||
private Channel<Boolean> appendFile;
|
||||
|
||||
|
||||
/**
|
||||
* Readout resources
|
||||
*/
|
||||
@@ -91,65 +82,31 @@ public class CrlogicChannelsTemplate {
|
||||
private Channel<String[]> readoutResources;
|
||||
|
||||
|
||||
/**
|
||||
* @return the ticksPerSecond
|
||||
*/
|
||||
|
||||
public Channel<Integer> getTicksPerSecond() {
|
||||
return ticksPerSecond;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the status
|
||||
*/
|
||||
public Channel<String> getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the message
|
||||
*/
|
||||
public Channel<String> getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ticksBetweenInterrupts
|
||||
*/
|
||||
public Channel<Integer> getTicksBetweenInterrupts() {
|
||||
return ticksBetweenInterrupts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the nfsServer
|
||||
*/
|
||||
public Channel<String> getNfsServer() {
|
||||
return nfsServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the nfsShare
|
||||
*/
|
||||
public Channel<String> getNfsShare() {
|
||||
return nfsShare;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dataFile
|
||||
*/
|
||||
public Channel<String> getDataFile() {
|
||||
return dataFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the appendFile
|
||||
*/
|
||||
public Channel<Boolean> getAppendFile() {
|
||||
return appendFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the readoutResources
|
||||
*/
|
||||
public Channel<String[]> getReadoutResources() {
|
||||
return readoutResources;
|
||||
}
|
||||
@@ -22,11 +22,7 @@ package ch.psi.fda.core.loops.cr;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.annotation.CaChannel;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class EncoderChannelsTemplate {
|
||||
public class TemplateEncoder {
|
||||
|
||||
/**
|
||||
* Resolution - $(P)$(E)_SCL
|
||||
@@ -48,23 +44,13 @@ public class EncoderChannelsTemplate {
|
||||
private Channel<Integer> direction;
|
||||
|
||||
|
||||
/**
|
||||
* @return the resolution
|
||||
*/
|
||||
|
||||
public Channel<Double> getResolution() {
|
||||
return resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the offset
|
||||
*/
|
||||
public Channel<Double> getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the direction
|
||||
*/
|
||||
public Channel<Integer> getDirection() {
|
||||
return direction;
|
||||
}
|
||||
@@ -22,11 +22,7 @@ package ch.psi.fda.core.loops.cr;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.annotation.CaChannel;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class MotorChannelsTemplate {
|
||||
public class TemplateMotor {
|
||||
|
||||
public enum Type {SOFT_CHANNEL, MOTOR_SIMULATION, OMS_VME58, OMS_MAXv};
|
||||
|
||||
@@ -334,317 +330,140 @@ public class MotorChannelsTemplate {
|
||||
@CaChannel(type=Boolean.class, name ="${PREFIX}.DMOV", monitor=true)
|
||||
private Channel<Boolean> moveDone;
|
||||
|
||||
/**
|
||||
* @return the highLimit
|
||||
*/
|
||||
|
||||
|
||||
public Channel<Double> getHighLimit() {
|
||||
return highLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lowLimit
|
||||
*/
|
||||
public Channel<Double> getLowLimit() {
|
||||
return lowLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the readbackValue
|
||||
*/
|
||||
public Channel<Double> getReadbackValue() {
|
||||
return readbackValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the setValue
|
||||
*/
|
||||
public Channel<Double> getSetValue() {
|
||||
return setValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the relativeMoveValue
|
||||
*/
|
||||
public Channel<Double> getRelativeMoveValue() {
|
||||
return relativeMoveValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the tweakValue
|
||||
*/
|
||||
public Channel<Double> getTweakValue() {
|
||||
return tweakValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the tweakReverse
|
||||
*/
|
||||
public Channel<Integer> getTweakReverse() {
|
||||
return tweakReverse;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the tweakForward
|
||||
*/
|
||||
public Channel<Integer> getTweakForward() {
|
||||
return tweakForward;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the jogReverse
|
||||
*/
|
||||
public Channel<Integer> getJogReverse() {
|
||||
return jogReverse;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the jogForward
|
||||
*/
|
||||
public Channel<Integer> getJogForward() {
|
||||
return jogForward;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the homeReverse
|
||||
*/
|
||||
public Channel<Integer> getHomeReverse() {
|
||||
return homeReverse;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the homeForward
|
||||
*/
|
||||
public Channel<Integer> getHomeForward() {
|
||||
return homeForward;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the engineeringUnit
|
||||
*/
|
||||
public Channel<String> getEngineeringUnit() {
|
||||
return engineeringUnit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public Channel<Integer> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the description
|
||||
*/
|
||||
public Channel<String> getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dialHighLimit
|
||||
*/
|
||||
public Channel<Double> getDialHighLimit() {
|
||||
return dialHighLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dialLowLimit
|
||||
*/
|
||||
public Channel<Double> getDialLowLimit() {
|
||||
return dialLowLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dialReadbackValue
|
||||
*/
|
||||
public Channel<Double> getDialReadbackValue() {
|
||||
return dialReadbackValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dialSetValue
|
||||
*/
|
||||
public Channel<Double> getDialSetValue() {
|
||||
return dialSetValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the rawValue
|
||||
*/
|
||||
public Channel<Integer> getRawValue() {
|
||||
return rawValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the rawReadbackValue
|
||||
*/
|
||||
public Channel<Integer> getRawReadbackValue() {
|
||||
return rawReadbackValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the command
|
||||
*/
|
||||
public Channel<Integer> getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the calibration
|
||||
*/
|
||||
public Channel<Integer> getCalibration() {
|
||||
return calibration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the userOffset
|
||||
*/
|
||||
public Channel<Double> getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the offsetMode
|
||||
*/
|
||||
public Channel<Integer> getOffsetMode() {
|
||||
return offsetMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the direction
|
||||
*/
|
||||
public Channel<Integer> getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the velocity
|
||||
*/
|
||||
public Channel<Double> getVelocity() {
|
||||
return velocity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the backlashVelocity
|
||||
*/
|
||||
public Channel<Double> getBacklashVelocity() {
|
||||
return backlashVelocity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the baseSpeed
|
||||
*/
|
||||
public Channel<Double> getBaseSpeed() {
|
||||
return baseSpeed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the accelerationTime
|
||||
*/
|
||||
public Channel<Double> getAccelerationTime() {
|
||||
return accelerationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the backlashAccelerationTime
|
||||
*/
|
||||
public Channel<Double> getBacklashAccelerationTime() {
|
||||
return backlashAccelerationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the backlashDistance
|
||||
*/
|
||||
public Channel<Double> getBacklashDistance() {
|
||||
return backlashDistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the moveFracion
|
||||
*/
|
||||
public Channel<Double> getMoveFracion() {
|
||||
return moveFracion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the motorResolution
|
||||
*/
|
||||
public Channel<Double> getMotorResolution() {
|
||||
return motorResolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the encoderResolution
|
||||
*/
|
||||
public Channel<Double> getEncoderResolution() {
|
||||
return encoderResolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the readbackResolution
|
||||
*/
|
||||
public Channel<Double> getReadbackResolution() {
|
||||
return readbackResolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the retryDeadband
|
||||
*/
|
||||
public Channel<Double> getRetryDeadband() {
|
||||
return retryDeadband;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maxRetryCount
|
||||
*/
|
||||
public Channel<Integer> getMaxRetryCount() {
|
||||
return maxRetryCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the retryCount
|
||||
*/
|
||||
public Channel<Integer> getRetryCount() {
|
||||
return retryCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the useEncoder
|
||||
*/
|
||||
public Channel<Boolean> getUseEncoder() {
|
||||
return useEncoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the useReadback
|
||||
*/
|
||||
public Channel<Boolean> getUseReadback() {
|
||||
return useReadback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the readbackDelay
|
||||
*/
|
||||
public Channel<Double> getReadbackDelay() {
|
||||
return readbackDelay;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the readbackLink
|
||||
*/
|
||||
public Channel<String> getReadbackLink() {
|
||||
return readbackLink;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the outputMode
|
||||
*/
|
||||
public Channel<Integer> getOutputMode() {
|
||||
return outputMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the moveDone
|
||||
*/
|
||||
public Channel<Boolean> getMoveDone() {
|
||||
return moveDone;
|
||||
}
|
||||
@@ -24,17 +24,12 @@ import java.util.List;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.annotation.CaChannel;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class VSC16ScalerChannelsTemplate {
|
||||
public class TemplateVSC16Scaler {
|
||||
|
||||
|
||||
public enum Command {Done, Count};
|
||||
/**
|
||||
* Command
|
||||
*/
|
||||
public enum Command {Done, Count};
|
||||
@CaChannel(type=Integer.class, name ="${PREFIX}.CNT")
|
||||
private Channel<Integer> command;
|
||||
|
||||
@@ -65,39 +60,21 @@ public class VSC16ScalerChannelsTemplate {
|
||||
@CaChannel(type=Integer.class, name={"${PREFIX}.PR1", "${PREFIX}.PR2", "${PREFIX}.PR3", "${PREFIX}.PR4", "${PREFIX}.PR5", "${PREFIX}.PR6", "${PREFIX}.PR7", "${PREFIX}.PR8", "${PREFIX}.PR9", "${PREFIX}.PR10", "${PREFIX}.PR11", "${PREFIX}.PR12", "${PREFIX}.PR13", "${PREFIX}.PR14", "${PREFIX}.PR15", "${PREFIX}.PR16"})
|
||||
private List<Channel<Integer>> channelPresetCount;
|
||||
|
||||
/**
|
||||
* @return the command
|
||||
*/
|
||||
|
||||
|
||||
public Channel<Integer> getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mode
|
||||
*/
|
||||
public Channel<Integer> getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the channelDescription
|
||||
*/
|
||||
public List<Channel<Boolean>> getChannelDescription() {
|
||||
return channelDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the channelGate
|
||||
*/
|
||||
public List<Channel<Boolean>> getChannelGate() {
|
||||
return channelGate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the channelPresetCount
|
||||
*/
|
||||
public List<Channel<Integer>> getChannelPresetCount() {
|
||||
return channelPresetCount;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,15 +19,11 @@
|
||||
|
||||
package ch.psi.fda.core.loops.cr;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class TimestampedValue {
|
||||
|
||||
private Double value;
|
||||
private long timestamp;
|
||||
private long nanosecondsOffset;
|
||||
private final Double value;
|
||||
private final long timestamp;
|
||||
private final long nanosecondsOffset;
|
||||
|
||||
public TimestampedValue(Double value, long timestamp, long nanosecondsOffset){
|
||||
this.value = value;
|
||||
@@ -35,47 +31,13 @@ public class TimestampedValue {
|
||||
this.nanosecondsOffset = nanosecondsOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value
|
||||
*/
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value the value to set
|
||||
*/
|
||||
public void setValue(Double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the timestamp
|
||||
*/
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param timestamp the timestamp to set
|
||||
*/
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the nanosecondsOffset
|
||||
*/
|
||||
public long getNanosecondsOffset() {
|
||||
return nanosecondsOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nanosecondsOffset the nanosecondsOffset to set
|
||||
*/
|
||||
public void setNanosecondsOffset(long nanosecondsOffset) {
|
||||
this.nanosecondsOffset = nanosecondsOffset;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -22,8 +22,7 @@ package ch.psi.fda.core.loops.cr;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
* Comparator for comparint 2 timestamped values
|
||||
*/
|
||||
public class TimestampedValueComparator implements Comparator<TimestampedValue> {
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.core.loops;
|
||||
package ch.psi.fda.core.loops.otf;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
@@ -26,10 +26,6 @@ import java.net.MalformedURLException;
|
||||
|
||||
import jcifs.smb.SmbFile;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class DistributedFile {
|
||||
|
||||
private SmbFile smbfile = null;
|
||||
@@ -17,57 +17,32 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.loops;
|
||||
package ch.psi.fda.core.loops.otf;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
//import jcifs.smb.SmbException;
|
||||
//import jcifs.smb.SmbFile;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ch.psi.fda.core.Action;
|
||||
import ch.psi.fda.core.ActionLoop;
|
||||
import ch.psi.fda.core.Sensor;
|
||||
import ch.psi.fda.core.actors.OTFActuator;
|
||||
import ch.psi.fda.core.messages.ComponentMetadata;
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import ch.psi.fda.core.messages.EndOfStreamMessage;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
import ch.psi.fda.core.sensors.MillisecondTimestampSensor;
|
||||
import ch.psi.fda.core.sensors.OTFNamedChannelSensor;
|
||||
import ch.psi.fda.core.sensors.OTFReadbackSensor;
|
||||
import ch.psi.fda.core.sensors.OTFScalerChannelSensor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
import ch.psi.fda.core.messages.Metadata;
|
||||
import ch.psi.fda.core.sensors.TimestampSensor;
|
||||
|
||||
/**
|
||||
* ActionLoop that is implementing the OTF Scan logic.
|
||||
* While executing the loop a full OTF scan procedure is executed.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class OTFLoop implements ActionLoop {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(OTFLoop.class.getName());
|
||||
|
||||
/**
|
||||
@@ -76,7 +51,6 @@ public class OTFLoop implements ActionLoop {
|
||||
*/
|
||||
private boolean dataGroup = false;
|
||||
|
||||
// Constants
|
||||
/**
|
||||
* Maximum number of monitored channels
|
||||
*/
|
||||
@@ -112,7 +86,7 @@ public class OTFLoop implements ActionLoop {
|
||||
/**
|
||||
* Bean holding all OTF channels and functionality.
|
||||
*/
|
||||
private OTFBean obean;
|
||||
private TemplateOTF obean;
|
||||
|
||||
/**
|
||||
* List of actions that are executed at the beginning of the loop.
|
||||
@@ -123,11 +97,6 @@ public class OTFLoop implements ActionLoop {
|
||||
*/
|
||||
private List<Action> postActions;
|
||||
|
||||
/**
|
||||
* Special OTF Actuator
|
||||
*/
|
||||
private OTFActuator actor = null;
|
||||
|
||||
/**
|
||||
* List of sensors of this loop
|
||||
*/
|
||||
@@ -142,40 +111,36 @@ public class OTFLoop implements ActionLoop {
|
||||
*/
|
||||
private int executionCount;
|
||||
|
||||
/**
|
||||
* Data queue sensor data is posted to. A message consists of a list of data objects
|
||||
* that are read out of the sensors of this loop.
|
||||
*/
|
||||
private BlockingQueue<Message> dataQueue;
|
||||
|
||||
/**
|
||||
* Flag that indicates that the loop was requested to abort.
|
||||
*/
|
||||
private volatile boolean abort = false;
|
||||
|
||||
private ChannelService cservice;
|
||||
|
||||
private String id;
|
||||
private String name; // name of the motor channel
|
||||
private String readback; // name of the encoder channel
|
||||
private double start;
|
||||
private double end;
|
||||
private double stepSize;
|
||||
private double integrationTime;
|
||||
private double additionalBacklash;
|
||||
|
||||
private final EventBus eventbus;
|
||||
private List<Metadata> metadata;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param channelPrefix Prefix of the OTF related records, e.g. MTEST-HW3-OTF
|
||||
* @param server NFS server the OTF C Logic should put its data to
|
||||
* @param share Share on NFS server to put the OTF C Logic data
|
||||
* @param smbShare SMB share to get the data written by the OTF C Logic
|
||||
* @param zigZag Operate loop in zig zag mode
|
||||
*/
|
||||
public OTFLoop(ChannelService s, String channelPrefix, String server, String share, String smbShare, boolean zigZag){
|
||||
cservice = s;
|
||||
// Initialize connection to the OTF records
|
||||
try {
|
||||
this.obean = new OTFBean();
|
||||
Map<String,String> m = new HashMap<>();
|
||||
m.put("PREFIX", channelPrefix);
|
||||
s.createAnnotatedChannels(obean, m);
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
throw new IllegalArgumentException("Unable to connect to the OTF channels",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to connect to the OTF channels",e);
|
||||
}
|
||||
public OTFLoop(TemplateOTF obean, String server, String share, String smbShare, boolean zigZag){
|
||||
|
||||
this.eventbus = new EventBus();
|
||||
|
||||
this.obean = obean;
|
||||
|
||||
// Store loop configuration
|
||||
this.server = server;
|
||||
@@ -187,13 +152,20 @@ public class OTFLoop implements ActionLoop {
|
||||
this.preActions = new ArrayList<Action>();
|
||||
this.postActions = new ArrayList<Action>();
|
||||
this.sensors = new ArrayList<Sensor>();
|
||||
|
||||
this.dataQueue = new LinkedBlockingQueue<Message>(2000);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#execute()
|
||||
*/
|
||||
public void setActuator(String id, String name, String readback, double start, double end, double stepSize, double integrationTime, double additionalBacklash){
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.readback = readback;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.stepSize = stepSize;
|
||||
this.integrationTime = integrationTime;
|
||||
this.additionalBacklash = additionalBacklash;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void execute() throws InterruptedException {
|
||||
|
||||
@@ -218,15 +190,12 @@ public class OTFLoop implements ActionLoop {
|
||||
|
||||
|
||||
// Issue end of loop control message
|
||||
dataQueue.put(new EndOfStreamMessage(dataGroup));
|
||||
eventbus.post(new EndOfStreamMessage(dataGroup));
|
||||
|
||||
// Increase execution count
|
||||
executionCount++;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#abort()
|
||||
*/
|
||||
@Override
|
||||
public void abort() {
|
||||
// Abort otf scan logic
|
||||
@@ -235,9 +204,6 @@ public class OTFLoop implements ActionLoop {
|
||||
abort=true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#prepare()
|
||||
*/
|
||||
@Override
|
||||
public void prepare() {
|
||||
executionCount = 0;
|
||||
@@ -245,14 +211,10 @@ public class OTFLoop implements ActionLoop {
|
||||
// Set abort flag to false
|
||||
abort=false;
|
||||
|
||||
// Check whether actor is set for the loop
|
||||
if(actor == null){
|
||||
throw new IllegalStateException("No actor specified for this loop");
|
||||
}
|
||||
|
||||
// list with all monitored channels
|
||||
List<String> monitoredChannels = new ArrayList<String>();
|
||||
dataIndexes = new ArrayList<Integer>();
|
||||
dataIndexes.add(1); // The first one is always the readback of the motor
|
||||
int channelCount =0;
|
||||
for(Sensor s: sensors){
|
||||
if(s instanceof OTFNamedChannelSensor){
|
||||
@@ -275,12 +237,12 @@ public class OTFLoop implements ActionLoop {
|
||||
}
|
||||
dataIndexes.add(2+so.getIndex()); // scalers follow directly after the readback
|
||||
}
|
||||
else if (s instanceof MillisecondTimestampSensor){
|
||||
else if (s instanceof TimestampSensor){
|
||||
dataIndexes.add(2+numberOfScalerChannels+numberOfMonitoredChannels);
|
||||
}
|
||||
else if (s instanceof OTFReadbackSensor){
|
||||
dataIndexes.add(1);
|
||||
}
|
||||
// else if (s instanceof OTFReadbackSensor){
|
||||
// dataIndexes.add(1);
|
||||
// }
|
||||
else{
|
||||
throw new IllegalArgumentException("Sensor type "+s.getClass()+" is not supported by this loop");
|
||||
}
|
||||
@@ -291,23 +253,23 @@ public class OTFLoop implements ActionLoop {
|
||||
obean.resetToDefaults();
|
||||
|
||||
// Set actor properties
|
||||
obean.setMotor(actor.getName());
|
||||
obean.setMotor(this.name);
|
||||
obean.waitUntilMotorOk(timeout);
|
||||
|
||||
obean.setBegin(actor.getStart());
|
||||
obean.setEnd(actor.getEnd());
|
||||
obean.setStepSize(actor.getStepSize());
|
||||
obean.setIntegrationTime(actor.getIntegrationTime());
|
||||
obean.setBegin(this.start);
|
||||
obean.setEnd(this.end);
|
||||
obean.setStepSize(this.stepSize);
|
||||
obean.setIntegrationTime(this.integrationTime);
|
||||
|
||||
// Override encoder if specified
|
||||
if(actor.getReadback()!=null){
|
||||
if(this.readback!=null){
|
||||
obean.setUseEncoder(true);
|
||||
obean.setEncoder(actor.getReadback());
|
||||
obean.setEncoder(this.readback);
|
||||
obean.waitUntilEncoderOk(timeout);
|
||||
}
|
||||
|
||||
// Set user backlash
|
||||
obean.setUserBacklash(actor.getAdditionalBacklash());
|
||||
obean.setUserBacklash(this.additionalBacklash);
|
||||
|
||||
|
||||
// NFS settings
|
||||
@@ -325,9 +287,7 @@ public class OTFLoop implements ActionLoop {
|
||||
// Set monitored channels
|
||||
obean.setMonitoredChannels(monitoredChannels.toArray(new String[monitoredChannels.size()]));
|
||||
}
|
||||
catch(ChannelException | ExecutionException | TimeoutException e){
|
||||
throw new RuntimeException("Unable to set OTF configuration parameters",e);
|
||||
} catch (InterruptedException e) {
|
||||
catch(Exception e){
|
||||
throw new RuntimeException("Unable to set OTF configuration parameters",e);
|
||||
}
|
||||
|
||||
@@ -354,61 +314,29 @@ public class OTFLoop implements ActionLoop {
|
||||
throw new RuntimeException("Unable to access share (temporary files)",e);
|
||||
}
|
||||
|
||||
metadata = new ArrayList<>();
|
||||
metadata.add(new Metadata(id)); // Id of the readback of the motor
|
||||
|
||||
// Build up data message metadata based on the sensors currently registered.
|
||||
for(Sensor s: sensors){
|
||||
metadata.add(new Metadata(s.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#cleanup()
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Action#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Close all connections used by the OTFBean
|
||||
try {
|
||||
cservice.destroyAnnotatedChannels(obean);
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channels",e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#getPreActions()
|
||||
*/
|
||||
@Override
|
||||
public List<Action> getPreActions() {
|
||||
return preActions;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#getPostActions()
|
||||
*/
|
||||
@Override
|
||||
public List<Action> getPostActions() {
|
||||
return postActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* The structure of the data message depends on the sensors registered at this loop
|
||||
* at the time this method is called.
|
||||
* @return the data queue and the metadata of the data messages
|
||||
*/
|
||||
public DataQueue getDataQueue() {
|
||||
DataMessageMetadata m = new DataMessageMetadata();
|
||||
|
||||
// Build up data message metadata based on the sensors currently registered.
|
||||
for(Sensor s: sensors){
|
||||
m.getComponents().add(new ComponentMetadata(s.getId()));
|
||||
}
|
||||
return new DataQueue(dataQueue, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect data written by the OTFScan logic
|
||||
* @param dataSet
|
||||
@@ -453,7 +381,7 @@ public class OTFLoop implements ActionLoop {
|
||||
continue;
|
||||
}
|
||||
|
||||
DataMessage message = new DataMessage();
|
||||
DataMessage message = new DataMessage(metadata);
|
||||
// Add data to dataset
|
||||
String[] tokens = line.split("\t");
|
||||
|
||||
@@ -477,7 +405,7 @@ public class OTFLoop implements ActionLoop {
|
||||
message.getData().add(new Double(0));
|
||||
}
|
||||
}
|
||||
dataQueue.put(message);
|
||||
eventbus.post(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -491,43 +419,21 @@ public class OTFLoop implements ActionLoop {
|
||||
}
|
||||
|
||||
|
||||
// Getter functions for variable parts
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return the sensors
|
||||
*/
|
||||
public List<Sensor> getSensors() {
|
||||
return sensors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the actor
|
||||
*/
|
||||
public OTFActuator getActor() {
|
||||
return actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param actor the actor to set
|
||||
*/
|
||||
public void setActor(OTFActuator actor) {
|
||||
this.actor = actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dataGroup
|
||||
*/
|
||||
public boolean isDataGroup() {
|
||||
return dataGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dataGroup the dataGroup to set
|
||||
*/
|
||||
public void setDataGroup(boolean dataGroup) {
|
||||
this.dataGroup = dataGroup;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.ActionLoop#getEventBus()
|
||||
*/
|
||||
@Override
|
||||
public EventBus getEventBus() {
|
||||
return eventbus;
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.sensors;
|
||||
package ch.psi.fda.core.loops.otf;
|
||||
|
||||
import ch.psi.fda.core.Sensor;
|
||||
|
||||
@@ -49,9 +49,6 @@ public class OTFNamedChannelSensor implements Sensor {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#read()
|
||||
*/
|
||||
@Override
|
||||
public Object read() {
|
||||
// Always return 0 if read() method is called.
|
||||
@@ -65,20 +62,8 @@ public class OTFNamedChannelSensor implements Sensor {
|
||||
return name;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#getId()
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Nothing to be done
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,14 +17,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.sensors;
|
||||
package ch.psi.fda.core.loops.otf;
|
||||
|
||||
import ch.psi.fda.core.Sensor;
|
||||
|
||||
/**
|
||||
* Sensor to read out a scaler channel. This sensor can only be used within the
|
||||
* OTFLoop. If it is used in other loops, the read value will always be 0.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class OTFScalerChannelSensor implements Sensor {
|
||||
@@ -49,12 +48,8 @@ public class OTFScalerChannelSensor implements Sensor {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#read()
|
||||
*/
|
||||
@Override
|
||||
public Object read() {
|
||||
// Always return 0 if read() method is called.
|
||||
return 0d;
|
||||
}
|
||||
|
||||
@@ -65,20 +60,8 @@ public class OTFScalerChannelSensor implements Sensor {
|
||||
return index;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#getId()
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Nothing to be done
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,22 +17,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.loops;
|
||||
package ch.psi.fda.core.loops.otf;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import ch.psi.jcae.annotation.CaChannel;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.annotation.CaChannel;
|
||||
|
||||
/**
|
||||
* Bean holding all OTF channels and functionality
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class OTFBean {
|
||||
public class TemplateOTF {
|
||||
|
||||
public enum Status { SETUP, INACTIVE, INITIALIZE, ACTIVE, STOP, FAULT, ERROR };
|
||||
public enum Command { NONE, START, STOP };
|
||||
@@ -211,7 +211,7 @@ public class OTFBean {
|
||||
throw new RuntimeException("OTFSCAN failed with message: "+message.getValue());
|
||||
}
|
||||
|
||||
} catch (ChannelException | ExecutionException | TimeoutException e) {
|
||||
} catch (ExecutionException | ChannelException | TimeoutException e) {
|
||||
throw new RuntimeException("An error occurred while waiting for the OTF logic to finish.", e);
|
||||
}
|
||||
}
|
||||
@@ -230,7 +230,7 @@ public class OTFBean {
|
||||
throw new RuntimeException("OTFSCAN failed with message: "+message.getValue());
|
||||
}
|
||||
|
||||
} catch (ChannelException | ExecutionException | TimeoutException e) {
|
||||
} catch (ExecutionException | ChannelException | TimeoutException e) {
|
||||
throw new RuntimeException("An error occurred while waiting for the OTF logic to finish.", e);
|
||||
}
|
||||
|
||||
@@ -240,10 +240,11 @@ public class OTFBean {
|
||||
|
||||
/**
|
||||
* Reset OTFScan records to defaults
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void resetToDefaults() throws ChannelException , ExecutionException , TimeoutException, InterruptedException{
|
||||
public void resetToDefaults() throws InterruptedException{
|
||||
try{
|
||||
setMonitoredChannels(new String[]{});
|
||||
setMotor("");
|
||||
begin.setValue(0d);
|
||||
@@ -263,219 +264,254 @@ public class OTFBean {
|
||||
// setNfsShare("");
|
||||
|
||||
waitUntilMotorNotOk(timeoutMotorOk);
|
||||
}
|
||||
catch(ExecutionException | ChannelException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get motor of the OTFScan axis
|
||||
* @return Name of the OTF motor
|
||||
* @throws ExecutionException
|
||||
* @throws TimeoutException
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public String getMotor() throws ChannelException, InterruptedException, TimeoutException, ExecutionException {
|
||||
return(this.motor.getValue());
|
||||
public String getMotor() throws InterruptedException {
|
||||
try {
|
||||
return(this.motor.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set motor of the OTFScan axis
|
||||
* @param motor
|
||||
* @throws ChannelException
|
||||
* @throws ExecutionException
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setMotor(String motor) throws InterruptedException, ExecutionException, ChannelException {
|
||||
this.motor.setValue(motor);
|
||||
public void setMotor(String motor) throws InterruptedException {
|
||||
try{
|
||||
this.motor.setValue(motor);
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get encoder of the OTFScan axis
|
||||
* @return Name of the used encoder
|
||||
* @throws ExecutionException
|
||||
* @throws ChannelException
|
||||
* @throws TimeoutException
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public String getEncoder() throws InterruptedException, TimeoutException, ChannelException, ExecutionException {
|
||||
return(this.encoder.getValue());
|
||||
public String getEncoder() throws InterruptedException {
|
||||
try{
|
||||
return(this.encoder.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set encoder to use of the OTFScan axis
|
||||
* @param encoder
|
||||
* @throws ChannelException
|
||||
* @throws ExecutionException
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setEncoder(String encoder) throws InterruptedException, ExecutionException, ChannelException {
|
||||
this.encoder.setValue(encoder);
|
||||
public void setEncoder(String encoder) throws InterruptedException {
|
||||
try{
|
||||
this.encoder.setValue(encoder);
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get begin position of the scan
|
||||
* @return Begin position scan
|
||||
* @throws ExecutionException
|
||||
* @throws ChannelException
|
||||
* @throws TimeoutException
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public Double getBegin() throws InterruptedException, TimeoutException, ChannelException, ExecutionException {
|
||||
return(this.begin.getValue());
|
||||
public Double getBegin() throws InterruptedException {
|
||||
try{
|
||||
return(this.begin.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set begin position of scan
|
||||
* @param begin
|
||||
* @throws ExecutionException
|
||||
* @throws ChannelException
|
||||
* @throws TimeoutException
|
||||
* @throws Exception
|
||||
*/
|
||||
public void setBegin(Double begin) throws InterruptedException, TimeoutException, ChannelException, ExecutionException {
|
||||
|
||||
if(begin==null){
|
||||
throw new IllegalArgumentException("Begin position must not be null");
|
||||
public void setBegin(Double begin) throws InterruptedException {
|
||||
try{
|
||||
if(begin==null){
|
||||
throw new IllegalArgumentException("Begin position must not be null");
|
||||
}
|
||||
|
||||
if(begin < beginMin.getValue() || begin > beginMax.getValue()){
|
||||
throw new IllegalArgumentException("Cannot set begin value to "+begin+ ". Value is outside range [min: "+beginMin.getValue()+" max: "+beginMax.getValue()+"]");
|
||||
}
|
||||
|
||||
this.begin.setValue(begin);
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if(begin < beginMin.getValue() || begin > beginMax.getValue()){
|
||||
throw new IllegalArgumentException("Cannot set begin value to "+begin+ ". Value is outside range [min: "+beginMin.getValue()+" max: "+beginMax.getValue()+"]");
|
||||
}
|
||||
|
||||
this.begin.setValue(begin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get minimum value of the begin position
|
||||
* @return Min value for begin
|
||||
* @throws ExecutionException
|
||||
* @throws ChannelException
|
||||
* @throws TimeoutException
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public Double getMinBegin() throws InterruptedException, TimeoutException, ChannelException, ExecutionException {
|
||||
return(this.beginMin.getValue());
|
||||
public Double getMinBegin() throws InterruptedException {
|
||||
try{
|
||||
return(this.beginMin.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get maximum value of the begin position
|
||||
* @return Max value for begin
|
||||
* @throws ExecutionException
|
||||
* @throws ChannelException
|
||||
* @throws TimeoutException
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public Double getMaxBegin() throws InterruptedException, TimeoutException, ChannelException, ExecutionException {
|
||||
return(this.beginMax.getValue());
|
||||
public Double getMaxBegin() throws InterruptedException {
|
||||
try{
|
||||
return(this.beginMax.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get end position of the scan
|
||||
* @return End position scan
|
||||
* @throws ExecutionException
|
||||
* @throws ChannelException
|
||||
* @throws TimeoutException
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public Double getEnd() throws InterruptedException, TimeoutException, ChannelException, ExecutionException {
|
||||
return(this.end.getValue());
|
||||
public Double getEnd() throws InterruptedException {
|
||||
try{
|
||||
return(this.end.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set end positon of scan
|
||||
* @param end
|
||||
* @throws ExecutionException
|
||||
* @throws ChannelException
|
||||
* @throws TimeoutException
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setEnd(Double end) throws InterruptedException, TimeoutException, ChannelException, ExecutionException {
|
||||
|
||||
if(end==null){
|
||||
throw new IllegalArgumentException("End position must not be null");
|
||||
public void setEnd(Double end) throws InterruptedException {
|
||||
try{
|
||||
if(end==null){
|
||||
throw new IllegalArgumentException("End position must not be null");
|
||||
}
|
||||
|
||||
if(end < endMin.getValue() || end > endMax.getValue()){
|
||||
throw new IllegalArgumentException("Cannot set end value to "+end+ ". Value is outside range [min: "+endMin.getValue()+" max: "+endMax.getValue()+"]");
|
||||
}
|
||||
|
||||
this.end.setValue(end);
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if(end < endMin.getValue() || end > endMax.getValue()){
|
||||
throw new IllegalArgumentException("Cannot set end value to "+end+ ". Value is outside range [min: "+endMin.getValue()+" max: "+endMax.getValue()+"]");
|
||||
}
|
||||
|
||||
this.end.setValue(end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get minimum value of end position
|
||||
* @return Min value for end
|
||||
* @throws ExecutionException
|
||||
* @throws ChannelException
|
||||
* @throws TimeoutException
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public Double getMinEnd() throws InterruptedException, TimeoutException, ChannelException, ExecutionException {
|
||||
return(this.endMin.getValue());
|
||||
public Double getMinEnd() throws InterruptedException {
|
||||
try{
|
||||
return(this.endMin.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get maximum value of end position
|
||||
* @return Max value for end
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public Double getMaxEnd() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
return(this.endMax.getValue());
|
||||
public Double getMaxEnd() throws InterruptedException {
|
||||
try{
|
||||
return(this.endMax.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scan step size
|
||||
* @return Step size
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public Double getStepSize() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
return(this.stepSize.getValue());
|
||||
public Double getStepSize() throws InterruptedException {
|
||||
try{
|
||||
return(this.stepSize.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set step size of scan
|
||||
* @param stepSize
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setStepSize(Double stepSize) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
|
||||
if(integrationTime==null){
|
||||
throw new IllegalArgumentException("Step size must not be null");
|
||||
public void setStepSize(Double stepSize) throws InterruptedException {
|
||||
try{
|
||||
if(integrationTime==null){
|
||||
throw new IllegalArgumentException("Step size must not be null");
|
||||
}
|
||||
|
||||
// Check if step size is greater than min step size
|
||||
if(stepSizeMin.getValue() != 0 && stepSize < stepSizeMin.getValue()){
|
||||
throw new IllegalArgumentException("Step size value ["+stepSize+"] is less than minimum step size ["+stepSizeMin.getValue()+"]!");
|
||||
}
|
||||
|
||||
this.stepSize.setValue(stepSize);
|
||||
|
||||
// TODO WORKAROUND - Wait to "ensure" that step size related fields are updated (i.e. min/max integration time)
|
||||
Thread.sleep(1);
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// Check if step size is greater than min step size
|
||||
if(stepSizeMin.getValue() != 0 && stepSize < stepSizeMin.getValue()){
|
||||
throw new IllegalArgumentException("Step size value ["+stepSize+"] is less than minimum step size ["+stepSizeMin.getValue()+"]!");
|
||||
}
|
||||
|
||||
this.stepSize.setValue(stepSize);
|
||||
|
||||
// TODO WORKAROUND - Wait to "ensure" that step size related fields are updated (i.e. min/max integration time)
|
||||
Thread.sleep(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get minimum integration time
|
||||
* @return Min value for step size
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public double getMinStepSize() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
return(this.stepSizeMin.getValue());
|
||||
public double getMinStepSize() throws InterruptedException {
|
||||
try{
|
||||
return(this.stepSizeMin.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scan integration time (time that is spend in one step)
|
||||
* @return Integration time
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public Double getIntegrationTime() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
return(this.integrationTime.getValue());
|
||||
public Double getIntegrationTime() throws InterruptedException {
|
||||
try{
|
||||
return(this.integrationTime.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set integration time of scan
|
||||
* @param integrationTime
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setIntegrationTime(Double integrationTime) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
|
||||
public void setIntegrationTime(Double integrationTime) throws InterruptedException {
|
||||
try{
|
||||
if(integrationTime==null){
|
||||
throw new IllegalArgumentException("Integration time must not be null");
|
||||
}
|
||||
@@ -498,108 +534,155 @@ public class OTFBean {
|
||||
}
|
||||
|
||||
this.integrationTime.setValue(integrationTime);
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get minimum integration time
|
||||
* @return Min value for integration time
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public Double getMinIntegrationTime() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public Double getMinIntegrationTime() throws InterruptedException {
|
||||
try{
|
||||
return(this.integrationTimeMin.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get maximum integration time
|
||||
* @return Max value for integration time
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public Double getMaxIntegrationTime() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public Double getMaxIntegrationTime() throws InterruptedException {
|
||||
try{
|
||||
return(this.integrationTimeMax.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get additional user defined backlash
|
||||
* @return User backlash
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public Double getUserBacklash() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public Double getUserBacklash() throws InterruptedException {
|
||||
try{
|
||||
return(this.userBacklash.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set additional user defined backlash
|
||||
* @param userBacklash
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setUserBacklash(Double userBacklash) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
if(userBacklash==null){
|
||||
throw new IllegalArgumentException("User backlash must not be null");
|
||||
public void setUserBacklash(Double userBacklash) throws InterruptedException {
|
||||
try{
|
||||
if(userBacklash==null){
|
||||
throw new IllegalArgumentException("User backlash must not be null");
|
||||
}
|
||||
|
||||
this.userBacklash.setValue(userBacklash);
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
this.userBacklash.setValue(userBacklash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current NFS server the data is written to
|
||||
* @return Name of NFS server
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public String getNfsServer() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public String getNfsServer() throws InterruptedException {
|
||||
try{
|
||||
return(this.nfsServer.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name of the NFS server the data is written to
|
||||
* @param nfsServer
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setNfsServer(String nfsServer) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public void setNfsServer(String nfsServer) throws InterruptedException {
|
||||
try{
|
||||
this.nfsServer.setValue(nfsServer);
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the NFS share the data is written to
|
||||
* @return Name of NFS share
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public String getNfsShare() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
return(this.nfsShare.getValue());
|
||||
public String getNfsShare() throws InterruptedException {
|
||||
try{
|
||||
return(this.nfsShare.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name of the NFS share the data is written to
|
||||
* @param nfsShare
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setNfsShare(String nfsShare) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
this.nfsShare.setValue(nfsShare);
|
||||
public void setNfsShare(String nfsShare) throws InterruptedException {
|
||||
try{
|
||||
this.nfsShare.setValue(nfsShare);
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the data file
|
||||
* @return Name of data file name
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public String getFileName() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public String getFileName() throws InterruptedException {
|
||||
try{
|
||||
return(this.fileName.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name of the data file
|
||||
* @param filename
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setFileName(String filename) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
this.fileName.setValue(filename);
|
||||
public void setFileName(String filename) throws InterruptedException {
|
||||
try{
|
||||
this.fileName.setValue(filename);
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get File name formate
|
||||
* @return Get format for file name
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public String getFileNameFormat() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
return(this.fileNameFormat.getValue());
|
||||
public String getFileNameFormat() throws InterruptedException {
|
||||
try{
|
||||
return(this.fileNameFormat.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -607,109 +690,157 @@ public class OTFBean {
|
||||
* @param fileNameFormat
|
||||
* @throws Exception
|
||||
*/
|
||||
public void setFileNameFormat(String fileNameFormat) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
this.fileNameFormat.setValue(fileNameFormat);
|
||||
public void setFileNameFormat(String fileNameFormat) throws InterruptedException {
|
||||
try{
|
||||
this.fileNameFormat.setValue(fileNameFormat);
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value of the IOC based file name counter
|
||||
* @return File counter
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public int getFileCounter() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public int getFileCounter() throws InterruptedException {
|
||||
try{
|
||||
return(this.fileCount.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the IOC based file counter
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void resetFileCounter() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public void resetFileCounter() throws InterruptedException {
|
||||
try{
|
||||
this.resetFileCounter.setValue(1);
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if append file option is activated
|
||||
* @return Append file flag
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public boolean isAppendFile() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public boolean isAppendFile() throws InterruptedException {
|
||||
try{
|
||||
return(this.appendFile.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to append the specified file if the file exists
|
||||
* @param append
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setAppendFile(boolean append) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public void setAppendFile(boolean append) throws InterruptedException {
|
||||
try{
|
||||
this.appendFile.setValue(append);
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if file name generation is on or off
|
||||
* @return File name generation flag
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public boolean isFileNameGeneration() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public boolean isFileNameGeneration() throws InterruptedException {
|
||||
try{
|
||||
return(this.fileNameGeneration.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Whether the file name should be generated out of the file name format and the file counter
|
||||
* @param generation
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setFileNameGeneration(boolean generation) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
this.fileNameGeneration.setValue(generation);
|
||||
public void setFileNameGeneration(boolean generation) throws InterruptedException {
|
||||
try{
|
||||
this.fileNameGeneration.setValue(generation);
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if ZigZag scan option is on or off
|
||||
* @return ZigZag flag
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public boolean isZigZag() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
return(this.zigZag.getValue());
|
||||
public boolean isZigZag() throws InterruptedException {
|
||||
try{
|
||||
return(this.zigZag.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ZigZag scan mode on/off
|
||||
* @param zigZag ZigZag mode on = true, ZigZag mode off = false
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setZigZag(boolean zigZag) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
this.zigZag.setValue(zigZag);
|
||||
public void setZigZag(boolean zigZag) throws InterruptedException {
|
||||
try{
|
||||
this.zigZag.setValue(zigZag);
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether encoder is used
|
||||
*/
|
||||
public boolean isUseEncoder() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
return(this.useEncoder.getValue());
|
||||
public boolean isUseEncoder() throws InterruptedException {
|
||||
try{
|
||||
return(this.useEncoder.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set flag to use encoder
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setUseEncoder(boolean flag) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public void setUseEncoder(boolean flag) throws InterruptedException {
|
||||
try{
|
||||
this.useEncoder.setValue(flag);
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels that are currently monitored by the OTFScan logic
|
||||
* @return Names of the monitored channels
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public String[] getMonitoredChannels() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
String[] values = new String[this.monitoredChannels.size()];
|
||||
|
||||
for(int i=0; i<this.monitoredChannels.size();i++){
|
||||
values[i] = monitoredChannels.get(i).getValue();
|
||||
public String[] getMonitoredChannels() throws InterruptedException {
|
||||
try{
|
||||
String[] values = new String[this.monitoredChannels.size()];
|
||||
|
||||
for(int i=0; i<this.monitoredChannels.size();i++){
|
||||
values[i] = monitoredChannels.get(i).getValue();
|
||||
}
|
||||
|
||||
return(values);
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return(values);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -717,85 +848,117 @@ public class OTFBean {
|
||||
* Note: As OTF only supports 8 channels to be monitored, only the first 8
|
||||
* values of the passed channelNames are considered.
|
||||
* @param values Array of channel names to be monitored
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public void setMonitoredChannels(String[] values) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public void setMonitoredChannels(String[] values) throws InterruptedException {
|
||||
|
||||
if(values.length>monitoredChannels.size()){
|
||||
throw new IllegalArgumentException("Only up to "+monitoredChannels.size()+" monitored channels are supported by OTF");
|
||||
}
|
||||
|
||||
for(int i=0; i<this.monitoredChannels.size(); i++){
|
||||
if(values != null && i<values.length){
|
||||
this.monitoredChannels.get(i).setValue(values[i]);
|
||||
try{
|
||||
if(values.length>monitoredChannels.size()){
|
||||
throw new IllegalArgumentException("Only up to "+monitoredChannels.size()+" monitored channels are supported by OTF");
|
||||
}
|
||||
else{
|
||||
this.monitoredChannels.get(i).setValue("");
|
||||
|
||||
for(int i=0; i<this.monitoredChannels.size(); i++){
|
||||
if(values != null && i<values.length){
|
||||
this.monitoredChannels.get(i).setValue(values[i]);
|
||||
}
|
||||
else{
|
||||
this.monitoredChannels.get(i).setValue("");
|
||||
}
|
||||
}
|
||||
} catch (ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether an scan is running
|
||||
* @return Running flag
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public boolean isRunning() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
return(running.getValue());
|
||||
public boolean isRunning() throws InterruptedException {
|
||||
try{
|
||||
return(running.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status of the scan
|
||||
* @return Status of the scan
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public Status getStatus() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
return(Status.values()[this.status.getValue()]);
|
||||
public Status getStatus() throws InterruptedException {
|
||||
try{
|
||||
return(Status.values()[this.status.getValue()]);
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the (error) message from the OTF records
|
||||
* @return Message from OTF C logic
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public String getMessage() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
return(message.getValue());
|
||||
public String getMessage() throws InterruptedException {
|
||||
try{
|
||||
return(message.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the specified motor is recognized as ok (i.e. it is registered as OTFScan motor)
|
||||
* @return Flag whether motor is ok
|
||||
* @throws TimeoutException, ChannelException, ExecutionException
|
||||
* @throws CAException
|
||||
*/
|
||||
public boolean isMotorOk() throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
return(motorOk.getValue());
|
||||
public boolean isMotorOk() throws InterruptedException {
|
||||
try{
|
||||
return(motorOk.getValue());
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the motor flag goes to ok
|
||||
* @param timeout Timout in milliseconds
|
||||
*
|
||||
* @throws TimeoutException, ChannelException, ExecutionException If motor ok flag does not switch to ok within the specified timeout
|
||||
* @throws CAException If motor ok flag does not switch to ok within the specified timeout
|
||||
*/
|
||||
public void waitUntilMotorOk(long timeout) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public void waitUntilMotorOk(long timeout) throws InterruptedException {
|
||||
try{
|
||||
motorOk.waitForValue(true, timeout);
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the motor flag goes to not ok
|
||||
* @param timeout Timout in milliseconds
|
||||
*
|
||||
* @throws TimeoutException, ChannelException, ExecutionException If motor ok flag does not switch to ok within the specified timeout
|
||||
* @throws CAException If motor ok flag does not switch to ok within the specified timeout
|
||||
*/
|
||||
public void waitUntilMotorNotOk(long timeout) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public void waitUntilMotorNotOk(long timeout) throws InterruptedException {
|
||||
try{
|
||||
motorOk.waitForValue(false, timeout);
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void waitUntilEncoderOk(long timeout) throws TimeoutException, ChannelException, ExecutionException, InterruptedException {
|
||||
public void waitUntilEncoderOk(long timeout) throws InterruptedException {
|
||||
try{
|
||||
if(!useEncoder.getValue()){
|
||||
return;
|
||||
}
|
||||
encoderOk.waitForValue(true, timeout);
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,10 @@
|
||||
|
||||
package ch.psi.fda.core.manipulator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -30,25 +32,16 @@ import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import ch.psi.fda.core.Manipulation;
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
||||
import ch.psi.fda.core.messages.Metadata;
|
||||
import ch.psi.fda.core.scripting.JythonParameterMapping;
|
||||
import ch.psi.fda.core.scripting.JythonParameterMappingChannel;
|
||||
import ch.psi.fda.core.scripting.JythonParameterMappingGlobalVariable;
|
||||
import ch.psi.fda.core.scripting.JythonParameterMappingID;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* Manipulation
|
||||
* @author ebner
|
||||
*/
|
||||
public class JythonManipulation implements Manipulation{
|
||||
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(JythonManipulation.class.getName());
|
||||
|
||||
/**
|
||||
@@ -92,20 +85,24 @@ public class JythonManipulation implements Manipulation{
|
||||
* Component index of the script parameter. The sequence of the indexes in this array correspond to the script
|
||||
* parameter position, i.e. the first index corresponds to the first parameter.
|
||||
*/
|
||||
private Integer[] parameterIndex;
|
||||
// private Integer[] parameterIndex;
|
||||
private List<String> parameterIds = new ArrayList<>();
|
||||
/**
|
||||
* Parameter array of the entry function
|
||||
*/
|
||||
private String[] parameter;
|
||||
private ChannelService cservice;
|
||||
|
||||
/**
|
||||
* Jython entry call
|
||||
*/
|
||||
private String jythonCall;
|
||||
|
||||
public JythonManipulation(ChannelService s, String id, String script, List<JythonParameterMapping> mapping){
|
||||
this(s, id, script, mapping, false);
|
||||
|
||||
private Map<String,Object> gvariables = new HashMap<String,Object>();
|
||||
|
||||
|
||||
public JythonManipulation(String id, String script, List<JythonParameterMapping> mapping){
|
||||
this(id, script, mapping, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,12 +111,11 @@ public class JythonManipulation implements Manipulation{
|
||||
* @param script
|
||||
* @param mapping
|
||||
*/
|
||||
public JythonManipulation(ChannelService s, String id, String script, List<JythonParameterMapping> mapping, boolean returnArray){
|
||||
public JythonManipulation(String id, String script, List<JythonParameterMapping> mapping, boolean returnArray){
|
||||
this.id = id;
|
||||
this.script = script;
|
||||
this.mapping = mapping;
|
||||
this.returnArray = returnArray;
|
||||
this.cservice = s;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,7 +140,7 @@ public class JythonManipulation implements Manipulation{
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize(DataMessageMetadata metadata){
|
||||
public void initialize(List<Metadata> metadata){
|
||||
|
||||
// Workaround for Jython memory leak
|
||||
// http://blog.hillbrecht.de/2009/07/11/jython-memory-leakout-of-memory-problem/
|
||||
@@ -178,7 +174,8 @@ public class JythonManipulation implements Manipulation{
|
||||
|
||||
// Determine component index of the needed parameters
|
||||
// If the component index of the parameter cannot be determined an IllegalArgumentException is thrown
|
||||
parameterIndex = new Integer[parameter.length];
|
||||
// parameterIndex = new Integer[parameter.length];
|
||||
parameterIds = new ArrayList<>();
|
||||
for(int i=0;i<parameter.length; i++){
|
||||
String p = parameter[i];
|
||||
p = p.trim();
|
||||
@@ -189,26 +186,19 @@ public class JythonManipulation implements Manipulation{
|
||||
if(jpm instanceof JythonParameterMappingID){
|
||||
JythonParameterMappingID pm = (JythonParameterMappingID)jpm;
|
||||
// Mapping for parameter found, determine index of the corresponding component
|
||||
parameterIndex[i] = metadata.getIndex(pm.getRefid());
|
||||
// parameterIndex[i] = metadata.getIndex(pm.getRefid());
|
||||
parameterIds.add(pm.getRefid());
|
||||
}
|
||||
else if (jpm instanceof JythonParameterMappingChannel){
|
||||
JythonParameterMappingChannel pm = (JythonParameterMappingChannel)jpm;
|
||||
parameterIndex[i] = null;
|
||||
|
||||
Channel<?> cb;
|
||||
try {
|
||||
cb = cservice.createChannel(new ChannelDescriptor<>(pm.getType(), pm.getChannel(), true));
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
throw new IllegalArgumentException("Unable to establish channel: "+pm.getChannel(), e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to establish channel: "+pm.getChannel(), e);
|
||||
}
|
||||
|
||||
engine.put(pm.getVariable(), cb);
|
||||
JythonParameterMappingChannel<?> pm = (JythonParameterMappingChannel<?>) jpm;
|
||||
// parameterIndex[i] = null;
|
||||
parameterIds.add(null);
|
||||
engine.put(pm.getVariable(), pm.getChannel());
|
||||
}
|
||||
else if (jpm instanceof JythonParameterMappingGlobalVariable){
|
||||
JythonParameterMappingGlobalVariable pm = (JythonParameterMappingGlobalVariable)jpm;
|
||||
parameterIndex[i] = null;
|
||||
parameterIds.add(null);
|
||||
// parameterIndex[i] = null;
|
||||
|
||||
engine.put(pm.getVariable(), pm.getGlobalVariable());
|
||||
}
|
||||
@@ -235,16 +225,23 @@ public class JythonManipulation implements Manipulation{
|
||||
buffer.setCharAt(buffer.length()-1, ')');
|
||||
|
||||
jythonCall = buffer.toString();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(DataMessage message){
|
||||
|
||||
// Set global variables - WORKAROUND gvariables
|
||||
// This block is not in initialization as we want to assure that all invocations
|
||||
// of this manipulation will get the same value (i.e. to prevent inconsistent behaviour
|
||||
// if variable was changed during an execution of the manipulation)
|
||||
for(String k: gvariables.keySet()){
|
||||
engine.put(k, gvariables.get(k));
|
||||
}
|
||||
|
||||
// Manipulate data
|
||||
for(int i=0;i<parameterIndex.length;i++){
|
||||
if(parameterIndex[i] != null){
|
||||
engine.put(parameter[i], message.getData().get(parameterIndex[i]));
|
||||
for(int i=0;i<parameterIds.size();i++){
|
||||
if(parameterIds.get(i) != null){
|
||||
engine.put(parameter[i], message.getData(parameterIds.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +261,8 @@ public class JythonManipulation implements Manipulation{
|
||||
return(((Integer)r).doubleValue());
|
||||
}
|
||||
else{
|
||||
return Double.NaN;
|
||||
// return Double.NaN;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
} catch (ScriptException e) {
|
||||
@@ -273,4 +271,13 @@ public class JythonManipulation implements Manipulation{
|
||||
return Double.NaN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround to put variables into the jython engine.
|
||||
* @param name
|
||||
* @param value
|
||||
*/
|
||||
public void setVariable(String name, Object value){
|
||||
gvariables.put(name, value);
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.manipulator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import ch.psi.fda.core.messages.ComponentMetadata;
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import ch.psi.fda.core.messages.EndOfStreamMessage;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class Manipulator implements Runnable{
|
||||
|
||||
/**
|
||||
* Outgoing data queue
|
||||
*/
|
||||
private final DataQueue outQueue;
|
||||
|
||||
/**
|
||||
* Incomming data queue
|
||||
*/
|
||||
private final DataQueue queue;
|
||||
|
||||
/**
|
||||
* List of manipulations
|
||||
*/
|
||||
private final List<Manipulation> manipulations;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param queue
|
||||
* @param manipulations
|
||||
*/
|
||||
// TODO need to support multiple (a list of) manipulation(s)
|
||||
public Manipulator(DataQueue queue, List<Manipulation> manipulations){
|
||||
|
||||
this.manipulations = manipulations;
|
||||
|
||||
// Create outgoing data metadata
|
||||
DataMessageMetadata dmetadata = queue.getDataMessageMetadata().clone();
|
||||
|
||||
// Initialize manipulations and create outgoing metadata
|
||||
for(Manipulation manipulation: this.manipulations){
|
||||
// Initialize manipulation
|
||||
// manipulation.initialize(queue.getDataMessageMetadata());
|
||||
manipulation.initialize(dmetadata);
|
||||
|
||||
// Add manipulation id to metadata
|
||||
dmetadata.getComponents().add(new ComponentMetadata(manipulation.getId(),0)); // Calculated component always belongs to lowes dimension
|
||||
}
|
||||
|
||||
this.queue = queue;
|
||||
this.outQueue = new DataQueue(new LinkedBlockingQueue<Message>(1000) , dmetadata ); // Create bounded queue to prevent running out of memory ...
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the outQueue
|
||||
*/
|
||||
public DataQueue getOutQueue() {
|
||||
return outQueue;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try{
|
||||
|
||||
// Dispatch Messages
|
||||
Message message = queue.getQueue().take();
|
||||
while(!(message instanceof EndOfStreamMessage)){
|
||||
if(message instanceof DataMessage){
|
||||
DataMessage dm = (DataMessage) message;
|
||||
|
||||
for(Manipulation manipulation: manipulations){
|
||||
dm.getData().add(manipulation.execute(dm));
|
||||
}
|
||||
}
|
||||
|
||||
// Put message to outgoing queue ...
|
||||
outQueue.getQueue().put(message);
|
||||
|
||||
// Read next message
|
||||
message = queue.getQueue().take();
|
||||
}
|
||||
|
||||
// Write end of stream message
|
||||
outQueue.getQueue().put(message);
|
||||
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Stop loop and exit logic instead of throwing an Exception
|
||||
throw new RuntimeException("Data manipulator was interrupted while writing data to file",e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
package ch.psi.fda.core.messages;
|
||||
|
||||
|
||||
/**
|
||||
* A control message that is not holding any data but
|
||||
* control information (like end of loop, etc.)
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public abstract class ControlMessage extends Message {
|
||||
public abstract class ControlMessage extends Message{
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
|
||||
@@ -24,35 +24,57 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* Message holding data
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class DataMessage extends Message {
|
||||
public class DataMessage extends Message{
|
||||
|
||||
/**
|
||||
* Data payload of the message
|
||||
*/
|
||||
private List<Object> data;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Constructor - Create message object with data payload
|
||||
*/
|
||||
public DataMessage(){
|
||||
private final List<Object> data;
|
||||
private List<Metadata> metadata;
|
||||
|
||||
// public DataMessage(){
|
||||
// this.data = new ArrayList<Object>();
|
||||
// this.metadata = new ArrayList<>();
|
||||
// }
|
||||
//
|
||||
public DataMessage(List<Metadata> metadata){
|
||||
this.data = new ArrayList<Object>();
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data object of the message
|
||||
* @return Data object of the message
|
||||
*/
|
||||
public List<Object> getData(){
|
||||
return(data);
|
||||
}
|
||||
public List<Metadata> getMetadata(){
|
||||
return metadata;
|
||||
}
|
||||
public void setMetadata(List<Metadata> metadata){
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getData(String id){
|
||||
int i=0;
|
||||
for(Metadata m: metadata){
|
||||
if(m.getId().equals(id)){
|
||||
return (T) data.get(i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
throw new IllegalArgumentException("No data found for id: "+id);
|
||||
}
|
||||
|
||||
public Metadata getMetadata(String id){
|
||||
for(Metadata m: metadata){
|
||||
if(m.getId().equals(id)){
|
||||
return m;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("No data found for id: "+id);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer b = new StringBuffer();
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.messages;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Structure to hold the metadata of a component of a message.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class DataMessageMetadata {
|
||||
|
||||
/**
|
||||
* List of the metadata of the message components
|
||||
*/
|
||||
private List<ComponentMetadata> components;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public DataMessageMetadata(){
|
||||
components = new ArrayList<ComponentMetadata>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of component metadata of a message described by this object.
|
||||
*/
|
||||
public List<ComponentMetadata> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the component with the specified Id
|
||||
* @param componentId Id of the component to look for
|
||||
* @return Index of the component
|
||||
* @throws IllegalArgumentException There is no component with the specified Id
|
||||
*/
|
||||
public int getIndex(String componentId) throws IllegalArgumentException {
|
||||
for(int i=0;i<components.size();i++){
|
||||
ComponentMetadata c =components.get(i);
|
||||
if(c.getId().equals(componentId)){
|
||||
return(i);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("There is no message component with Id "+ componentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone data structure
|
||||
* @return Cloned data structure
|
||||
*/
|
||||
public DataMessageMetadata clone(){
|
||||
DataMessageMetadata metadata = new DataMessageMetadata();
|
||||
|
||||
for(int i=0;i<components.size();i++){
|
||||
ComponentMetadata c =components.get(i);
|
||||
metadata.getComponents().add(new ComponentMetadata(c.getId(), c.getDimension()));
|
||||
}
|
||||
|
||||
return(metadata);
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.messages;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
|
||||
/**
|
||||
* Container holding for holding a queue and the metadata of the
|
||||
* data messages of that queue.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class DataQueue {
|
||||
|
||||
/**
|
||||
* Queue serving the messages
|
||||
*/
|
||||
private final BlockingQueue<Message> queue;
|
||||
/**
|
||||
* Metadata of the data messages of the queue
|
||||
*/
|
||||
private final DataMessageMetadata dataMessageMetadata;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param queue Data queue
|
||||
* @param dataMessageMetadata Metadata of the data messages of the queue
|
||||
*/
|
||||
public DataQueue(BlockingQueue<Message> queue, DataMessageMetadata dataMessageMetadata){
|
||||
this.queue = queue;
|
||||
this.dataMessageMetadata = dataMessageMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the queue
|
||||
*/
|
||||
public BlockingQueue<Message> getQueue() {
|
||||
return queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the metadata
|
||||
*/
|
||||
public DataMessageMetadata getDataMessageMetadata() {
|
||||
return dataMessageMetadata;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,11 +22,10 @@ package ch.psi.fda.core.messages;
|
||||
/**
|
||||
* Message that is send at the end of the action loop inside an ActionLoop implementation
|
||||
* of just to indicate that a particular stream has finished
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class EndOfStreamMessage extends ControlMessage{
|
||||
public class EndOfStreamMessage extends ControlMessage {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Intersect flag - flag to indicate that stream should be intersected
|
||||
@@ -42,16 +41,10 @@ public class EndOfStreamMessage extends ControlMessage{
|
||||
this.iflag = iflag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the iflag
|
||||
*/
|
||||
public boolean isIflag(){
|
||||
return(iflag);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Message[ c message: end of stream ]";
|
||||
|
||||
@@ -19,10 +19,11 @@
|
||||
|
||||
package ch.psi.fda.core.messages;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Message that can be put to the data queue
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public abstract class Message {
|
||||
public abstract class Message implements Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
|
||||
@@ -19,64 +19,40 @@
|
||||
|
||||
package ch.psi.fda.core.messages;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Metadata of a component of a message. Each component has a global id.
|
||||
* Optionally the component can also belong to a dimension. However, depending on the
|
||||
* view the number of the dimension might vary. Therefore the dimension number
|
||||
* might change during the lifetime of a message (component).
|
||||
*
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ComponentMetadata {
|
||||
/**
|
||||
* Global id of the component
|
||||
*/
|
||||
public class Metadata implements Serializable{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final String id;
|
||||
private int dimension;
|
||||
|
||||
/**
|
||||
* Dimension of the component (optional)
|
||||
*/
|
||||
private final int dimension;
|
||||
|
||||
/**
|
||||
* Default constructor - Create component metadata
|
||||
* @param id Global id of the component
|
||||
*/
|
||||
public ComponentMetadata(String id){
|
||||
public Metadata(String id){
|
||||
this.id = id;
|
||||
this.dimension = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that initializes id and the dimension number
|
||||
* @param id
|
||||
* @param dimension
|
||||
*/
|
||||
public ComponentMetadata(String id, int dimension){
|
||||
public Metadata(String id, int dimension){
|
||||
this.id = id;
|
||||
this.dimension = dimension;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dimension
|
||||
*/
|
||||
public void setDimension(int dimension){
|
||||
this.dimension = dimension;
|
||||
}
|
||||
|
||||
public int getDimension() {
|
||||
return dimension;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Component Metadata[id="+id+" dimension="+dimension+"]";
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,9 @@ package ch.psi.fda.core.messages;
|
||||
|
||||
/**
|
||||
* Message that is send at the end of the action loop inside an ActionLoop implementation
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class StreamDelimiterMessage extends ControlMessage{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* Number of the dimension this delimiter belongs to.
|
||||
*/
|
||||
@@ -38,7 +36,6 @@ public class StreamDelimiterMessage extends ControlMessage{
|
||||
private final boolean iflag;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param number Number of the dimension this delimiter belongs to
|
||||
*/
|
||||
public StreamDelimiterMessage(int number){
|
||||
@@ -46,7 +43,6 @@ public class StreamDelimiterMessage extends ControlMessage{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param number
|
||||
* @param iflag Flag to indicate that data is grouped
|
||||
*/
|
||||
@@ -55,23 +51,14 @@ public class StreamDelimiterMessage extends ControlMessage{
|
||||
this.iflag = iflag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number
|
||||
*/
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the iflag
|
||||
*/
|
||||
public boolean isIflag(){
|
||||
return iflag;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.scripting;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Singleton dictionary class
|
||||
*
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class JythonGlobalVariableDictionary {
|
||||
|
||||
private static JythonGlobalVariableDictionary instance = new JythonGlobalVariableDictionary();
|
||||
private HashMap<String, JythonGlobalVariable> dictionary = new HashMap<String, JythonGlobalVariable>();
|
||||
|
||||
/**
|
||||
* Private constructor
|
||||
*/
|
||||
private JythonGlobalVariableDictionary(){
|
||||
}
|
||||
|
||||
/**
|
||||
* Get singleton instance of the dictionary
|
||||
* @return
|
||||
*/
|
||||
public static JythonGlobalVariableDictionary getInstance(){
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get variable from dictionary. If the variable does not exist it will be created.
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public JythonGlobalVariable getVariable(String name){
|
||||
JythonGlobalVariable variable;
|
||||
if(dictionary.containsKey(name)){
|
||||
variable = dictionary.get(name);
|
||||
}
|
||||
else{
|
||||
variable = new JythonGlobalVariable();
|
||||
variable.setName(name);
|
||||
dictionary.put(name, variable);
|
||||
}
|
||||
|
||||
return variable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear variable dictionary
|
||||
*/
|
||||
public void clear(){
|
||||
dictionary.clear();
|
||||
}
|
||||
}
|
||||
@@ -19,57 +19,24 @@
|
||||
|
||||
package ch.psi.fda.core.scripting;
|
||||
|
||||
import ch.psi.jcae.Channel;
|
||||
|
||||
|
||||
/**
|
||||
* Mapping of a script parameter to a channel bean.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class JythonParameterMappingChannel extends JythonParameterMapping {
|
||||
public class JythonParameterMappingChannel<T> extends JythonParameterMapping {
|
||||
|
||||
/**
|
||||
* Id of the component to map to this variable
|
||||
*/
|
||||
private String channel;
|
||||
private Class<?> type;
|
||||
private Channel<T> channel;
|
||||
|
||||
/**
|
||||
* Constructor accepting varible/id pair
|
||||
* @param variable
|
||||
* @param channel
|
||||
* @param type
|
||||
*/
|
||||
public JythonParameterMappingChannel(String variable, String channel, Class<?> type){
|
||||
public JythonParameterMappingChannel(String variable, Channel<T> channel){
|
||||
super(variable);
|
||||
this.channel = channel;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the channel
|
||||
*/
|
||||
public String getChannel() {
|
||||
public Channel<T> getChannel() {
|
||||
return channel;
|
||||
}
|
||||
/**
|
||||
* @param channel
|
||||
*/
|
||||
public void setChannel(String channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type the type to set
|
||||
*/
|
||||
public void setType(Class<?> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.sensors;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.EngineConfiguration;
|
||||
import ch.psi.fda.core.Sensor;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* Scalar sensor that reads a double form a Channel Access channel
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ChannelAccessDoubleArraySensor implements Sensor {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessDoubleArraySensor.class.getName());
|
||||
|
||||
/**
|
||||
* Channel Access channel of this sensor
|
||||
*/
|
||||
private final Channel<double[]> channel;
|
||||
|
||||
/**
|
||||
* Number of elements to read from the waveform
|
||||
*/
|
||||
private final int numberOfElements;
|
||||
|
||||
/**
|
||||
* Global id of the sensor
|
||||
*/
|
||||
private final String id;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param id Global id of the sensor
|
||||
* @param channelName Name of the Channel Access channel of this sensor
|
||||
* @param numberOfElements Number of elements to read out of the waveform
|
||||
*/
|
||||
public ChannelAccessDoubleArraySensor(ChannelService s, String id, String channelName, int numberOfElements){
|
||||
try {
|
||||
this.channel = s.createChannel(new ChannelDescriptor<>(double[].class, channelName, false, numberOfElements));
|
||||
this.numberOfElements = numberOfElements;
|
||||
this.id = id;
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new IllegalArgumentException("Unable to initialize sensor channel [name:"+channelName+"]",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize sensor channel [name:"+channelName+"]",e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#readout()
|
||||
*/
|
||||
@Override
|
||||
public Object read() throws InterruptedException {
|
||||
logger.finest("Read sensor "+channel.getName());
|
||||
|
||||
double[] v;
|
||||
try {
|
||||
// v = channel.getValue(numberOfElements);
|
||||
v = channel.getValue();
|
||||
} catch (IllegalStateException e) {
|
||||
// Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
|
||||
// return NaN (Not a Number)
|
||||
if(EngineConfiguration.getInstance().isFailOnSensorError()){
|
||||
throw e;
|
||||
}
|
||||
v = new double[numberOfElements];
|
||||
for(int i =0;i<v.length;i++){
|
||||
v[i] = Double.NaN;
|
||||
}
|
||||
} catch (ChannelException | TimeoutException | ExecutionException e) {
|
||||
// Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
|
||||
// return NaN (Not a Number)
|
||||
if(EngineConfiguration.getInstance().isFailOnSensorError()){
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new RuntimeException("Unable to get value from channel [name:"+channel.getName()+"]",e);
|
||||
}
|
||||
|
||||
v = new double[numberOfElements];
|
||||
for(int i =0;i<v.length;i++){
|
||||
v[i] = Double.NaN;
|
||||
}
|
||||
|
||||
// } catch (InterruptedException e) {
|
||||
// // Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
|
||||
// // return NaN (Not a Number)
|
||||
// if(EngineConfiguration.getInstance().isFailOnSensorError()){
|
||||
// throw new RuntimeException("Unable to get value from channel [name:"+channel.getName()+"]",e);
|
||||
// }
|
||||
//
|
||||
// v = new double[numberOfElements];
|
||||
// for(int i =0;i<v.length;i++){
|
||||
// v[i] = Double.NaN;
|
||||
// }
|
||||
}
|
||||
return(v);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#getId()
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy channel
|
||||
try {
|
||||
logger.finest("Destroy sensor channel: "+channel.getName());
|
||||
channel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.sensors;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.EngineConfiguration;
|
||||
import ch.psi.fda.core.Sensor;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* Scalar sensor that reads a double form a Channel Access channel
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ChannelAccessDoubleSensor implements Sensor {
|
||||
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessDoubleSensor.class.getName());
|
||||
|
||||
/**
|
||||
* Channel Access channel of this sensor
|
||||
*/
|
||||
private Channel<Double> channel;
|
||||
|
||||
/**
|
||||
* Global id of the sensor
|
||||
*/
|
||||
private final String id;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param id Global id of the sensor
|
||||
* @param channelName Name of the Channel Access channel of this sensor
|
||||
*/
|
||||
public ChannelAccessDoubleSensor(ChannelService s, String id, String channelName){
|
||||
try {
|
||||
channel = s.createChannel(new ChannelDescriptor<>(Double.class, channelName, false));
|
||||
this.id = id;
|
||||
} catch (ChannelException | TimeoutException e) {
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new IllegalArgumentException("Unable to initialize sensor channel [name:"+channelName+"]",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize sensor channel [name:"+channelName+"]",e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#readout()
|
||||
*/
|
||||
@Override
|
||||
public Object read() throws InterruptedException {
|
||||
logger.finest("Read sensor "+channel.getName());
|
||||
|
||||
Double v;
|
||||
try {
|
||||
v = channel.getValue();
|
||||
} catch (IllegalStateException e) {
|
||||
// Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
|
||||
// return NaN (Not a Number)
|
||||
if(EngineConfiguration.getInstance().isFailOnSensorError()){
|
||||
throw e;
|
||||
}
|
||||
v = Double.NaN;
|
||||
} catch (ChannelException | TimeoutException | ExecutionException e) {
|
||||
// Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
|
||||
// return NaN (Not a Number)
|
||||
if(EngineConfiguration.getInstance().isFailOnSensorError()){
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new RuntimeException("Unable to get value from channel [name:"+channel.getName()+"]",e);
|
||||
}
|
||||
v = Double.NaN;
|
||||
// } catch (InterruptedException e) {
|
||||
// if(EngineConfiguration.getInstance().isFailOnSensorError()){
|
||||
// throw new RuntimeException("Unable to get value from channel [name:"+channel.getName()+"]",e);
|
||||
// }
|
||||
// v = Double.NaN;
|
||||
}
|
||||
return(v);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#getId()
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy channel
|
||||
try {
|
||||
logger.finest("Destroy sensor channel: "+channel.getName());
|
||||
channel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get channel object of sensor
|
||||
* @return
|
||||
*/
|
||||
public Channel<Double> getChannel(){
|
||||
return channel;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.sensors;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.Sensor;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
|
||||
/**
|
||||
* Channel Access sensor capable of reading a channel access channel
|
||||
*/
|
||||
public class ChannelAccessSensor<T> implements Sensor {
|
||||
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessSensor.class.getName());
|
||||
|
||||
private Channel<T> channel;
|
||||
private final String id;
|
||||
private boolean failOnSensorError = true;
|
||||
|
||||
public ChannelAccessSensor(String id, Channel<T> channel){
|
||||
this.id = id;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public ChannelAccessSensor(String id, Channel<T> channel, boolean failOnSensorError){
|
||||
this.id = id;
|
||||
this.channel = channel;
|
||||
this.failOnSensorError = failOnSensorError;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read() throws InterruptedException {
|
||||
logger.finest("Read sensor "+channel.getName());
|
||||
|
||||
T v;
|
||||
try {
|
||||
v = channel.getValue();
|
||||
} catch (TimeoutException | ChannelException | ExecutionException e) {
|
||||
if(failOnSensorError){
|
||||
throw new RuntimeException("Unable to get value from channel [name:"+channel.getName()+"]",e);
|
||||
}
|
||||
v = null;
|
||||
}
|
||||
return(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.sensors;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.EngineConfiguration;
|
||||
import ch.psi.fda.core.Sensor;
|
||||
import ch.psi.jcae.Channel;
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.jcae.ChannelException;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* Scalar sensor that reads a double form a Channel Access channel
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ChannelAccessStringSensor implements Sensor {
|
||||
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ChannelAccessStringSensor.class.getName());
|
||||
|
||||
/**
|
||||
* Channel Access channel of this sensor
|
||||
*/
|
||||
private Channel<String> channel;
|
||||
|
||||
/**
|
||||
* Global id of the sensor
|
||||
*/
|
||||
private final String id;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param id Global id of the sensor
|
||||
* @param channelName Name of the Channel Access channel of this sensor
|
||||
*/
|
||||
public ChannelAccessStringSensor(ChannelService s, String id, String channelName){
|
||||
try {
|
||||
channel = s.createChannel(new ChannelDescriptor<String>(String.class, channelName, false));
|
||||
this.id = id;
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Unable to initialize sensor channel [name:"+channelName+"]",e);
|
||||
} catch (ChannelException e) {
|
||||
throw new IllegalArgumentException("Unable to initialize sensor channel [name:"+channelName+"]",e);
|
||||
} catch (TimeoutException e) {
|
||||
throw new IllegalArgumentException("Unable to initialize sensor channel [name:"+channelName+"]",e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#readout()
|
||||
*/
|
||||
@Override
|
||||
public Object read() throws InterruptedException {
|
||||
logger.finest("Read sensor "+channel.getName());
|
||||
|
||||
String v;
|
||||
try {
|
||||
v = channel.getValue();
|
||||
} catch (IllegalStateException e) {
|
||||
// Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
|
||||
// return NaN (Not a Number)
|
||||
if(EngineConfiguration.getInstance().isFailOnSensorError()){
|
||||
throw e;
|
||||
}
|
||||
v = null;
|
||||
} catch (TimeoutException | ExecutionException |ChannelException e) {
|
||||
// Only fail during data acquisition if fail on error sensor flag is on true. Otherwise
|
||||
// return NaN (Not a Number)
|
||||
if(EngineConfiguration.getInstance().isFailOnSensorError()){
|
||||
// Convert Exception into unchecked RuntimeException
|
||||
throw new RuntimeException("Unable to get value from channel [name:"+channel.getName()+"]",e);
|
||||
}
|
||||
v = null;
|
||||
// } catch (InterruptedException e) {
|
||||
// if(EngineConfiguration.getInstance().isFailOnSensorError()){
|
||||
// throw new RuntimeException("Unable to get value from channel [name:"+channel.getName()+"]",e);
|
||||
// }
|
||||
// v = null;
|
||||
}
|
||||
|
||||
return(v);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#getId()
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy channel
|
||||
try {
|
||||
logger.finest("Destroy sensor channel: "+channel.getName());
|
||||
channel.destroy();
|
||||
} catch (ChannelException e) {
|
||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,90 +1,39 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.sensors;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.Action;
|
||||
import ch.psi.fda.core.Sensor;
|
||||
|
||||
/**
|
||||
* Complex sensor that complements an other sensor with pre and post actions.
|
||||
* Before reading out the complemented sensor the pre actions are executed. After the
|
||||
* readout the post actions.
|
||||
*
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ComplexSensor implements Sensor {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(ComplexSensor.class.getName());
|
||||
|
||||
/**
|
||||
* Id of the sensor
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Sensor to complement
|
||||
*/
|
||||
private final Sensor sensor;
|
||||
|
||||
/**
|
||||
* Actions that are executed directly before the first step of this actor
|
||||
*/
|
||||
private final List<Action> preActions;
|
||||
|
||||
/**
|
||||
* Actions that are executed directly after the last step of this actor
|
||||
*/
|
||||
private final List<Action> postActions;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ComplexSensor(String id, Sensor sensor){
|
||||
this.id = id;
|
||||
|
||||
this.sensor = sensor;
|
||||
this.preActions = new ArrayList<Action>();
|
||||
this.postActions = new ArrayList<Action>();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#read()
|
||||
*/
|
||||
@Override
|
||||
public Object read() throws InterruptedException {
|
||||
// Execute pre actions
|
||||
logger.finest("Execute pre actions");
|
||||
for(Action action: preActions){
|
||||
action.execute();
|
||||
}
|
||||
|
||||
// Readout sensor
|
||||
Object value = sensor.read();
|
||||
|
||||
// Execute post actions
|
||||
logger.finest("Execute post actions");
|
||||
for(Action action: postActions){
|
||||
action.execute();
|
||||
@@ -93,44 +42,15 @@ public class ComplexSensor implements Sensor {
|
||||
return value;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#getId()
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Destroy preActions
|
||||
for(Action a: preActions){
|
||||
a.destroy();
|
||||
}
|
||||
|
||||
sensor.destroy();
|
||||
|
||||
// Destroy postActions
|
||||
for(Action a: postActions){
|
||||
a.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the preActions
|
||||
*/
|
||||
public List<Action> getPreActions() {
|
||||
return preActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the postActions
|
||||
*/
|
||||
public List<Action> getPostActions() {
|
||||
return postActions;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2010 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful,
|
||||
* but without any warranty; without even the implied warranty of
|
||||
* merchantability or fitness for a particular purpose. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package ch.psi.fda.core.sensors;
|
||||
|
||||
import ch.psi.fda.core.Sensor;
|
||||
|
||||
/**
|
||||
* Sensor to read actuator readback. This sensor must only be used within the
|
||||
* OTFLoop. If it is used in other loops, the read value will always be 0.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class OTFReadbackSensor implements Sensor {
|
||||
|
||||
/**
|
||||
* Global id of the sensor
|
||||
*/
|
||||
private final String id;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param id Global id of the sensor
|
||||
*/
|
||||
public OTFReadbackSensor(String id){
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#read()
|
||||
*/
|
||||
@Override
|
||||
public Object read() {
|
||||
// Always return 0 if read() method is called.
|
||||
return 0d;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#getId()
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Nothing to be done
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,48 +22,25 @@ package ch.psi.fda.core.sensors;
|
||||
import ch.psi.fda.core.Sensor;
|
||||
|
||||
/**
|
||||
* Get the current time in milliseconds
|
||||
* @author ebner
|
||||
*
|
||||
* Sensor to read the current time in milliseconds
|
||||
*/
|
||||
public class MillisecondTimestampSensor implements Sensor {
|
||||
public class TimestampSensor implements Sensor {
|
||||
|
||||
/**
|
||||
* Global id of the sensor
|
||||
*/
|
||||
private final String id;
|
||||
private final String id; // Global id of the sensor
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param id Global id of the sensor
|
||||
*/
|
||||
public MillisecondTimestampSensor(String id){
|
||||
public TimestampSensor(String id){
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#read()
|
||||
*/
|
||||
@Override
|
||||
public Object read() {
|
||||
// Return current time in milliseconds
|
||||
return new Double(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#getId()
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.core.Sensor#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Nothing to be done
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,18 +19,6 @@
|
||||
|
||||
package ch.psi.fda.deserializer;
|
||||
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
|
||||
/**
|
||||
* Data deserializer
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public interface DataDeserializer extends Runnable {
|
||||
|
||||
/**
|
||||
* Get data queue of deserializer
|
||||
* @return data queue of deserializer
|
||||
*/
|
||||
public DataQueue getQueue();
|
||||
public interface DataDeserializer {
|
||||
public void read();
|
||||
}
|
||||
|
||||
@@ -9,45 +9,40 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.messages.ComponentMetadata;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import ch.psi.fda.core.messages.EndOfStreamMessage;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
import ch.psi.fda.core.messages.Metadata;
|
||||
import ch.psi.fda.core.messages.StreamDelimiterMessage;
|
||||
|
||||
/**
|
||||
* Deserializer MDA file
|
||||
* TODO Need to be optimized as currently the while file is read into memory when creating this object.
|
||||
*/
|
||||
public class DataDeserializerMDA implements DataDeserializer {
|
||||
|
||||
private static Logger logger = Logger.getLogger(DataDeserializerMDA.class.getName());
|
||||
|
||||
private DataQueue queue;
|
||||
private EventBus bus;
|
||||
private RecursiveReturnContainer c;
|
||||
|
||||
public DataDeserializerMDA(File file){
|
||||
public DataDeserializerMDA(EventBus b, File file){
|
||||
this.bus = b;
|
||||
|
||||
try {
|
||||
RecursiveReturnContainer c = read(new FileInputStream(file));
|
||||
|
||||
this.queue = new DataQueue(new LinkedBlockingQueue<Message>(), c.getMetadata());
|
||||
|
||||
// Add data to queue
|
||||
for(Message m: c.getMessage()){
|
||||
queue.getQueue().put(m);
|
||||
}
|
||||
queue.getQueue().put(new EndOfStreamMessage());
|
||||
try{
|
||||
c = read(new FileInputStream(file));
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public RecursiveReturnContainer read(InputStream in) throws IOException {
|
||||
private RecursiveReturnContainer read(InputStream in) throws IOException {
|
||||
logger.fine("Read MDA input stream");
|
||||
|
||||
XDRInputStream x = new XDRInputStream(in);
|
||||
@@ -218,7 +213,7 @@ public class DataDeserializerMDA implements DataDeserializer {
|
||||
logger.fine("MDA - number of triggers:: "+ numberOfTriggers);
|
||||
|
||||
|
||||
List<ComponentMetadata> componentMetadataList = new ArrayList<ComponentMetadata>();
|
||||
List<Metadata> componentMetadataList = new ArrayList<>();
|
||||
/**
|
||||
* Read positioners metadata
|
||||
*/
|
||||
@@ -234,7 +229,7 @@ public class DataDeserializerMDA implements DataDeserializer {
|
||||
String positionerName = x.readString();
|
||||
logger.fine("MDA - positioner name:: "+positionerName);
|
||||
// MDA starts at dimension number 1 we start at 0
|
||||
componentMetadataList.add(new ComponentMetadata(positionerName,scanRank-1));
|
||||
componentMetadataList.add(new Metadata(positionerName,scanRank-1));
|
||||
}
|
||||
|
||||
length = x.readInt();
|
||||
@@ -288,7 +283,7 @@ public class DataDeserializerMDA implements DataDeserializer {
|
||||
String detectorName = x.readString();
|
||||
logger.fine("MDA - detector name:: "+detectorName);
|
||||
// MDA starts at dimension number 1 we start at 0
|
||||
componentMetadataList.add(new ComponentMetadata(detectorName, scanRank-1));
|
||||
componentMetadataList.add(new Metadata(detectorName, scanRank-1));
|
||||
}
|
||||
|
||||
length = x.readInt();
|
||||
@@ -372,7 +367,7 @@ public class DataDeserializerMDA implements DataDeserializer {
|
||||
|
||||
RecursiveReturnContainer cont = new RecursiveReturnContainer();
|
||||
// Update component metadata
|
||||
cont.getMetadata().getComponents().addAll(componentMetadataList);
|
||||
cont.getMetadata().addAll(componentMetadataList);
|
||||
|
||||
if(scanRank > 1){
|
||||
/**
|
||||
@@ -389,14 +384,14 @@ public class DataDeserializerMDA implements DataDeserializer {
|
||||
|
||||
if(i==0){
|
||||
// For the first scan of each dimension component data is read and stored
|
||||
cont.getMetadata().getComponents().addAll(container.getMetadata().getComponents());
|
||||
cont.getMetadata().addAll(container.getMetadata());
|
||||
}
|
||||
|
||||
logger.fine("Convert data structure [rank="+scanRank+"] ...");
|
||||
for(Message m: container.getMessage()){
|
||||
if(m instanceof DataMessage){
|
||||
// Add own data to message and pass it to container
|
||||
DataMessage mm = new DataMessage();
|
||||
DataMessage mm = new DataMessage(new ArrayList<Metadata>()); // Workaround
|
||||
for(Double[] d: data){
|
||||
mm.getData().add(d[i]);
|
||||
}
|
||||
@@ -424,7 +419,7 @@ public class DataDeserializerMDA implements DataDeserializer {
|
||||
logger.fine("Convert data structure [rank="+scanRank+"]...");
|
||||
|
||||
for(int t = 0; t<npts ; t++){
|
||||
DataMessage m = new DataMessage();
|
||||
DataMessage m = new DataMessage(new ArrayList<Metadata>()); // workaround
|
||||
for(Double[] d: data){
|
||||
m.getData().add(d[t]);
|
||||
}
|
||||
@@ -443,23 +438,19 @@ public class DataDeserializerMDA implements DataDeserializer {
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
public void read() {
|
||||
// Add data to queue
|
||||
for(Message m: c.getMessage()){
|
||||
if(m instanceof DataMessage){
|
||||
DataMessage dm = (DataMessage)m;
|
||||
dm.getMetadata().addAll(c.getMetadata()); // WORKAROUND !!!! ideally the reference to metadata is set while creating the
|
||||
// data message. Then there would be only one list with one reference. In this case we now have multiple lists!
|
||||
}
|
||||
bus.post(m);
|
||||
}
|
||||
bus.post(new EndOfStreamMessage());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.deserializer.DataDeserializer#getQueue()
|
||||
*/
|
||||
@Override
|
||||
public DataQueue getQueue() {
|
||||
return queue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -469,12 +460,12 @@ public class DataDeserializerMDA implements DataDeserializer {
|
||||
*/
|
||||
class RecursiveReturnContainer{
|
||||
private List<Message> message = new ArrayList<Message>();
|
||||
private DataMessageMetadata metadata = new DataMessageMetadata();
|
||||
private List<Metadata> metadata = new ArrayList<>();
|
||||
|
||||
public List<Message> getMessage() {
|
||||
return message;
|
||||
}
|
||||
public DataMessageMetadata getMetadata() {
|
||||
public List<Metadata> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,28 +25,24 @@ import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.core.messages.ComponentMetadata;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ch.psi.fda.core.messages.DataMessage;
|
||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
||||
import ch.psi.fda.core.messages.DataQueue;
|
||||
import ch.psi.fda.core.messages.Metadata;
|
||||
import ch.psi.fda.core.messages.StreamDelimiterMessage;
|
||||
import ch.psi.fda.core.messages.EndOfStreamMessage;
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
|
||||
/**
|
||||
* Deserialize file data and put it into the DataQueue
|
||||
* @author ebner
|
||||
*
|
||||
* Deserializer for text files
|
||||
*/
|
||||
public class DataDeserializerTXT implements DataDeserializer {
|
||||
|
||||
// Get Logger
|
||||
private static Logger logger = Logger.getLogger(DataDeserializerTXT.class.getName());
|
||||
|
||||
private DataQueue queue;
|
||||
|
||||
private EventBus bus;
|
||||
private List<Metadata> metadata;
|
||||
private File file;
|
||||
|
||||
private List<Integer> dindex;
|
||||
@@ -56,12 +52,14 @@ public class DataDeserializerTXT implements DataDeserializer {
|
||||
* Default Constructor
|
||||
* @param file
|
||||
*/
|
||||
public DataDeserializerTXT(File file){
|
||||
public DataDeserializerTXT(EventBus b, File file){
|
||||
this.bus = b;
|
||||
this.file = file;
|
||||
this.dindex = new ArrayList<Integer>();
|
||||
this.iindex = new ArrayList<Integer>();
|
||||
|
||||
DataMessageMetadata metadata;
|
||||
|
||||
this.metadata = new ArrayList<>();
|
||||
try{
|
||||
// Read metadata
|
||||
// Open file
|
||||
@@ -81,11 +79,10 @@ public class DataDeserializerTXT implements DataDeserializer {
|
||||
String[] dimensions = line.split("\t");
|
||||
|
||||
// Create data message metadata
|
||||
metadata = new DataMessageMetadata();
|
||||
Integer d = -1;
|
||||
for(int i=0;i<ids.length;i++){
|
||||
Integer dimension = Integer.parseInt(dimensions[i]);
|
||||
metadata.getComponents().add(new ComponentMetadata(ids[i], dimension));
|
||||
metadata.add(new Metadata(ids[i], dimension));
|
||||
|
||||
// Store the first index of the first component
|
||||
// in each dimension ...
|
||||
@@ -103,23 +100,10 @@ public class DataDeserializerTXT implements DataDeserializer {
|
||||
catch(Exception e){
|
||||
throw new RuntimeException("Unable to read file metadata and initialize data queue",e);
|
||||
}
|
||||
|
||||
this.queue = new DataQueue(new LinkedBlockingQueue<Message>(10000000), metadata);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ch.psi.fda.deserializer.DataDeserializer#getQueue()
|
||||
*/
|
||||
@Override
|
||||
public DataQueue getQueue(){
|
||||
return(queue);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
public void read() {
|
||||
try{
|
||||
|
||||
List<Double> checklist = new ArrayList<Double>(dindex.size());
|
||||
@@ -146,7 +130,7 @@ public class DataDeserializerTXT implements DataDeserializer {
|
||||
|
||||
// Create and populate new data message
|
||||
String[] data = line.split("\t");
|
||||
DataMessage message = new DataMessage();
|
||||
DataMessage message = new DataMessage(metadata);
|
||||
for (String d : data) {
|
||||
// Remove spaces at the end and beginning of the value
|
||||
d = d.trim();
|
||||
@@ -190,19 +174,16 @@ public class DataDeserializerTXT implements DataDeserializer {
|
||||
Integer i = iindex.get(t);
|
||||
if(dindex.get(t)>0){
|
||||
Double d = (Double) message.getData().get(i);
|
||||
// if(checklist.get(i)==null){
|
||||
// checklist.set(i, d);
|
||||
// }
|
||||
if(checklist.get(i)!=null &&!checklist.get(i).equals(d)){
|
||||
// If value changes issue a dimension delimiter message
|
||||
queue.getQueue().put(new StreamDelimiterMessage(dindex.get(t)-1));
|
||||
bus.post(new StreamDelimiterMessage(dindex.get(t)-1));
|
||||
}
|
||||
checklist.set(i, d);
|
||||
}
|
||||
}
|
||||
|
||||
// Put message to queue
|
||||
queue.getQueue().put(message);
|
||||
bus.post(message);
|
||||
|
||||
// TODO Need to detect dimension boundaries
|
||||
|
||||
@@ -210,20 +191,15 @@ public class DataDeserializerTXT implements DataDeserializer {
|
||||
|
||||
// Add delimiter for all the dimensions
|
||||
for(int i=dindex.size()-1;i>=0;i--){
|
||||
queue.getQueue().put(new StreamDelimiterMessage(dindex.get(i)));
|
||||
bus.post(new StreamDelimiterMessage(dindex.get(i)));
|
||||
}
|
||||
// queue.getQueue().put(new DimensionDelimiterMessage(dindex.get(0)-1));
|
||||
// queue.getQueue().put(new DimensionDelimiterMessage(dindex.get(0)));
|
||||
|
||||
|
||||
// Place end of stream message
|
||||
queue.getQueue().put(new EndOfStreamMessage());
|
||||
bus.post(new EndOfStreamMessage());
|
||||
|
||||
// Close file
|
||||
reader.close();
|
||||
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Data deserializer was interrupted while reading the datafile",e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Data deserializer had a problem reading the specified datafile",e);
|
||||
}
|
||||
|
||||
@@ -17,12 +17,16 @@ public class ProgressPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private javax.swing.JButton abortButton;
|
||||
private javax.swing.JProgressBar progressBar;
|
||||
|
||||
/** Creates new form ScanProgressPanel */
|
||||
public ProgressPanel() {
|
||||
initComponents();
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
/**
|
||||
* This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
*/
|
||||
private void initComponents() {
|
||||
@@ -59,8 +63,6 @@ public class ProgressPanel extends javax.swing.JPanel {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void addActionListener(ActionListener l){
|
||||
abortButton.addActionListener(l);
|
||||
}
|
||||
@@ -70,9 +72,4 @@ public class ProgressPanel extends javax.swing.JPanel {
|
||||
progressBar.setValue(100);
|
||||
abortButton.setEnabled(false);
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify
|
||||
private javax.swing.JButton abortButton;
|
||||
private javax.swing.JProgressBar progressBar;
|
||||
// End of variables declaration
|
||||
}
|
||||
|
||||
@@ -13,31 +13,38 @@ public class ScrollableFlowPanel extends JPanel implements Scrollable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void setBounds(int x, int y, int width, int height) {
|
||||
super.setBounds(x, y, getParent().getWidth(), height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(getWidth(), getPreferredHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredScrollableViewportSize() {
|
||||
return super.getPreferredSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
|
||||
int hundredth = (orientation == SwingConstants.VERTICAL ? getParent().getHeight() : getParent().getWidth()) / 100;
|
||||
return (hundredth == 0 ? 1 : hundredth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
|
||||
return orientation == SwingConstants.VERTICAL ? getParent().getHeight() : getParent().getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getScrollableTracksViewportWidth() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getScrollableTracksViewportHeight() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -33,17 +33,17 @@ import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import ch.psi.fda.aq.AcquisitionConfiguration;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ApplicationConfigurator {
|
||||
|
||||
// Get Logger
|
||||
private static final Logger logger = Logger.getLogger(ApplicationConfigurator.class.getName());
|
||||
|
||||
public final static String FDA_HOME_ARGUMENT = "ch.psi.fda.home";
|
||||
public final static String FDA_CONFIG_FILE_ARGUMENT = "ch.psi.fda.config.file";
|
||||
|
||||
private final File home;
|
||||
private final File configdir;
|
||||
@@ -89,9 +89,9 @@ public class ApplicationConfigurator {
|
||||
}
|
||||
|
||||
// Set FDA configuration argument -Dch.psi.fda.config.file=...
|
||||
property = System.getProperty(FDA_CONFIG_FILE_ARGUMENT);
|
||||
property = System.getProperty(AcquisitionConfiguration.FDA_CONFIG_FILE);
|
||||
if(property==null){
|
||||
System.setProperty(FDA_CONFIG_FILE_ARGUMENT, fdaProperties.getAbsolutePath());
|
||||
System.setProperty(AcquisitionConfiguration.FDA_CONFIG_FILE, fdaProperties.getAbsolutePath());
|
||||
}
|
||||
|
||||
// Set jcae.properties file
|
||||
|
||||
@@ -19,11 +19,7 @@
|
||||
|
||||
package ch.psi.fda.model;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
@@ -32,13 +28,7 @@ import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.UnmarshalException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import javax.xml.validation.Schema;
|
||||
import javax.xml.validation.SchemaFactory;
|
||||
@@ -49,83 +39,14 @@ import org.xml.sax.SAXParseException;
|
||||
import ch.psi.fda.model.v1.Configuration;
|
||||
|
||||
/**
|
||||
* Manage the serialization and deserialization of the model
|
||||
* @author ebner
|
||||
*
|
||||
* Manage the serialization and deserialization of the FDA data model
|
||||
*/
|
||||
public class ModelManager {
|
||||
|
||||
/**
|
||||
* Deserialize an instance of a data model of the type Configuration
|
||||
* Before creating the object model variables will be replaced
|
||||
* De-serialize an instance of the FDA data model
|
||||
*
|
||||
* @param file Scan file
|
||||
* @param variables Scan variables
|
||||
* @throws JAXBException Something went wrong while unmarshalling
|
||||
* @throws SAXException Cannot read model schema file
|
||||
* @throws ParserConfigurationException
|
||||
* @throws IOException
|
||||
* @throws TransformerFactoryConfigurationError
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public static Configuration unmarshall(File file, HashMap<String, String> variables) throws JAXBException, SAXException, IOException,
|
||||
ParserConfigurationException, TransformerFactoryConfigurationError, TransformerException {
|
||||
|
||||
// Load template file
|
||||
Transformer xformer = TransformerFactory.newInstance().newTransformer(new StreamSource(file));
|
||||
// Overwrite parameters
|
||||
for(String key: variables.keySet()){
|
||||
xformer.setParameter(key, variables.get(key));
|
||||
}
|
||||
|
||||
|
||||
// Workaround for complex parameters (parameter including xml fragments)
|
||||
// How the workaround works:
|
||||
// Because we want to set complex parameters we first have to apply the xslt transformation to the input
|
||||
// stream and create an other output stream. In the template file the complex parameter must be referenced as follows
|
||||
// <xsl:value-of select="$var.regions" disable-output-escaping="yes" />
|
||||
// If it is not done this way the < and > of the tags will be replaced by < and >
|
||||
// Also if we directly transform to a DOMResult the dom tree would not include the
|
||||
// nodes added by the parameter but just a text object. Therefor we do the workaround via the StreamResult ...
|
||||
ByteArrayOutputStream bstream = new ByteArrayOutputStream();
|
||||
StreamResult sresult = new StreamResult(bstream);
|
||||
|
||||
|
||||
// Perform transformation (using template file also as input source)
|
||||
xformer.transform(new StreamSource(file), sresult );
|
||||
|
||||
|
||||
// Workaround for complex parameters
|
||||
ByteArrayInputStream bistream = new ByteArrayInputStream(bstream.toByteArray());
|
||||
StreamSource bsource = new StreamSource(bistream);
|
||||
|
||||
|
||||
JAXBContext context = JAXBContext.newInstance(Configuration.class);
|
||||
Unmarshaller u = context.createUnmarshaller();
|
||||
|
||||
// Validation
|
||||
SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
||||
Source s = new StreamSource(Configuration.class.getResourceAsStream("/model-v1.xsd"));
|
||||
Schema schema = sf.newSchema(new Source[]{s}); // Use schema reference provided in XML
|
||||
u.setSchema(schema);
|
||||
|
||||
try{
|
||||
Configuration model = (Configuration) u.unmarshal(bsource, Configuration.class).getValue();
|
||||
return (model);
|
||||
}
|
||||
catch(UnmarshalException e){
|
||||
// Check
|
||||
if(e.getLinkedException() instanceof SAXParseException){
|
||||
throw new RuntimeException("Configuration file does not comply to required model specification\nCause: "+e.getLinkedException().getMessage(), e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserialize an instance of a data model of the type Configuration
|
||||
* @param file
|
||||
* @param file File to deserialize
|
||||
* @throws JAXBException Something went wrong while unmarshalling
|
||||
* @throws SAXException Cannot read model schema file
|
||||
*/
|
||||
@@ -154,7 +75,8 @@ public class ModelManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize an instance of a data model of the type Configuration
|
||||
* Serialize an instance of the FDA data model
|
||||
*
|
||||
* @param model Model datastructure
|
||||
* @param file File to write the model data into
|
||||
* @throws JAXBException Something went wrong while marshalling model
|
||||
|
||||
170
ch.psi.fda/src/main/java/ch/psi/fda/rest/AcquisitionEngine.java
Normal file
170
ch.psi.fda/src/main/java/ch/psi/fda/rest/AcquisitionEngine.java
Normal file
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.rest;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ch.psi.fda.aq.Acquisition;
|
||||
import ch.psi.fda.aq.AcquisitionConfiguration;
|
||||
import ch.psi.fda.model.v1.Configuration;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
|
||||
/**
|
||||
* Main engine for data acquisition.
|
||||
*/
|
||||
public class AcquisitionEngine {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AcquisitionEngine.class.getName());
|
||||
|
||||
private AcquisitionConfiguration config;
|
||||
private ChannelService cservice;
|
||||
private final ZMQDataService dservice;
|
||||
|
||||
/**
|
||||
* Variable holding the current acquisition
|
||||
*/
|
||||
private volatile Acquisition acquisition;
|
||||
private volatile ExecutionRequest currentRequest;
|
||||
|
||||
private ExecutorService eservice;
|
||||
|
||||
|
||||
private BlockingQueue<ExecutionRequest> requests = new LinkedBlockingQueue<>();
|
||||
|
||||
@Inject
|
||||
public AcquisitionEngine(ChannelService cservice, ZMQDataService dservice, AcquisitionConfiguration config) {
|
||||
this.dservice = dservice;
|
||||
this.cservice = cservice;
|
||||
this.config = config;
|
||||
|
||||
// Start main execution loop
|
||||
eservice = Executors.newSingleThreadExecutor();
|
||||
eservice.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
try {
|
||||
ExecutionRequest r = requests.take();
|
||||
|
||||
logger.info("Execute - " + r.getTrackingId());
|
||||
|
||||
EventBus ebus = new EventBus();
|
||||
// Provide tracking id to data service and register the service to the event bus
|
||||
AcquisitionEngine.this.dservice.setTrackingId(r.getTrackingId());
|
||||
ebus.register(AcquisitionEngine.this.dservice);
|
||||
|
||||
synchronized (AcquisitionEngine.this) { // synchronize access to acquisition object via the AcquisitionEngine object
|
||||
acquisition = new Acquisition(AcquisitionEngine.this.cservice, AcquisitionEngine.this.config);
|
||||
currentRequest = r;
|
||||
}
|
||||
acquisition.initalize(ebus, r.getConfiguration());
|
||||
acquisition.execute();
|
||||
logger.info("" + r.getTrackingId() + " done");
|
||||
|
||||
// Cleanup
|
||||
ebus.unregister(AcquisitionEngine.this.dservice);
|
||||
} finally {
|
||||
acquisition.destroy();
|
||||
|
||||
synchronized (AcquisitionEngine.this) {
|
||||
acquisition = null;
|
||||
currentRequest = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit a scan to be executed. This will generate an execution request which is
|
||||
* enqueued in the execution queue.
|
||||
*
|
||||
* @param configuration
|
||||
* @return
|
||||
*/
|
||||
public String submit(Configuration configuration){
|
||||
ExecutionRequest r = new ExecutionRequest(UUID.randomUUID().toString(), configuration);
|
||||
try{
|
||||
requests.put(r);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
return r.getTrackingId();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Terminate the currently executed request
|
||||
*/
|
||||
public void terminate(){
|
||||
synchronized(this){
|
||||
if(acquisition==null){
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Stop current acquisition");
|
||||
acquisition.abort();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate the request which is identified by its tracking id. If the request
|
||||
* is still in the execution queue it gets removed there.
|
||||
* @param trackingId
|
||||
*/
|
||||
public void terminate(String trackingId){
|
||||
|
||||
// If request is currently executed terminate it
|
||||
if(currentRequest.getTrackingId().equals(trackingId)){
|
||||
terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove request from request queue
|
||||
ExecutionRequest rremove = null;
|
||||
for(ExecutionRequest r:requests){
|
||||
if(r.getTrackingId().equals(trackingId)){
|
||||
rremove = r; // We have to split the filtering and termination as we otherwise get a concurrent access exception.
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(rremove!=null){
|
||||
boolean b = requests.remove(rremove);
|
||||
// There is a chance that between the upper loop and here the request
|
||||
// already got dequeued. This check ensures that the requests got removed
|
||||
// if not it got dequeued and therefore we have to terminate the current
|
||||
// execution.
|
||||
if(!b){
|
||||
terminate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,23 +16,28 @@
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.aq.ng.rdescriptors;
|
||||
package ch.psi.fda.rest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ch.psi.jcae.ChannelDescriptor;
|
||||
import ch.psi.fda.model.v1.Configuration;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ProbeDescriptor {
|
||||
public class ExecutionRequest {
|
||||
|
||||
private List<ChannelDescriptor<?>> sensors = new ArrayList<>();
|
||||
private final String trackingId;
|
||||
private final Configuration configuration;
|
||||
|
||||
public List<ChannelDescriptor<?>> getSensors(){
|
||||
return sensors;
|
||||
public ExecutionRequest(String trackingId, Configuration configuration){
|
||||
this.trackingId = trackingId;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
public String getTrackingId() {
|
||||
return trackingId;
|
||||
}
|
||||
public Configuration getConfiguration() {
|
||||
return configuration;
|
||||
}
|
||||
}
|
||||
22
ch.psi.fda/src/main/java/ch/psi/fda/rest/ResourceBinder.java
Normal file
22
ch.psi.fda/src/main/java/ch/psi/fda/rest/ResourceBinder.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package ch.psi.fda.rest;
|
||||
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.glassfish.hk2.utilities.binding.AbstractBinder;
|
||||
|
||||
import ch.psi.fda.aq.AcquisitionConfiguration;
|
||||
import ch.psi.jcae.ChannelService;
|
||||
import ch.psi.jcae.impl.DefaultChannelService;
|
||||
|
||||
public class ResourceBinder extends AbstractBinder {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(DefaultChannelService.class).to(ChannelService.class).in(Singleton.class);
|
||||
bind(AcquisitionConfiguration.class).to(AcquisitionConfiguration.class).in(Singleton.class);
|
||||
bind(AcquisitionEngine.class).to(AcquisitionEngine.class).in(Singleton.class);
|
||||
bind(ZMQDataService.class).to(ZMQDataService.class).in(Singleton.class);
|
||||
}
|
||||
|
||||
}
|
||||
98
ch.psi.fda/src/main/java/ch/psi/fda/rest/RestServer.java
Normal file
98
ch.psi.fda/src/main/java/ch/psi/fda/rest/RestServer.java
Normal file
@@ -0,0 +1,98 @@
|
||||
package ch.psi.fda.rest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.GnuParser;
|
||||
import org.apache.commons.cli.HelpFormatter;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
|
||||
import org.glassfish.jersey.jackson.JacksonFeature;
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.glassfish.grizzly.http.server.HttpServer;
|
||||
|
||||
import sun.misc.Signal;
|
||||
import sun.misc.SignalHandler;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class RestServer {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(RestServer.class.getName());
|
||||
|
||||
public static void main(String[] args) throws IOException, ParseException {
|
||||
|
||||
// Option handling
|
||||
int port = 8080;
|
||||
|
||||
Options options = new Options();
|
||||
options.addOption("h", false, "Help");
|
||||
options.addOption("p", true, "Server port (default: "+port+")");
|
||||
|
||||
GnuParser parser = new GnuParser();
|
||||
CommandLine line = parser.parse(options, args);
|
||||
|
||||
if (line.hasOption("p")) {
|
||||
port = Integer.parseInt(line.getOptionValue("p"));
|
||||
}
|
||||
if (line.hasOption("h")) {
|
||||
HelpFormatter f = new HelpFormatter();
|
||||
f.printHelp("broker", options);
|
||||
return;
|
||||
}
|
||||
|
||||
URI baseUri = UriBuilder.fromUri("http://" + InetAddress.getLocalHost().getHostName() + "/").port(port).build();
|
||||
|
||||
|
||||
// Broker broker = createBroker(config);
|
||||
|
||||
|
||||
ResourceBinder binder = new ResourceBinder();
|
||||
|
||||
ResourceConfig resourceConfig = new ResourceConfig(JacksonFeature.class);
|
||||
resourceConfig.packages(RestServer.class.getPackage().getName()+".services"); // Services are located in services package
|
||||
resourceConfig.register(binder);
|
||||
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig);
|
||||
|
||||
// Static content
|
||||
// String home = System.getenv("BROKER_BASE");
|
||||
// if (home == null) {
|
||||
// home = "src/main/assembly";
|
||||
// }
|
||||
// home = home + "/www";
|
||||
// server.getServerConfiguration().addHttpHandler(new StaticHttpHandler(home), "/static");
|
||||
|
||||
logger.info("Broker started");
|
||||
// logger.info(String.format("Management interface available at %sstatic/", baseUri));
|
||||
logger.info("Use ctrl+c to stop ...");
|
||||
|
||||
// Signal handling
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
Signal.handle(new Signal("INT"), new SignalHandler() {
|
||||
public void handle(Signal sig) {
|
||||
if(latch.getCount()==0){
|
||||
logger.info("Terminate broker by System.exit()");
|
||||
System.exit(1); // Terminate program after 2 ctrl+c
|
||||
}
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
// Wait for termination, i.e. wait for ctrl+c
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
server.stop();
|
||||
|
||||
// broker.terminate();
|
||||
|
||||
}
|
||||
}
|
||||
85
ch.psi.fda/src/main/java/ch/psi/fda/rest/ZMQDataService.java
Normal file
85
ch.psi.fda/src/main/java/ch/psi/fda/rest/ZMQDataService.java
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but without any
|
||||
* warranty; without even the implied warranty of merchantability or fitness for
|
||||
* a particular purpose. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.rest;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jeromq.ZMQ;
|
||||
|
||||
import ch.psi.fda.core.messages.Message;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
/**
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ZMQDataService {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ZMQDataService.class.getName());
|
||||
|
||||
private final int bufferSize = 5;
|
||||
|
||||
private ZMQ.Context context;
|
||||
private ZMQ.Socket socket;
|
||||
|
||||
private String trackingId;
|
||||
|
||||
public ZMQDataService(){
|
||||
initialize();
|
||||
}
|
||||
|
||||
public void initialize(){
|
||||
context = ZMQ.context();
|
||||
zmq.ZError.clear(); // Clear error code
|
||||
socket = context.socket(ZMQ.PUB);
|
||||
socket.setHWM(bufferSize);
|
||||
socket.bind("tcp://*:10000");
|
||||
}
|
||||
|
||||
public void terminate(){
|
||||
socket.close();
|
||||
context.term();
|
||||
zmq.ZError.clear(); // Clear error code
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMessage(Message m) {
|
||||
logger.info(m.toString());
|
||||
socket.sendMore("{\"trackingId\":\"" + trackingId + "\"}");
|
||||
try (
|
||||
ByteArrayOutputStream b = new ByteArrayOutputStream();
|
||||
ObjectOutputStream o = new ObjectOutputStream(b);
|
||||
) {
|
||||
o.writeObject(m);
|
||||
socket.send(b.toByteArray());
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.WARNING, "Unable to serialize message", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setTrackingId(String id){
|
||||
trackingId = id;
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,34 @@
|
||||
* along with this code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package ch.psi.fda.aq.ng.rdescriptors;
|
||||
|
||||
/**
|
||||
* Resource descriptor of an operating system shell.
|
||||
* @author ebner
|
||||
*
|
||||
*/
|
||||
public class ShellDescriptor {
|
||||
package ch.psi.fda.rest.services;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import ch.psi.fda.model.v1.Configuration;
|
||||
import ch.psi.fda.rest.AcquisitionEngine;
|
||||
|
||||
@Path("fda")
|
||||
public class ScanService {
|
||||
|
||||
@Inject
|
||||
private AcquisitionEngine aengine;
|
||||
|
||||
@POST
|
||||
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
|
||||
// @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
|
||||
public String execute(Configuration configuration) throws InterruptedException{
|
||||
return aengine.submit(configuration);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
public void stop(){
|
||||
aengine.terminate();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user