Compare commits
155 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d1e8913dd4 | |||
| c5d845e7ff | |||
| 5f836e7856 | |||
| 8c13c1c85d | |||
| e1ff42d464 | |||
| b014dd6afd | |||
| e412ae7092 | |||
| e63d2e3052 | |||
| 09ead2eb64 | |||
| 166e8d325a | |||
| 03ac83adf6 | |||
| edf3672317 | |||
| 10f0fcdde2 | |||
| 19d2b28f25 | |||
| ac04a730a3 | |||
| 87ed988dfe | |||
| fb21986493 | |||
| 1601fbcbfd | |||
| c25a80ddfb | |||
| ba630a44e1 | |||
| 5316773104 | |||
| 38b60f3f5e | |||
| 31d37c7c45 | |||
| 366a7f2a74 | |||
| e5cc3126ab | |||
| 45505b511d | |||
| e21b3d64ee | |||
| 1a294a1a75 | |||
| fb5b2ff257 | |||
| 8d9fba4be6 | |||
| 065ed130a6 | |||
| 074ac2caff | |||
| f2e3bf23e8 | |||
| f39822ec74 | |||
| 5038912472 | |||
| 8ab87b8332 | |||
| 8f698e82ba | |||
| 58e92684ad | |||
| 5a6396cfb7 | |||
| 57ecb121b2 | |||
| 3ce7282214 | |||
| 16d18288b6 | |||
| 76ce595f87 | |||
| 486d11db2b | |||
| fa2416492e | |||
| db097eba8f | |||
| 838f6fd385 | |||
| 1c9eca2a1c | |||
| f30aa6495f | |||
| a15356190d | |||
| 88f4dd2b19 | |||
| 9f4c6c0356 | |||
| 84fb119932 | |||
| 311eae3cbc | |||
| 9529d7f088 | |||
| e597b5cd12 | |||
| 8ab6f7965b | |||
| 4bb984cc1c | |||
| b64f31e778 | |||
| 43a8347924 | |||
| f520ff4337 | |||
| 5995b2ed5c | |||
| e20cab4874 | |||
| 576d7eb048 | |||
| 21f86d7d69 | |||
| aa1681aaf3 | |||
| da182adcd2 | |||
| 8d1bd4e816 | |||
| 07d6b47885 | |||
| 87781b8f06 | |||
| 28bd7c40d8 | |||
| dcd394b586 | |||
| 76c40ccf28 | |||
| 8522d46813 | |||
| 1077ec8ab3 | |||
| da0e0eab79 | |||
| ac54407e34 | |||
| b0d4ef9d8b | |||
| f8ee1bd666 | |||
| 8d37cdbeca | |||
| fbe03b7ade | |||
| d866fa0eda | |||
| 2b0877c65d | |||
| d7f1b15927 | |||
| 35a4949907 | |||
| 30355deacc | |||
| eb0aa9a1b6 | |||
| b447ec12d7 | |||
| ae78b8c7a7 | |||
| c9ff7ccf2c | |||
| c01995675e | |||
| e4885d11e1 | |||
| 407aff2e24 | |||
| 9d6ae89f13 | |||
| fafea6dc69 | |||
| 3e841c7596 | |||
| 542379545b | |||
| 4d0f329e72 | |||
| 488fa5c908 | |||
| d550e59254 | |||
| 685ac0cd2d | |||
| 9476f9b57c | |||
| 8888172ede | |||
| e324987c8e | |||
| 76e9ea1bed | |||
| 244001fd99 | |||
| 55faaa2aa3 | |||
| ab0d1654c1 | |||
| 726cf9c0ff | |||
| 03c7d84b05 | |||
| 54fb16a0e9 | |||
| f96b85f6d0 | |||
| 696893ba16 | |||
| d84ce43676 | |||
| e625185b6d | |||
| 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 |
8
.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/bin
|
||||||
|
/target
|
||||||
|
/build
|
||||||
|
.gradle
|
||||||
|
.settings
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
/schema/
|
||||||
165
Readme.md
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
# Overview
|
||||||
|
This package holds the core functionality of FDA.
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
use -Djava.util.logging.config.file=logging.properties` to configure logging
|
||||||
|
|
||||||
|
## Server
|
||||||
|
|
||||||
|
The FDA server is started as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
./bin/server -h
|
||||||
|
usage: fda
|
||||||
|
-h Help
|
||||||
|
-p <arg> Server port (default: 8080)
|
||||||
|
-s <arg> Server address (default: localhost)
|
||||||
|
```
|
||||||
|
|
||||||
|
Start new scan:
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -X PUT -d @scan1d.xml -H 'Content-Type:application/xml' http://localhost:8080/fda/scan
|
||||||
|
```
|
||||||
|
|
||||||
|
## Viewer
|
||||||
|
|
||||||
|
```
|
||||||
|
./bin/viewer -h
|
||||||
|
usage: viewer
|
||||||
|
-h Help
|
||||||
|
-p <arg> Server port (default: 10000)
|
||||||
|
-s <arg> Server address (default: localhost)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
# Development
|
||||||
|
When checking out the project from the repository there is the `target/generated-sources/xjc` folder missing.
|
||||||
|
After checking out the project execute `mvn compile` to create the folder and the required classes.
|
||||||
|
|
||||||
|
To build project use `mvn clean install`.
|
||||||
|
|
||||||
|
To upload the latest version to the central artifact repository use `mvn clean deploy`.
|
||||||
|
Create Zip file via `mvn clean compile assembly:assembly`
|
||||||
|
|
||||||
|
To use the FDA libary in an other project (like the GUI project) use:
|
||||||
|
|
||||||
|
```
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.psi</groupId>
|
||||||
|
<artifactId>fda</artifactId>
|
||||||
|
<version>x.x.x</version>
|
||||||
|
</dependency>
|
||||||
|
```
|
||||||
|
|
||||||
|
## REST
|
||||||
|
FDA offers a rest service to execute scans. There are 3 distinct service for fda scan, fdaq and cdump.
|
||||||
|
|
||||||
|
### FDA Service
|
||||||
|
|
||||||
|
Submit scan
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT fda/{trackingId}
|
||||||
|
Content-Type: application/xml
|
||||||
|
<configuration>
|
||||||
|
...
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
204 - Success
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Stop/cancel scan
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE fda/{trackingId}
|
||||||
|
|
||||||
|
204 - Success
|
||||||
|
```
|
||||||
|
|
||||||
|
Stop all scans
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE fda
|
||||||
|
|
||||||
|
204 - Success
|
||||||
|
```
|
||||||
|
|
||||||
|
Check if scan is running
|
||||||
|
|
||||||
|
```
|
||||||
|
GET fda/{trackingId}/running
|
||||||
|
|
||||||
|
200 - true/false
|
||||||
|
```
|
||||||
|
|
||||||
|
Wait for scan done (blocks until scan is done)
|
||||||
|
|
||||||
|
```
|
||||||
|
GET fda/{trackingId}/done
|
||||||
|
|
||||||
|
204 - Success
|
||||||
|
```
|
||||||
|
|
||||||
|
# Notes
|
||||||
|
## Upgrade FDA 1.x to 2.x
|
||||||
|
In existing fda.properties file the following property need to be added: `ch.psi.fda.aq.data.dir=../data`
|
||||||
|
|
||||||
|
## Upgrade FDA 2.6.1
|
||||||
|
There are 2 new properties for crlogic:
|
||||||
|
|
||||||
|
```
|
||||||
|
ch.psi.fda.aq.crlogic.ioc=X05LA-VME-ES2
|
||||||
|
ch.psi.fda.aq.crlogic.prefix=X05LA-ES2-CRL
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
# FDAQ
|
||||||
|
## Overview
|
||||||
|
This software is used to readout the FDAQ box developed at X10SA.
|
||||||
|
On The FDAQ box there are 2 socket servers, one for retrieving the data and one for resetting the socket
|
||||||
|
server for data retrieval.
|
||||||
|
|
||||||
|
The fdaq code provides exactly 2 functionalities. It can query on the data socket for data (need to specifying how many data point to read),
|
||||||
|
and it can send a reset request on the reset channel.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To acquire data into a file use:
|
||||||
|
|
||||||
|
```
|
||||||
|
java -jar ch.psi.fda.fdaq-<version>.jar <file>
|
||||||
|
```
|
||||||
|
|
||||||
|
You can terminate the acquisition with *CTRL+C*. If you submit 2 consequtive *CTRL+C* the program will terminate immediately (and data might be lost);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
This will take the default connections settings:
|
||||||
|
|
||||||
|
* Hostname: mchip015.psi.ch
|
||||||
|
* Port: 2233
|
||||||
|
* Kill Port: 2234
|
||||||
|
* Number Of Elements: Integer.MAX_VALUE/2
|
||||||
|
|
||||||
|
If you need to specify different settings create a property files with following content:
|
||||||
|
|
||||||
|
```
|
||||||
|
ch.psi.fda.fdaq.hostname=myhost
|
||||||
|
ch.psi.fda.fdaq.port=1234
|
||||||
|
ch.psi.fda.fdaq.killPort=4321
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `-Dch.psi.fda.fdaq.config.file=<file>` to use this property file as base configuration.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Development
|
||||||
|
A standalone jar can be build via `mvn clean compile assembly:single`.
|
||||||
|
|
||||||
|
To upload the latest version to the artifact repository use ` mvn clean compile deploy`.
|
||||||
|
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
Trigger port is `Trigger In 1`. For testing apply a 1kHz signal.
|
||||||
92
build.gradle
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
apply plugin: 'java'
|
||||||
|
apply plugin: 'eclipse'
|
||||||
|
|
||||||
|
sourceCompatibility = 1.7
|
||||||
|
|
||||||
|
version = '3.0.0'
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url "https://plugins.gradle.org/m2/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "com.github.jacobono:gradle-jaxb-plugin:1.3.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: "com.github.jacobono.jaxb"
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven { url "http://artifacts.psi.ch/artifactory/libs-releases" }
|
||||||
|
maven { url "http://artifacts.psi.ch/artifactory/libs-snapshots" }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile 'ch.psi:jcae:2.4.1'
|
||||||
|
compile 'com.google.inject:guice:3.0'
|
||||||
|
compile 'org.glassfish.jersey.containers:jersey-container-grizzly2-http:2.5.1'
|
||||||
|
compile 'org.glassfish.jersey.media:jersey-media-sse:2.5.1'
|
||||||
|
compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.5.1'
|
||||||
|
compile 'org.zeromq:jeromq:0.3.4'
|
||||||
|
compile 'org.apache.commons:cli:1.2'
|
||||||
|
// For reading/writing Matlab files
|
||||||
|
compile 'com.jmatio:jmatio:0.2u2psi1'
|
||||||
|
// Library for reading/writing XDR Format (MDA)
|
||||||
|
compile 'org.freehep:freehep-xdr:2.0.4'
|
||||||
|
compile 'ch.psi:plot:2.1-SNAPSHOT'
|
||||||
|
|
||||||
|
compile 'com.google.guava:guava:>15.0'
|
||||||
|
|
||||||
|
compile 'com.sun.mail:javax.mail:1.5.0'
|
||||||
|
compile 'javax.inject:javax.inject:1'
|
||||||
|
compile 'org.python:jython:2.5.3'
|
||||||
|
compile 'com.fasterxml.jackson.core:jackson-databind:2.5.2'
|
||||||
|
|
||||||
|
|
||||||
|
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.7-b41'
|
||||||
|
jaxb 'com.sun.xml.bind:jaxb-impl:2.2.7-b41'
|
||||||
|
jaxb 'javax.xml.bind:jaxb-api:2.2.7'
|
||||||
|
|
||||||
|
testCompile 'junit:junit:4.+'
|
||||||
|
}
|
||||||
|
|
||||||
|
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||||
|
classifier = 'sources'
|
||||||
|
from sourceSets.main.allSource
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||||
|
classifier = 'javadoc'
|
||||||
|
from javadoc.destinationDir
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
artifacts {
|
||||||
|
archives sourcesJar
|
||||||
|
//archives javadocJar
|
||||||
|
}
|
||||||
|
|
||||||
|
jaxb{
|
||||||
|
xsdDir = "src/main/resources"
|
||||||
|
xjc {
|
||||||
|
generatePackage = "ch.psi.fda.model.v1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'maven'
|
||||||
|
|
||||||
|
uploadArchives {
|
||||||
|
repositories {
|
||||||
|
mavenDeployer {
|
||||||
|
repository(url: "http://artifacts.psi.ch/artifactory/libs-snapshots-local"){
|
||||||
|
authentication(userName: "upload", password: "{DESede}eWKHxAtQ2Dc=")
|
||||||
|
}
|
||||||
|
pom.groupId = 'ch.psi'
|
||||||
|
pom.artifactId = 'fda'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<classpath>
|
|
||||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="src" path="target/generated-sources/xjc"/>
|
|
||||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="optional" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
|
||||||
</classpath>
|
|
||||||
1
ch.psi.fda/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
/target
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>ch.psi.fda</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
|
||||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
eclipse.preferences.version=1
|
|
||||||
encoding//src/main/java=UTF-8
|
|
||||||
encoding//src/test/java=UTF-8
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
eclipse.preferences.version=1
|
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
|
||||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
|
||||||
org.eclipse.jdt.core.compiler.source=1.7
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#Tue Oct 18 15:52:42 CEST 2011
|
|
||||||
activeProfiles=
|
|
||||||
eclipse.preferences.version=1
|
|
||||||
resolveWorkspaceProjects=true
|
|
||||||
version=1
|
|
||||||
@@ -1,223 +0,0 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>ch.psi</groupId>
|
|
||||||
<artifactId>fda</artifactId>
|
|
||||||
<version>1.1.40</version>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.guava</groupId>
|
|
||||||
<artifactId>guava</artifactId>
|
|
||||||
<version>15.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.inject</groupId>
|
|
||||||
<artifactId>guice</artifactId>
|
|
||||||
<version>3.0</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-lang</groupId>
|
|
||||||
<artifactId>commons-lang</artifactId>
|
|
||||||
<version>2.6</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>ch.psi</groupId>
|
|
||||||
<artifactId>jcae</artifactId>
|
|
||||||
<version>1.0.30</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- Plotting library -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>ch.psi</groupId>
|
|
||||||
<artifactId>plot</artifactId>
|
|
||||||
<version>1.1.30</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- Java SMB/CIFS library -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>jcifs</groupId>
|
|
||||||
<artifactId>jcifs</artifactId>
|
|
||||||
<version>1.3.17</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- JAXB implementation -->
|
|
||||||
<!-- <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId>
|
|
||||||
<version>2.2.1</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId>
|
|
||||||
<artifactId>jaxb-xjc</artifactId> <version>2.2.1</version> </dependency> -->
|
|
||||||
<!-- Jython Library -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.python</groupId>
|
|
||||||
<artifactId>jython</artifactId>
|
|
||||||
<version>2.5.3</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- CLI Libraries -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>cli</artifactId>
|
|
||||||
<version>1.2</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- Library to Read Matlab Files -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.jmatio</groupId>
|
|
||||||
<artifactId>jmatio</artifactId>
|
|
||||||
<version>0.2u2psi1</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- Mail Libraries -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.mail</groupId>
|
|
||||||
<artifactId>mail</artifactId>
|
|
||||||
<version>1.4.1</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- Library for reading/writing XDR Format (MDA) -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.freehep</groupId>
|
|
||||||
<artifactId>freehep-xdr</artifactId>
|
|
||||||
<version>2.0.4</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- JUnit test library -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<version>4.8.2</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<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>
|
|
||||||
</plugin>
|
|
||||||
<!-- Generate Javadoc Jar -->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
|
||||||
<version>2.8</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>attach-javadocs</id>
|
|
||||||
<goals>
|
|
||||||
<goal>jar</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<!-- Generate Source Jar -->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-source-plugin</artifactId>
|
|
||||||
<version>2.1.2</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>attach-sources</id>
|
|
||||||
<goals>
|
|
||||||
<goal>jar</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<!-- Schema generation -->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.jvnet.jaxb2.maven2</groupId>
|
|
||||||
<artifactId>maven-jaxb2-plugin</artifactId>
|
|
||||||
<version>0.8.0</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>generate</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<generatePackage>ch.psi.fda.model.v1</generatePackage>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<!-- Schema Documentation Generation -->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>xml-maven-plugin</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>transform</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>transform</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<transformationSets>
|
|
||||||
<transformationSet>
|
|
||||||
<!-- <outputDir>target</outputDir> -->
|
|
||||||
<dir>src/main/resources</dir>
|
|
||||||
<stylesheet>src/main/documentation/xs3p.xsl</stylesheet>
|
|
||||||
<fileMappers>
|
|
||||||
<fileMapper
|
|
||||||
implementation="org.codehaus.plexus.components.io.filemappers.RegExpFileMapper">
|
|
||||||
<pattern>\.xsd$</pattern>
|
|
||||||
<replacement>.html</replacement>
|
|
||||||
</fileMapper>
|
|
||||||
</fileMappers>
|
|
||||||
</transformationSet>
|
|
||||||
</transformationSets>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
<pluginManagement>
|
|
||||||
<plugins>
|
|
||||||
<!--This plugin's configuration is used to store Eclipse m2e settings
|
|
||||||
only. It has no influence on the Maven build itself. -->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.eclipse.m2e</groupId>
|
|
||||||
<artifactId>lifecycle-mapping</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
<configuration>
|
|
||||||
<lifecycleMappingMetadata>
|
|
||||||
<pluginExecutions>
|
|
||||||
<pluginExecution>
|
|
||||||
<pluginExecutionFilter>
|
|
||||||
<groupId>
|
|
||||||
org.jvnet.jaxb2.maven2
|
|
||||||
</groupId>
|
|
||||||
<artifactId>
|
|
||||||
maven-jaxb2-plugin
|
|
||||||
</artifactId>
|
|
||||||
<versionRange>
|
|
||||||
[0.8.0,)
|
|
||||||
</versionRange>
|
|
||||||
<goals>
|
|
||||||
<goal>generate</goal>
|
|
||||||
</goals>
|
|
||||||
</pluginExecutionFilter>
|
|
||||||
<action>
|
|
||||||
<ignore></ignore>
|
|
||||||
</action>
|
|
||||||
</pluginExecution>
|
|
||||||
</pluginExecutions>
|
|
||||||
</lifecycleMappingMetadata>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</pluginManagement>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<distributionManagement>
|
|
||||||
<snapshotRepository>
|
|
||||||
<id>i.snapshots</id>
|
|
||||||
<name>Artifactory Snapshots</name>
|
|
||||||
<url>http://yoke/artifactory/libs-snapshots-local</url>
|
|
||||||
</snapshotRepository>
|
|
||||||
<repository>
|
|
||||||
<id>i.releases</id>
|
|
||||||
<name>Atrifactory Releases</name>
|
|
||||||
<url>http://yoke/artifactory/libs-releases-local</url>
|
|
||||||
</repository>
|
|
||||||
</distributionManagement>
|
|
||||||
</project>
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package ch.psi.fda.aq;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
import ch.psi.jcae.ChannelBeanFactory;
|
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
|
||||||
|
|
||||||
public class AcquisitionModule extends AbstractModule {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
try {
|
|
||||||
bind(ChannelBeanFactory.class).toInstance(ChannelBeanFactory.getFactory());
|
|
||||||
} catch (CAException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,155 +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.aq;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
|
||||||
|
|
||||||
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 EventBus bus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public Collector(EventBus b){
|
|
||||||
queues = new ArrayList<DataQueue>();
|
|
||||||
this.bus = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (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
|
|
||||||
}
|
|
||||||
|
|
||||||
bus.post(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
bus.post(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
|
|
||||||
bus.post(ddm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the queues
|
|
||||||
*/
|
|
||||||
public List<DataQueue> getQueues() {
|
|
||||||
return queues;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the outgoing data metadata
|
|
||||||
*/
|
|
||||||
public DataMessageMetadata getMetadata(){
|
|
||||||
DataMessageMetadata dataMessageMetadata = new DataMessageMetadata();
|
|
||||||
|
|
||||||
// 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(dataMessageMetadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,156 +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.logging.Logger;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
import ch.psi.fda.core.Action;
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
import ch.psi.jcae.ChannelBeanFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Condition a channnel needs to match
|
|
||||||
* Only accepts channels of type Integer
|
|
||||||
*
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ChannelAccessConditionAnd implements Action {
|
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
private static Logger logger = Logger.getLogger(ChannelAccessConditionAnd.class.getName());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Channel to set
|
|
||||||
*/
|
|
||||||
private final ChannelBean<Integer> channel;
|
|
||||||
/**
|
|
||||||
* Value to wait for
|
|
||||||
*/
|
|
||||||
private final Integer 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(String channelName, Integer expectedValue, Long timeout){
|
|
||||||
|
|
||||||
if(timeout !=null && timeout<=0){
|
|
||||||
throw new IllegalArgumentException("Timeout must be > 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.channel = (ChannelBean<Integer>) ChannelBeanFactory.getFactory().createChannelBean( (Class<Integer>) expectedValue.getClass(), channelName, false);
|
|
||||||
} catch (CAException 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();
|
|
||||||
}
|
|
||||||
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<Integer>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(Integer o1, Integer 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 (CAException 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 (CAException e) {
|
|
||||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,156 +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.logging.Logger;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
import ch.psi.fda.core.Action;
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
import ch.psi.jcae.ChannelBeanFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Or condition of a channel
|
|
||||||
* Only supports Integer values and channel
|
|
||||||
*
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ChannelAccessConditionOr implements Action {
|
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
private static Logger logger = Logger.getLogger(ChannelAccessConditionOr.class.getName());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Channel to set
|
|
||||||
*/
|
|
||||||
private final ChannelBean<Integer> channel;
|
|
||||||
/**
|
|
||||||
* Value to wait for
|
|
||||||
*/
|
|
||||||
private final Integer 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(String channelName, Integer expectedValue, Long timeout){
|
|
||||||
|
|
||||||
if(timeout !=null && timeout<=0){
|
|
||||||
throw new IllegalArgumentException("Timeout must be > 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.channel = (ChannelBean<Integer>) ChannelBeanFactory.getFactory().createChannelBean( (Class<Integer>) expectedValue.getClass(), channelName, false);
|
|
||||||
} catch (CAException 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();
|
|
||||||
}
|
|
||||||
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<Integer>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(Integer o1, Integer 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 (CAException 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 (CAException e) {
|
|
||||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,149 +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.logging.Logger;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
import ch.psi.fda.core.Action;
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
import ch.psi.jcae.ChannelBeanFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regex condition
|
|
||||||
* Only supports String value/channel.
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ChannelAccessConditionRegex implements Action {
|
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
private static Logger logger = Logger.getLogger(ChannelAccessConditionRegex.class.getName());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Channel to set
|
|
||||||
*/
|
|
||||||
private final ChannelBean<String> channel;
|
|
||||||
/**
|
|
||||||
* Value to wait for
|
|
||||||
*/
|
|
||||||
private final String 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(String channelName, String expectedValue, Long timeout){
|
|
||||||
|
|
||||||
if(timeout !=null && timeout<=0){
|
|
||||||
throw new IllegalArgumentException("Timeout must be > 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.channel = (ChannelBean<String>) ChannelBeanFactory.getFactory().createChannelBean( (Class<String>) expectedValue.getClass(), channelName, false);
|
|
||||||
} catch (CAException 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();
|
|
||||||
}
|
|
||||||
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<String>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(String o1, String 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 (CAException 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 (CAException e) {
|
|
||||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,96 +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.guard;
|
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
import ch.psi.jcae.ChannelBeanFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Channel and condition that need to be met.
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ChannelAccessGuardCondition {
|
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
private static Logger logger = Logger.getLogger(ChannelAccessGuardCondition.class.getName());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Channel name
|
|
||||||
*/
|
|
||||||
private final ChannelBean<?> channel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Value of the channel to meet condition
|
|
||||||
*/
|
|
||||||
private final Object value;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
* @param channel Name of the channel that contributes to a guard
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
public ChannelAccessGuardCondition(String channel, Object value){
|
|
||||||
try {
|
|
||||||
this.channel = ChannelBeanFactory.getFactory().createChannelBean(value.getClass(), channel, true);
|
|
||||||
} catch (CAException 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);
|
|
||||||
}
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the channel
|
|
||||||
*/
|
|
||||||
public ChannelBean<?> getChannel() {
|
|
||||||
return channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the value
|
|
||||||
*/
|
|
||||||
public Object 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 (CAException e) {
|
|
||||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright 2012 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;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
|
|
||||||
import jcifs.smb.SmbFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class DistributedFile {
|
|
||||||
|
|
||||||
private SmbFile smbfile = null;
|
|
||||||
private File file = null;
|
|
||||||
|
|
||||||
public DistributedFile(SmbFile file){
|
|
||||||
this.smbfile = file;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DistributedFile(File file){
|
|
||||||
this.file = file;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DistributedFile(String url) throws MalformedURLException{
|
|
||||||
if(url.startsWith("smb://")){
|
|
||||||
smbfile = new SmbFile(url);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
file = new File(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getCanonicalPath() throws IOException{
|
|
||||||
if(smbfile!=null){
|
|
||||||
return(smbfile.getCanonicalPath());
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return file.getCanonicalPath();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public boolean exists() throws IOException {
|
|
||||||
if(smbfile!=null){
|
|
||||||
return(smbfile.exists());
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return file.exists();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean isDirectory() throws IOException {
|
|
||||||
if(smbfile!=null){
|
|
||||||
return(smbfile.isDirectory());
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return file.isDirectory();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public DistributedFile[] listFiles() throws IOException {
|
|
||||||
if(smbfile!=null){
|
|
||||||
SmbFile[] files = smbfile.listFiles();
|
|
||||||
DistributedFile[] dfiles = new DistributedFile[files.length];
|
|
||||||
for(int i=0;i<files.length;i++){
|
|
||||||
dfiles[i] = new DistributedFile(files[i]);
|
|
||||||
}
|
|
||||||
return(dfiles);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
File[] files = file.listFiles();
|
|
||||||
DistributedFile[] dfiles = new DistributedFile[files.length];
|
|
||||||
for(int i=0;i<files.length;i++){
|
|
||||||
dfiles[i] = new DistributedFile(files[i]);
|
|
||||||
}
|
|
||||||
return(dfiles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getName() {
|
|
||||||
if(smbfile!=null){
|
|
||||||
return(smbfile.getName());
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return file.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean isFile() throws IOException {
|
|
||||||
if(smbfile!=null){
|
|
||||||
return(smbfile.isFile());
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return file.isFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void delete() throws IOException {
|
|
||||||
if(smbfile!=null){
|
|
||||||
smbfile.delete();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public InputStreamReader getInputStream() throws IOException {
|
|
||||||
if(smbfile!=null){
|
|
||||||
return(new InputStreamReader(smbfile.getInputStream()));
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return new FileReader(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,770 +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.loops;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import ch.psi.jcae.annotation.CaChannel;
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bean holding all OTF channels and functionality
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class OTFBean {
|
|
||||||
|
|
||||||
public enum Status { SETUP, INACTIVE, INITIALIZE, ACTIVE, STOP, FAULT, ERROR };
|
|
||||||
public enum Command { NONE, START, STOP };
|
|
||||||
|
|
||||||
private long timeoutMotorOk = 8000;
|
|
||||||
private long commandTimeout = 20000; // Maximum time until a command should take effect
|
|
||||||
|
|
||||||
@CaChannel(type=String.class, name =":UMOT")
|
|
||||||
private ChannelBean<String> motor;
|
|
||||||
|
|
||||||
@CaChannel(type=String.class, name=":MENC")
|
|
||||||
private ChannelBean<String> encoder;
|
|
||||||
|
|
||||||
@CaChannel(type=Double.class, name=":UBEG")
|
|
||||||
private ChannelBean<Double> begin;
|
|
||||||
|
|
||||||
@CaChannel(type=Double.class, name=":UBEG.DRVL")
|
|
||||||
private ChannelBean<Double> beginMin;
|
|
||||||
|
|
||||||
@CaChannel(type=Double.class, name=":UBEG.DRVH")
|
|
||||||
private ChannelBean<Double> beginMax;
|
|
||||||
|
|
||||||
@CaChannel(type=Double.class, name=":UEND")
|
|
||||||
private ChannelBean<Double> end;
|
|
||||||
|
|
||||||
@CaChannel(type=Double.class, name=":UEND.DRVL")
|
|
||||||
private ChannelBean<Double> endMin;
|
|
||||||
|
|
||||||
@CaChannel(type=Double.class, name=":UEND.DRVH")
|
|
||||||
private ChannelBean<Double> endMax;
|
|
||||||
|
|
||||||
@CaChannel(type=Double.class, name=":USSIZ")
|
|
||||||
private ChannelBean<Double> stepSize;
|
|
||||||
|
|
||||||
@CaChannel(type=Double.class, name=":USSIZ.DRVL")
|
|
||||||
private ChannelBean<Double> stepSizeMin;
|
|
||||||
|
|
||||||
@CaChannel(type=Double.class, name=":UITIM")
|
|
||||||
private ChannelBean<Double> integrationTime;
|
|
||||||
|
|
||||||
@CaChannel(type=Double.class, name=":UITIM.DRVL")
|
|
||||||
private ChannelBean<Double> integrationTimeMin;
|
|
||||||
|
|
||||||
@CaChannel(type=Double.class, name=":UITIM.DRVH")
|
|
||||||
private ChannelBean<Double> integrationTimeMax;
|
|
||||||
|
|
||||||
@CaChannel(type=Double.class, name=":UBCL")
|
|
||||||
private ChannelBean<Double> userBacklash;
|
|
||||||
|
|
||||||
@CaChannel(type=String.class, name=":NFSSE")
|
|
||||||
private ChannelBean<String> nfsServer;
|
|
||||||
|
|
||||||
@CaChannel(type=String.class, name=":NFSSH")
|
|
||||||
private ChannelBean<String> nfsShare;
|
|
||||||
|
|
||||||
@CaChannel(type=String.class, name=":DFNAM")
|
|
||||||
private ChannelBean<String> fileName;
|
|
||||||
|
|
||||||
@CaChannel(type=String.class, name=":FFORM")
|
|
||||||
private ChannelBean<String> fileNameFormat;
|
|
||||||
|
|
||||||
@CaChannel(type=Integer.class, name=":FCNT")
|
|
||||||
private ChannelBean<Integer> fileCount;
|
|
||||||
|
|
||||||
@CaChannel(type=Integer.class, name=":FCNT.B")
|
|
||||||
private ChannelBean<Integer> resetFileCounter;
|
|
||||||
|
|
||||||
@CaChannel(type=Boolean.class, name=":FAPPE")
|
|
||||||
private ChannelBean<Boolean> appendFile;
|
|
||||||
|
|
||||||
@CaChannel(type=Boolean.class, name=":FUSE")
|
|
||||||
private ChannelBean<Boolean> fileNameGeneration;
|
|
||||||
|
|
||||||
@CaChannel(type=Boolean.class, name=":UZIGZ")
|
|
||||||
private ChannelBean<Boolean> zigZag;
|
|
||||||
|
|
||||||
@CaChannel(type=Integer.class, name=":UCOM")
|
|
||||||
private ChannelBean<Integer> command;
|
|
||||||
|
|
||||||
@CaChannel(type=Boolean.class, name=":SCRU", monitor=true)
|
|
||||||
private ChannelBean<Boolean> scanRunning;
|
|
||||||
|
|
||||||
@CaChannel(type=Boolean.class, name=":MUENC")
|
|
||||||
private ChannelBean<Boolean> useEncoder;
|
|
||||||
|
|
||||||
@CaChannel(type=String.class, name={":CTM0",":CTM1",":CTM2",":CTM3",":CTM4",":CTM5",":CTM6",":CTM7"})
|
|
||||||
private List<ChannelBean<String>> monitoredChannels;
|
|
||||||
|
|
||||||
@CaChannel(type=Boolean.class, name=":OTF", monitor=true)
|
|
||||||
private ChannelBean<Boolean> running;
|
|
||||||
|
|
||||||
@CaChannel(type=Integer.class, name=":USTAT", monitor=true)
|
|
||||||
private ChannelBean<Integer> status;
|
|
||||||
|
|
||||||
@CaChannel(type=Boolean.class, name=":MOK", monitor=true)
|
|
||||||
private ChannelBean<Boolean> motorOk;
|
|
||||||
|
|
||||||
@CaChannel(type=Boolean.class, name=":EOK", monitor=true)
|
|
||||||
private ChannelBean<Boolean> encoderOk;
|
|
||||||
|
|
||||||
@CaChannel(type=String.class, name=":MSG")
|
|
||||||
private ChannelBean<String> message;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the trigger name that can be used by the sscan record to trigger an OTFScan
|
|
||||||
* @return Name of the trigger that can be used by sscan record
|
|
||||||
*/
|
|
||||||
public String getSScanTriggerName(){
|
|
||||||
return(running.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start OTF scan
|
|
||||||
*/
|
|
||||||
public void start() {
|
|
||||||
try{
|
|
||||||
if(getStatus().equals(Status.INACTIVE)){
|
|
||||||
|
|
||||||
// Send START command
|
|
||||||
this.command.setValue(Command.START.ordinal());
|
|
||||||
|
|
||||||
// Wait until OtF logic is active
|
|
||||||
this.scanRunning.waitForValue(true, commandTimeout);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
throw new RuntimeException("Cannot start scan, status is not INACTIVE.\nThe current status is: "+getStatus()+" . The OTF logic need to be recovered manually [Message: "+getMessage()+"]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(Exception e){
|
|
||||||
throw new RuntimeException("Unable to start OTF scan.",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abort scan
|
|
||||||
*/
|
|
||||||
public void abort() {
|
|
||||||
try{
|
|
||||||
// Send STOP command
|
|
||||||
this.command.setValue(Command.STOP.ordinal());
|
|
||||||
|
|
||||||
// Do not wait for put to return
|
|
||||||
this.running.setValueNoWait(false);
|
|
||||||
}
|
|
||||||
catch(Exception e){
|
|
||||||
throw new RuntimeException("Unable to abort OTF logic" ,e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop OTF scan
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public void stop() throws Exception{
|
|
||||||
if(!getStatus().equals(Status.INACTIVE) || !getStatus().equals(Status.FAULT)){
|
|
||||||
|
|
||||||
// Send STOP command
|
|
||||||
this.command.setValue(Command.STOP.ordinal());
|
|
||||||
|
|
||||||
// Wait until logic is stopped
|
|
||||||
status.waitForValue(Status.INACTIVE.ordinal(), commandTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait until scan has stopped
|
|
||||||
* @throws InterruptedException
|
|
||||||
*/
|
|
||||||
public void waitUntilStopped() throws InterruptedException {
|
|
||||||
try {
|
|
||||||
scanRunning.waitForValue(false); // Use of default wait timeout
|
|
||||||
|
|
||||||
// Check whether the status is INACTIVE otherwise get messge from OTF and throw an exception
|
|
||||||
if(status.getValue() != Status.INACTIVE.ordinal()){
|
|
||||||
throw new RuntimeException("OTFSCAN failed with message: "+message.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (CAException e) {
|
|
||||||
throw new RuntimeException("An error occurred while waiting for the OTF logic to finish.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait until scan has stopped
|
|
||||||
* @param waitTimeout
|
|
||||||
* @throws InterruptedException
|
|
||||||
*/
|
|
||||||
public void waitUntilStopped(Long waitTimeout) throws InterruptedException {
|
|
||||||
try {
|
|
||||||
scanRunning.waitForValue(false, waitTimeout);
|
|
||||||
|
|
||||||
// Check whether the status is INACTIVE otherwise get messge from OTF and throw an exception
|
|
||||||
if(status.getValue() != Status.INACTIVE.ordinal()){
|
|
||||||
throw new RuntimeException("OTFSCAN failed with message: "+message.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (CAException e) {
|
|
||||||
throw new RuntimeException("An error occurred while waiting for the OTF logic to finish.", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset OTFScan records to defaults
|
|
||||||
* @throws CAException
|
|
||||||
* @throws InterruptedException
|
|
||||||
*/
|
|
||||||
public void resetToDefaults() throws CAException, InterruptedException{
|
|
||||||
setMonitoredChannels(new String[]{});
|
|
||||||
setMotor("");
|
|
||||||
begin.setValue(0d);
|
|
||||||
end.setValue(0d);
|
|
||||||
stepSize.setValue(0d);
|
|
||||||
integrationTime.setValue(0d);
|
|
||||||
zigZag.setValue(false);
|
|
||||||
setAppendFile(false);
|
|
||||||
setFileNameGeneration(true);
|
|
||||||
setFileName("");
|
|
||||||
setFileNameFormat("%06d.txt");
|
|
||||||
resetFileCounter();
|
|
||||||
|
|
||||||
setUserBacklash(0d);
|
|
||||||
|
|
||||||
// setNfsServer("");
|
|
||||||
// setNfsShare("");
|
|
||||||
|
|
||||||
waitUntilMotorNotOk(timeoutMotorOk);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get motor of the OTFScan axis
|
|
||||||
* @return Name of the OTF motor
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public String getMotor() throws CAException, InterruptedException {
|
|
||||||
return(this.motor.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set motor of the OTFScan axis
|
|
||||||
* @param motor
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void setMotor(String motor) throws CAException, InterruptedException {
|
|
||||||
this.motor.setValue(motor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get encoder of the OTFScan axis
|
|
||||||
* @return Name of the used encoder
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public String getEncoder() throws CAException, InterruptedException {
|
|
||||||
return(this.encoder.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set encoder to use of the OTFScan axis
|
|
||||||
* @param encoder
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void setEncoder(String encoder) throws CAException, InterruptedException {
|
|
||||||
this.encoder.setValue(encoder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get begin position of the scan
|
|
||||||
* @return Begin position scan
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public Double getBegin() throws CAException, InterruptedException {
|
|
||||||
return(this.begin.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set begin position of scan
|
|
||||||
* @param begin
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public void setBegin(Double begin) throws CAException, InterruptedException {
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get minimum value of the begin position
|
|
||||||
* @return Min value for begin
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public Double getMinBegin() throws CAException, InterruptedException {
|
|
||||||
return(this.beginMin.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get maximum value of the begin position
|
|
||||||
* @return Max value for begin
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public Double getMaxBegin() throws CAException, InterruptedException {
|
|
||||||
return(this.beginMax.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get end position of the scan
|
|
||||||
* @return End position scan
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public Double getEnd() throws CAException, InterruptedException {
|
|
||||||
return(this.end.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set end positon of scan
|
|
||||||
* @param end
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void setEnd(Double end) throws CAException, InterruptedException {
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get minimum value of end position
|
|
||||||
* @return Min value for end
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public Double getMinEnd() throws CAException, InterruptedException {
|
|
||||||
return(this.endMin.getValue());
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get maximum value of end position
|
|
||||||
* @return Max value for end
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public Double getMaxEnd() throws CAException, InterruptedException {
|
|
||||||
return(this.endMax.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get scan step size
|
|
||||||
* @return Step size
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public Double getStepSize() throws CAException, InterruptedException {
|
|
||||||
return(this.stepSize.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set step size of scan
|
|
||||||
* @param stepSize
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void setStepSize(Double stepSize) throws CAException, InterruptedException {
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get minimum integration time
|
|
||||||
* @return Min value for step size
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public double getMinStepSize() throws CAException, InterruptedException {
|
|
||||||
return(this.stepSizeMin.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get scan integration time (time that is spend in one step)
|
|
||||||
* @return Integration time
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public Double getIntegrationTime() throws CAException, InterruptedException {
|
|
||||||
return(this.integrationTime.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set integration time of scan
|
|
||||||
* @param integrationTime
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void setIntegrationTime(Double integrationTime) throws CAException, InterruptedException {
|
|
||||||
|
|
||||||
if(integrationTime==null){
|
|
||||||
throw new IllegalArgumentException("Integration time must not be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check range (if limit is set to 0 then limit is not set)
|
|
||||||
double min = integrationTimeMin.getValue();
|
|
||||||
double max = integrationTimeMax.getValue();
|
|
||||||
if(min!= 0 && max!= 0){
|
|
||||||
if(integrationTime < min || integrationTime > max){
|
|
||||||
throw new IllegalArgumentException("Integration time ["+integrationTime+"] is outside range [min: "+min+" max: "+max+"]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(min!= 0 && integrationTime<min){
|
|
||||||
throw new IllegalArgumentException("Integration time ["+integrationTime+"] is outside range [min: "+min+" max: - ]");
|
|
||||||
}
|
|
||||||
else if(max!= 0 && integrationTime>max){
|
|
||||||
throw new IllegalArgumentException("Integration time ["+integrationTime+"] is outside range [min: - max: "+max+"]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.integrationTime.setValue(integrationTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get minimum integration time
|
|
||||||
* @return Min value for integration time
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public Double getMinIntegrationTime() throws CAException, InterruptedException {
|
|
||||||
return(this.integrationTimeMin.getValue());
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get maximum integration time
|
|
||||||
* @return Max value for integration time
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public Double getMaxIntegrationTime() throws CAException, InterruptedException {
|
|
||||||
return(this.integrationTimeMax.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get additional user defined backlash
|
|
||||||
* @return User backlash
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public Double getUserBacklash() throws CAException, InterruptedException {
|
|
||||||
return(this.userBacklash.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set additional user defined backlash
|
|
||||||
* @param userBacklash
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void setUserBacklash(Double userBacklash) throws CAException, InterruptedException {
|
|
||||||
if(userBacklash==null){
|
|
||||||
throw new IllegalArgumentException("User backlash must not be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.userBacklash.setValue(userBacklash);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the current NFS server the data is written to
|
|
||||||
* @return Name of NFS server
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public String getNfsServer() throws CAException, InterruptedException {
|
|
||||||
return(this.nfsServer.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set name of the NFS server the data is written to
|
|
||||||
* @param nfsServer
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void setNfsServer(String nfsServer) throws CAException, InterruptedException {
|
|
||||||
this.nfsServer.setValue(nfsServer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the NFS share the data is written to
|
|
||||||
* @return Name of NFS share
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public String getNfsShare() throws CAException, InterruptedException {
|
|
||||||
return(this.nfsShare.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set name of the NFS share the data is written to
|
|
||||||
* @param nfsShare
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void setNfsShare(String nfsShare) throws CAException, InterruptedException {
|
|
||||||
this.nfsShare.setValue(nfsShare);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name of the data file
|
|
||||||
* @return Name of data file name
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public String getFileName() throws CAException, InterruptedException {
|
|
||||||
return(this.fileName.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set name of the data file
|
|
||||||
* @param filename
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void setFileName(String filename) throws CAException, InterruptedException {
|
|
||||||
this.fileName.setValue(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get File name formate
|
|
||||||
* @return Get format for file name
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public String getFileNameFormat() throws CAException, InterruptedException {
|
|
||||||
return(this.fileNameFormat.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set file name formate of the data file
|
|
||||||
* @param fileNameFormat
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public void setFileNameFormat(String fileNameFormat) throws CAException, InterruptedException {
|
|
||||||
this.fileNameFormat.setValue(fileNameFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get value of the IOC based file name counter
|
|
||||||
* @return File counter
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public int getFileCounter() throws CAException, InterruptedException {
|
|
||||||
return(this.fileCount.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the IOC based file counter
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void resetFileCounter() throws CAException, InterruptedException {
|
|
||||||
this.resetFileCounter.setValue(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get if append file option is activated
|
|
||||||
* @return Append file flag
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public boolean isAppendFile() throws CAException, InterruptedException {
|
|
||||||
return(this.appendFile.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set whether to append the specified file if the file exists
|
|
||||||
* @param append
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void setAppendFile(boolean append) throws CAException, InterruptedException {
|
|
||||||
this.appendFile.setValue(append);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get if file name generation is on or off
|
|
||||||
* @return File name generation flag
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public boolean isFileNameGeneration() throws CAException, InterruptedException {
|
|
||||||
return(this.fileNameGeneration.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Whether the file name should be generated out of the file name format and the file counter
|
|
||||||
* @param generation
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void setFileNameGeneration(boolean generation) throws CAException, InterruptedException {
|
|
||||||
this.fileNameGeneration.setValue(generation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get if ZigZag scan option is on or off
|
|
||||||
* @return ZigZag flag
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public boolean isZigZag() throws CAException, InterruptedException {
|
|
||||||
return(this.zigZag.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set ZigZag scan mode on/off
|
|
||||||
* @param zigZag ZigZag mode on = true, ZigZag mode off = false
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void setZigZag(boolean zigZag) throws CAException, InterruptedException {
|
|
||||||
this.zigZag.setValue(zigZag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get whether encoder is used
|
|
||||||
*/
|
|
||||||
public boolean isUseEncoder() throws CAException, InterruptedException {
|
|
||||||
return(this.useEncoder.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set flag to use encoder
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public void setUseEncoder(boolean flag) throws CAException, InterruptedException {
|
|
||||||
this.useEncoder.setValue(flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the channels that are currently monitored by the OTFScan logic
|
|
||||||
* @return Names of the monitored channels
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public String[] getMonitoredChannels() throws CAException, InterruptedException {
|
|
||||||
String[] values = new String[this.monitoredChannels.size()];
|
|
||||||
|
|
||||||
for(int i=0; i<this.monitoredChannels.size();i++){
|
|
||||||
values[i] = monitoredChannels.get(i).getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
return(values);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the channels that need to be monitored.
|
|
||||||
* 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 CAException
|
|
||||||
*/
|
|
||||||
public void setMonitoredChannels(String[] values) throws CAException, 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]);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
this.monitoredChannels.get(i).setValue("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether an scan is running
|
|
||||||
* @return Running flag
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public boolean isRunning() throws CAException, InterruptedException {
|
|
||||||
return(running.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get status of the scan
|
|
||||||
* @return Status of the scan
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public Status getStatus() throws CAException, InterruptedException {
|
|
||||||
return(Status.values()[this.status.getValue()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the (error) message from the OTF records
|
|
||||||
* @return Message from OTF C logic
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public String getMessage() throws CAException, InterruptedException {
|
|
||||||
return(message.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether the specified motor is recognized as ok (i.e. it is registered as OTFScan motor)
|
|
||||||
* @return Flag whether motor is ok
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
public boolean isMotorOk() throws CAException, InterruptedException {
|
|
||||||
return(motorOk.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait until the motor flag goes to ok
|
|
||||||
* @param timeout Timout in milliseconds
|
|
||||||
*
|
|
||||||
* @throws CAException If motor ok flag does not switch to ok within the specified timeout
|
|
||||||
*/
|
|
||||||
public void waitUntilMotorOk(long timeout) throws CAException, InterruptedException {
|
|
||||||
motorOk.waitForValue(true, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait until the motor flag goes to not ok
|
|
||||||
* @param timeout Timout in milliseconds
|
|
||||||
*
|
|
||||||
* @throws CAException If motor ok flag does not switch to ok within the specified timeout
|
|
||||||
*/
|
|
||||||
public void waitUntilMotorNotOk(long timeout) throws CAException, InterruptedException {
|
|
||||||
motorOk.waitForValue(false, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void waitUntilEncoderOk(long timeout) throws CAException, InterruptedException {
|
|
||||||
if(!useEncoder.getValue()){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
encoderOk.waitForValue(true, timeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,521 +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.loops;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
//import jcifs.smb.SmbException;
|
|
||||||
//import jcifs.smb.SmbFile;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
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.ChannelBeanFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag to indicate whether the data of this loop will be grouped
|
|
||||||
* According to this flag the dataGroup flag in EndOfStream will be set.
|
|
||||||
*/
|
|
||||||
private boolean dataGroup = false;
|
|
||||||
|
|
||||||
// Constants
|
|
||||||
/**
|
|
||||||
* Maximum number of monitored channels
|
|
||||||
*/
|
|
||||||
private static final int numberOfMonitoredChannels = 8;
|
|
||||||
/**
|
|
||||||
* Maximum number of Scaler channels
|
|
||||||
*/
|
|
||||||
private static final int numberOfScalerChannels = 16;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default timeout (in milliseconds) for wait operations
|
|
||||||
*/
|
|
||||||
private long timeout = 8000;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the NFS server to place the data of the OTF logic
|
|
||||||
*/
|
|
||||||
private final String server;
|
|
||||||
/**
|
|
||||||
* Share on the NFS server to put the OTF data on to
|
|
||||||
*/
|
|
||||||
private final String share;
|
|
||||||
/**
|
|
||||||
* SMB share to access the data written by the OTF C logic
|
|
||||||
*/
|
|
||||||
private final String smbShare;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag whether the actor of this loop should move in zig zag mode
|
|
||||||
*/
|
|
||||||
private final boolean zigZag;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bean holding all OTF channels and functionality.
|
|
||||||
*/
|
|
||||||
private OTFBean obean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of actions that are executed at the beginning of the loop.
|
|
||||||
*/
|
|
||||||
private List<Action> preActions;
|
|
||||||
/**
|
|
||||||
* List of actions that are executed at the end of the loop.
|
|
||||||
*/
|
|
||||||
private List<Action> postActions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Special OTF Actuator
|
|
||||||
*/
|
|
||||||
private OTFActuator actor = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of sensors of this loop
|
|
||||||
*/
|
|
||||||
private List<Sensor> sensors;
|
|
||||||
|
|
||||||
|
|
||||||
private List<Integer> dataIndexes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execution count of this loop. This count is used to determine the
|
|
||||||
* file name of the OTF file.
|
|
||||||
*/
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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(String channelPrefix, String server, String share, String smbShare, boolean zigZag){
|
|
||||||
|
|
||||||
// Initialize connection to the OTF records
|
|
||||||
try {
|
|
||||||
this.obean = new OTFBean();
|
|
||||||
ChannelBeanFactory.getFactory().createChannelBeans(obean, channelPrefix);
|
|
||||||
} catch (CAException 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store loop configuration
|
|
||||||
this.server = server;
|
|
||||||
this.share = share;
|
|
||||||
this.smbShare = smbShare;
|
|
||||||
this.zigZag = zigZag;
|
|
||||||
|
|
||||||
// Initialize lists used by the loop
|
|
||||||
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()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void execute() throws InterruptedException {
|
|
||||||
|
|
||||||
// Execute pre actions
|
|
||||||
for(Action action: preActions){
|
|
||||||
action.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start scan
|
|
||||||
obean.start();
|
|
||||||
|
|
||||||
// Wait for end of scan
|
|
||||||
obean.waitUntilStopped();
|
|
||||||
|
|
||||||
// Read data from file
|
|
||||||
collectData();
|
|
||||||
|
|
||||||
// Execute post actions
|
|
||||||
for(Action action: postActions){
|
|
||||||
action.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Issue end of loop control message
|
|
||||||
dataQueue.put(new EndOfStreamMessage(dataGroup));
|
|
||||||
|
|
||||||
// Increase execution count
|
|
||||||
executionCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ch.psi.fda.core.Action#abort()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void abort() {
|
|
||||||
// Abort otf scan logic
|
|
||||||
obean.abort();
|
|
||||||
|
|
||||||
abort=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ch.psi.fda.core.ActionLoop#prepare()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void prepare() {
|
|
||||||
executionCount = 0;
|
|
||||||
|
|
||||||
// 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>();
|
|
||||||
int channelCount =0;
|
|
||||||
for(Sensor s: sensors){
|
|
||||||
if(s instanceof OTFNamedChannelSensor){
|
|
||||||
// Monitored channel
|
|
||||||
OTFNamedChannelSensor so = (OTFNamedChannelSensor) s;
|
|
||||||
if(channelCount>=numberOfMonitoredChannels){
|
|
||||||
throw new IllegalArgumentException("Only up to "+numberOfMonitoredChannels+" channels can be monitored by OTF");
|
|
||||||
}
|
|
||||||
|
|
||||||
monitoredChannels.add(so.getName());
|
|
||||||
dataIndexes.add(2+numberOfScalerChannels+channelCount);
|
|
||||||
|
|
||||||
|
|
||||||
channelCount++;
|
|
||||||
}
|
|
||||||
else if (s instanceof OTFScalerChannelSensor){
|
|
||||||
OTFScalerChannelSensor so = (OTFScalerChannelSensor) s;
|
|
||||||
if(so.getIndex()>=numberOfScalerChannels){
|
|
||||||
throw new IllegalArgumentException("Scaler index must be between 0<=index<"+numberOfScalerChannels);
|
|
||||||
}
|
|
||||||
dataIndexes.add(2+so.getIndex()); // scalers follow directly after the readback
|
|
||||||
}
|
|
||||||
else if (s instanceof MillisecondTimestampSensor){
|
|
||||||
dataIndexes.add(2+numberOfScalerChannels+numberOfMonitoredChannels);
|
|
||||||
}
|
|
||||||
else if (s instanceof OTFReadbackSensor){
|
|
||||||
dataIndexes.add(1);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
throw new IllegalArgumentException("Sensor type "+s.getClass()+" is not supported by this loop");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set OTF parameters
|
|
||||||
try{
|
|
||||||
obean.resetToDefaults();
|
|
||||||
|
|
||||||
// Set actor properties
|
|
||||||
obean.setMotor(actor.getName());
|
|
||||||
obean.waitUntilMotorOk(timeout);
|
|
||||||
|
|
||||||
obean.setBegin(actor.getStart());
|
|
||||||
obean.setEnd(actor.getEnd());
|
|
||||||
obean.setStepSize(actor.getStepSize());
|
|
||||||
obean.setIntegrationTime(actor.getIntegrationTime());
|
|
||||||
|
|
||||||
// Override encoder if specified
|
|
||||||
if(actor.getReadback()!=null){
|
|
||||||
obean.setUseEncoder(true);
|
|
||||||
obean.setEncoder(actor.getReadback());
|
|
||||||
obean.waitUntilEncoderOk(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set user backlash
|
|
||||||
obean.setUserBacklash(actor.getAdditionalBacklash());
|
|
||||||
|
|
||||||
|
|
||||||
// NFS settings
|
|
||||||
obean.setNfsServer(server);
|
|
||||||
obean.setNfsShare(share);
|
|
||||||
|
|
||||||
obean.setFileNameGeneration(true);
|
|
||||||
obean.setAppendFile(false);
|
|
||||||
obean.setZigZag(zigZag); // Set ZigZag because there might be iterations
|
|
||||||
obean.setFileNameFormat("%06d"); // Force an update of the filename/counter by setting file format twice with different values
|
|
||||||
obean.setFileNameFormat("%06d.txt");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Set monitored channels
|
|
||||||
obean.setMonitoredChannels(monitoredChannels.toArray(new String[monitoredChannels.size()]));
|
|
||||||
}
|
|
||||||
catch(CAException e){
|
|
||||||
throw new RuntimeException("Unable to set OTF configuration parameters",e);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException("Unable to set OTF configuration parameters",e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Cleanup temporary directory
|
|
||||||
try{
|
|
||||||
DistributedFile tmpDir = new DistributedFile(smbShare);
|
|
||||||
if( !tmpDir.exists() || !tmpDir.isDirectory() ){
|
|
||||||
throw new RuntimeException("Cannot access OTF temporary directory "+tmpDir.getCanonicalPath());
|
|
||||||
}
|
|
||||||
DistributedFile[] files = tmpDir.listFiles();
|
|
||||||
|
|
||||||
for(int i=0;i<files.length;i++){
|
|
||||||
// Only delete item if it is not a directory and if it matches the given pattern.
|
|
||||||
if(files[i].isFile() && files[i].getName().matches("[0-9]+.txt")){
|
|
||||||
files[i].delete();
|
|
||||||
logger.fine("Delete file: "+files[i].getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(MalformedURLException e){
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException("Unable to access share (temporary files)",e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (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 {
|
|
||||||
ChannelBeanFactory.getFactory().destroyChannelBeans(obean);
|
|
||||||
} catch (CAException e) {
|
|
||||||
throw new RuntimeException("Unable to destroy channels",e);
|
|
||||||
} catch (InterruptedException 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
|
|
||||||
* @param tmpFile
|
|
||||||
*/
|
|
||||||
private void collectData() {
|
|
||||||
try{
|
|
||||||
final int timestampIndex = 2+numberOfScalerChannels+numberOfMonitoredChannels;
|
|
||||||
|
|
||||||
DistributedFile tmpFile = new DistributedFile(smbShare +"/"+ String.format("%06d.txt", executionCount));
|
|
||||||
logger.fine("Collect data from "+tmpFile.getCanonicalPath());
|
|
||||||
|
|
||||||
DistributedFile lockfile = new DistributedFile(tmpFile.getCanonicalPath() + ".lock");
|
|
||||||
|
|
||||||
logger.fine("Wait until file is written [lock file: "+lockfile.getCanonicalPath()+"]");
|
|
||||||
// Wait until file is created
|
|
||||||
while ((!tmpFile.exists()) || lockfile.exists()) {
|
|
||||||
Thread.sleep(500);
|
|
||||||
if(abort){
|
|
||||||
// If abort is issued while waiting for data immediately return without
|
|
||||||
// trying to read the data
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.fine("Read file " + tmpFile.getCanonicalPath());
|
|
||||||
InputStreamReader inreader = tmpFile.getInputStream();
|
|
||||||
BufferedReader in = new BufferedReader(inreader);
|
|
||||||
String line;
|
|
||||||
boolean firstline = true;
|
|
||||||
while (true) {
|
|
||||||
line = in.readLine();
|
|
||||||
if (line == null) {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
if(line.matches("^\\[.*")){
|
|
||||||
// Skip header lines
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if(firstline){
|
|
||||||
firstline=false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataMessage message = new DataMessage();
|
|
||||||
// Add data to dataset
|
|
||||||
String[] tokens = line.split("\t");
|
|
||||||
|
|
||||||
for(Integer i: dataIndexes){
|
|
||||||
try{
|
|
||||||
if(i == timestampIndex) {
|
|
||||||
// Calculate time in milliseconds
|
|
||||||
Double seconds = new Double(tokens[i]);
|
|
||||||
Double nanoseconds = new Double(tokens[i+1]);
|
|
||||||
|
|
||||||
Double v = seconds*1000+Math.floor(nanoseconds*0.000001);
|
|
||||||
message.getData().add(v);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
message.getData().add(new Double(tokens[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(NumberFormatException e){
|
|
||||||
logger.warning("Cannot parse component ["+tokens[i]+"] from source file - will add 0 for this component");
|
|
||||||
message.getData().add(new Double(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dataQueue.put(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
in.close();
|
|
||||||
inreader.close();
|
|
||||||
} catch(InterruptedException e){
|
|
||||||
throw new RuntimeException("An interrupt occured while waiting for the file to show up",e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException("An IO Exception occured while reading the OTF data file",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,157 +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.loops.cr;
|
|
||||||
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
import ch.psi.jcae.annotation.CaChannel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class CrlogicChannelsTemplate {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =":TPS")
|
|
||||||
private ChannelBean<Integer> ticksPerSecond;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status of the OTFSCAN IOC logic
|
|
||||||
*/
|
|
||||||
@CaChannel(type=String.class, name =":STATUS")
|
|
||||||
private ChannelBean<String> status;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message from the OTFSCAN IOC logic
|
|
||||||
*/
|
|
||||||
@CaChannel(type=String.class, name =":MSG")
|
|
||||||
private ChannelBean<String> message;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IOC ticks between data acquisition interrupts
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =":TBINT")
|
|
||||||
private ChannelBean<Integer> ticksBetweenInterrupts;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name or ip address of the NFS server to save the data to
|
|
||||||
* (depending on the IOC setup)
|
|
||||||
*/
|
|
||||||
@CaChannel(type=String.class, name =":NFSSE")
|
|
||||||
private ChannelBean<String> nfsServer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the NFS share on the NFS server
|
|
||||||
*/
|
|
||||||
@CaChannel(type=String.class, name =":NFSSH")
|
|
||||||
private ChannelBean<String> nfsShare;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the data file
|
|
||||||
*/
|
|
||||||
@CaChannel(type=String.class, name =":DFNAM")
|
|
||||||
private ChannelBean<String> dataFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag to identify whether the data file should be appended
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Boolean.class, name =":FAPPE")
|
|
||||||
private ChannelBean<Boolean> appendFile;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Readout resources
|
|
||||||
*/
|
|
||||||
@CaChannel(type=String[].class, name =":RRES")
|
|
||||||
private ChannelBean<String[]> readoutResources;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the ticksPerSecond
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getTicksPerSecond() {
|
|
||||||
return ticksPerSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the status
|
|
||||||
*/
|
|
||||||
public ChannelBean<String> getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the message
|
|
||||||
*/
|
|
||||||
public ChannelBean<String> getMessage() {
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the ticksBetweenInterrupts
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getTicksBetweenInterrupts() {
|
|
||||||
return ticksBetweenInterrupts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the nfsServer
|
|
||||||
*/
|
|
||||||
public ChannelBean<String> getNfsServer() {
|
|
||||||
return nfsServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the nfsShare
|
|
||||||
*/
|
|
||||||
public ChannelBean<String> getNfsShare() {
|
|
||||||
return nfsShare;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the dataFile
|
|
||||||
*/
|
|
||||||
public ChannelBean<String> getDataFile() {
|
|
||||||
return dataFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the appendFile
|
|
||||||
*/
|
|
||||||
public ChannelBean<Boolean> getAppendFile() {
|
|
||||||
return appendFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the readoutResources
|
|
||||||
*/
|
|
||||||
public ChannelBean<String[]> getReadoutResources() {
|
|
||||||
return readoutResources;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,898 +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.loops.cr;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
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.Semaphore;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import jcifs.smb.SmbFile;
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
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.jcae.ChannelBeanFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
* While using Crlogic the IOC system clock rate should/must be set to 1000 (default 60)
|
|
||||||
*
|
|
||||||
* sysClkRateSet 1000
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class CrlogicLoop implements ActionLoop {
|
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
private static final Logger logger = Logger.getLogger(CrlogicLoop.class.getName());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag to indicate whether the data of this loop will be grouped
|
|
||||||
* According to this flag the dataGroup flag in EndOfStream will be set.
|
|
||||||
*/
|
|
||||||
private boolean dataGroup = false;
|
|
||||||
|
|
||||||
private boolean keepTmpFiles = false;
|
|
||||||
|
|
||||||
private BlockingQueue<String> readQueue = new LinkedBlockingQueue<String>();
|
|
||||||
private volatile boolean stopReadoutThread = false;
|
|
||||||
private Thread readoutThread;
|
|
||||||
|
|
||||||
// Constants
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default timeout (in milliseconds) for wait operations
|
|
||||||
*/
|
|
||||||
private long startStopTimeout = 8000;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the NFS server to place the data of the OTF logic
|
|
||||||
*/
|
|
||||||
private final String server;
|
|
||||||
/**
|
|
||||||
* Share on the NFS server to put the OTF data on to
|
|
||||||
*/
|
|
||||||
private final String share;
|
|
||||||
/**
|
|
||||||
* SMB share to access the data written by the OTF C logic
|
|
||||||
*/
|
|
||||||
private final String smbShare;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag whether the actor of this loop should move in zig zag mode
|
|
||||||
*/
|
|
||||||
private final boolean zigZag;
|
|
||||||
|
|
||||||
boolean useReadback;
|
|
||||||
boolean useEncoder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of actions that are executed at the beginning of the loop.
|
|
||||||
*/
|
|
||||||
private List<Action> preActions;
|
|
||||||
/**
|
|
||||||
* List of actions that are executed at the end of the loop.
|
|
||||||
*/
|
|
||||||
private List<Action> postActions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prefix for the CRLOGIC channels
|
|
||||||
*/
|
|
||||||
private String prefix;
|
|
||||||
|
|
||||||
private CrlogicChannelsTemplate template;
|
|
||||||
private MotorChannelsTemplate 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<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
|
|
||||||
*/
|
|
||||||
private boolean abort = false;
|
|
||||||
private boolean abortForce = false;
|
|
||||||
private Thread executionThread = null;
|
|
||||||
|
|
||||||
|
|
||||||
public CrlogicLoop(String prefix, String server, String share, String smbShare, boolean zigZag){
|
|
||||||
this.prefix = prefix;
|
|
||||||
this.server = server;
|
|
||||||
this.share = share;
|
|
||||||
this.smbShare = smbShare;
|
|
||||||
this.zigZag = zigZag;
|
|
||||||
|
|
||||||
// Initialize lists used by the loop
|
|
||||||
this.preActions = new ArrayList<Action>();
|
|
||||||
this.postActions = new ArrayList<Action>();
|
|
||||||
this.sensors = new ArrayList<Sensor>();
|
|
||||||
this.readoutResources = new ArrayList<String>();
|
|
||||||
this.scalerIndices = new HashMap<Integer, CrlogicDeltaDataFilter>();
|
|
||||||
|
|
||||||
this.crlogicDataFilter = new CrlogicRangeDataFilter();
|
|
||||||
this.dataQueue = new LinkedBlockingQueue<Message>(2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collect data from share
|
|
||||||
* @param tmpFileName Name of the temporary file
|
|
||||||
* @throws InterruptedException
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private void collectData(String tmpDir, String tmpFileName) throws InterruptedException, IOException {
|
|
||||||
semaphore.acquire();
|
|
||||||
if (tmpDir.startsWith("smb:")) {
|
|
||||||
|
|
||||||
SmbFile tmpFile = new SmbFile(tmpDir, tmpFileName);
|
|
||||||
logger.info("Collect data from " + tmpFile.getCanonicalPath());
|
|
||||||
|
|
||||||
SmbFile lockfile = new SmbFile(tmpFile.getCanonicalPath() + ".lock");
|
|
||||||
|
|
||||||
logger.info("Wait until file is written [lock file: " + lockfile.getCanonicalPath() + "]");
|
|
||||||
// Wait until file is created
|
|
||||||
while ((!tmpFile.exists()) || lockfile.exists()) {
|
|
||||||
try{
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
catch(InterruptedException e){
|
|
||||||
abort=true;
|
|
||||||
}
|
|
||||||
if(abort){
|
|
||||||
// If abort is issued while waiting for data immediately return without
|
|
||||||
// trying to read the data
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InputStreamReader inreader = new InputStreamReader(tmpFile.getInputStream());
|
|
||||||
BufferedReader in = new BufferedReader(inreader);
|
|
||||||
String line;
|
|
||||||
boolean firstline = true;
|
|
||||||
int linecount=0;
|
|
||||||
int mcounter=0;
|
|
||||||
|
|
||||||
// boolean wasInRangeBefore = false;
|
|
||||||
boolean discardAnyway = false;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
line = in.readLine();
|
|
||||||
linecount++;
|
|
||||||
if (line == null) {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// if(line.matches("^\\[.*")){
|
|
||||||
if (line.matches("^ *#.*")) {
|
|
||||||
// Skip header/comment lines
|
|
||||||
// logger.info("HEADER: " + line);
|
|
||||||
} else {
|
|
||||||
if (firstline) {
|
|
||||||
firstline = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// logger.info(line);
|
|
||||||
|
|
||||||
// Write into queue
|
|
||||||
DataMessage message = new DataMessage();
|
|
||||||
String[] tokens = line.split("\t");
|
|
||||||
boolean use = true;
|
|
||||||
|
|
||||||
for(int i=0;i<tokens.length;i++){
|
|
||||||
String t = tokens[i];
|
|
||||||
Double val;
|
|
||||||
|
|
||||||
if(i==0){
|
|
||||||
Double raw = new Double(t);
|
|
||||||
|
|
||||||
if(useEncoder){
|
|
||||||
val = crlogicDataFilter.calculatePositionMotorUseEncoder(raw);
|
|
||||||
}
|
|
||||||
else if(useReadback){
|
|
||||||
val = crlogicDataFilter.calculatePositionMotorUseReadback(raw);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
val = crlogicDataFilter.calculatePositionMotor(raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether data is within the configured range - otherwise drop data
|
|
||||||
use = crlogicDataFilter.filter(val);
|
|
||||||
// if(!use){
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
else if(scalerIndices.containsKey(i)){
|
|
||||||
CrlogicDeltaDataFilter f = scalerIndices.get(i);
|
|
||||||
val = f.delta(new Double(t));
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
val = new Double(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
message.getData().add(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Does not work if zigzag, ...
|
|
||||||
// // Use this to filter out motor retry movements at the end of the scan
|
|
||||||
// wasInRangeBefore = wasInRangeBefore | use;
|
|
||||||
// if(!use && wasInRangeBefore){
|
|
||||||
// discardAnyway=true;
|
|
||||||
// // Optimization - terminate read loop once range is left
|
|
||||||
// logger.info("Terminate read loop because point is outside range");
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Filter data
|
|
||||||
if(use && !discardAnyway){
|
|
||||||
dataQueue.put(message);
|
|
||||||
mcounter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
in.close();
|
|
||||||
inreader.close();
|
|
||||||
|
|
||||||
logger.info("Lines read: "+linecount+" Messages generated (after filtering): "+mcounter);
|
|
||||||
|
|
||||||
// Remove temporary file
|
|
||||||
if(!keepTmpFiles){
|
|
||||||
tmpFile.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// TODO - File in local file system
|
|
||||||
}
|
|
||||||
|
|
||||||
// Issue end of loop control message
|
|
||||||
dataQueue.put(new EndOfStreamMessage(dataGroup));
|
|
||||||
semaphore.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ch.psi.fda.core.Action#execute()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
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());
|
|
||||||
|
|
||||||
// Reset data filter
|
|
||||||
for(Integer k: scalerIndices.keySet()){
|
|
||||||
scalerIndices.get(k).reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized(this){
|
|
||||||
// Set abort state to false
|
|
||||||
abort = false;
|
|
||||||
abortForce = false;
|
|
||||||
|
|
||||||
// Set execution thread to current thread
|
|
||||||
executionThread = Thread.currentThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// TODO each actuator will result in an additional sensor (at the beginning)
|
|
||||||
// Dependent on actuator settings (readback use encoder, ...)
|
|
||||||
|
|
||||||
|
|
||||||
// TODO filename generation?
|
|
||||||
final String tmpFileName = "tmp-"+System.currentTimeMillis()+".txt";
|
|
||||||
|
|
||||||
Long timeout = 600000l; // 10 minutes move timeout
|
|
||||||
|
|
||||||
// Check if logic is inactive, otherwise return early
|
|
||||||
if(!template.getStatus().getValue().equals(CrlogicChannelsTemplate.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 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());
|
|
||||||
}
|
|
||||||
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{
|
|
||||||
throw new RuntimeException("CRLOGIC is not inactive");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
logger.info("Set parameters");
|
|
||||||
template.getNfsServer().setValue(server);
|
|
||||||
template.getNfsShare().setValue(share);
|
|
||||||
template.getDataFile().setValue(tmpFileName);
|
|
||||||
|
|
||||||
int tps = template.getTicksPerSecond().getValue();
|
|
||||||
logger.info("Ticks per second: "+tps);
|
|
||||||
|
|
||||||
logger.info("Set readout resources");
|
|
||||||
|
|
||||||
template.getReadoutResources().setValue(readoutResources.toArray(new String[readoutResources.size()]));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Set ticks between interrupt to integration time
|
|
||||||
int ticks = (int)(tps*integrationTime);
|
|
||||||
template.getTicksBetweenInterrupts().setValue(ticks);
|
|
||||||
|
|
||||||
// Prepare motor
|
|
||||||
double totalTimeSeconds = Math.abs((end-start)/stepSize*integrationTime);
|
|
||||||
int hours = (int) Math.floor(totalTimeSeconds/60/60);
|
|
||||||
int minutes = (int) Math.floor(totalTimeSeconds/60-hours*60);
|
|
||||||
int seconds = (int) Math.floor(totalTimeSeconds-hours*60*60-minutes*60);
|
|
||||||
|
|
||||||
logger.info("Estimated time: "+hours+":"+minutes+":"+seconds);
|
|
||||||
|
|
||||||
int direction = 1;
|
|
||||||
if(end-start<0){
|
|
||||||
direction = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
double motorBaseSpeed = motortemplate.getBaseSpeed().getValue();
|
|
||||||
double motorHighLimit = motortemplate.getHighLimit().getValue();
|
|
||||||
double motorLowLimit = motortemplate.getLowLimit().getValue();
|
|
||||||
double motorBacklash = motortemplate.getBacklashDistance().getValue();
|
|
||||||
|
|
||||||
boolean respectMotorMinSpeed = false; // if false set min speed to 0
|
|
||||||
double motorMinSpeed = 0;
|
|
||||||
if(respectMotorMinSpeed){
|
|
||||||
motorMinSpeed = motorBaseSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check user parameters
|
|
||||||
// TODO start and end values must be between the motor high and low value - otherwise fail
|
|
||||||
if(start>motorHighLimit || start<motorLowLimit){
|
|
||||||
// Start value is outside motor high and/or low value
|
|
||||||
logger.info("Start value is outside motor high and/or low value");
|
|
||||||
throw new IllegalArgumentException("Start value is outside motor high and/or low value");
|
|
||||||
}
|
|
||||||
if(end>motorHighLimit || end<motorLowLimit){
|
|
||||||
// End value is outside motor high and/or low value
|
|
||||||
logger.info("End value is outside motor high and/or low value");
|
|
||||||
throw new IllegalArgumentException("End value is outside motor high and/or low value");
|
|
||||||
}
|
|
||||||
// TODO Check minimum step size
|
|
||||||
int minimumTicks = 10;
|
|
||||||
double minStepSize = motorMinSpeed*(minimumTicks/tps);
|
|
||||||
if(stepSize<minStepSize){
|
|
||||||
// Step size is too small
|
|
||||||
logger.info("Step size is too small");
|
|
||||||
throw new IllegalArgumentException("Step size is too small");
|
|
||||||
}
|
|
||||||
// TODO Check integration time
|
|
||||||
if(motorMinSpeed>0){
|
|
||||||
double maxIntegrationTime = stepSize/motorMinSpeed;
|
|
||||||
if(integrationTime>maxIntegrationTime){
|
|
||||||
logger.info("Integration time is too big");
|
|
||||||
// Integration time is too big
|
|
||||||
throw new IllegalArgumentException("Integration time is too big");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
double motorMaxSpeed = motortemplate.getVelocity().getValue();
|
|
||||||
double minIntegrationTime = Math.min( (stepSize/motorMaxSpeed), ((double)minimumTicks/(double)tps) );
|
|
||||||
if(integrationTime<minIntegrationTime){
|
|
||||||
// Integration time is too small
|
|
||||||
logger.info("Integration time is too small [min integration time: "+minIntegrationTime+"]");
|
|
||||||
throw new IllegalArgumentException("Integration time is too small [min integration time: "+minIntegrationTime+"]");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// TODO Calculate and set motor speed, backlash, etc.
|
|
||||||
double motorSpeed = stepSize/integrationTime;
|
|
||||||
double backlash = (0.5*motorSpeed*motortemplate.getAccelerationTime().getValue())+motorBacklash+ubacklash;
|
|
||||||
double realEnd = end+(backlash*direction);
|
|
||||||
double realStart = start-(backlash*direction);
|
|
||||||
|
|
||||||
|
|
||||||
// Move to start
|
|
||||||
logger.info("Move motor to start ["+realStart+"]");
|
|
||||||
motortemplate.getSetValue().setValue(realStart, timeout); // Will block until move is done
|
|
||||||
|
|
||||||
|
|
||||||
// Set motor paramters
|
|
||||||
// Backup settings
|
|
||||||
logger.info("Backup motor settings");
|
|
||||||
double backupSpeed = motortemplate.getVelocity().getValue();
|
|
||||||
double backupBacklash = motorBacklash;
|
|
||||||
double backupMinSpeed = motorBaseSpeed;
|
|
||||||
|
|
||||||
try{
|
|
||||||
// Set motor settings
|
|
||||||
logger.info("Update motor settings");
|
|
||||||
// if(!respectMotorMinSpeed){
|
|
||||||
// motortemplate.getBaseSpeed().setValue(0d);
|
|
||||||
// }
|
|
||||||
// Set base speed as fast as possible but not faster than the original base speed.
|
|
||||||
double base = motorBaseSpeed;
|
|
||||||
if(motorSpeed<base){
|
|
||||||
base = motorSpeed;
|
|
||||||
}
|
|
||||||
motortemplate.getBaseSpeed().setValue(base);
|
|
||||||
motortemplate.getVelocity().setValue(motorSpeed);
|
|
||||||
motortemplate.getBacklashDistance().setValue(0d);
|
|
||||||
|
|
||||||
|
|
||||||
// Execute pre actions
|
|
||||||
for(Action action: preActions){
|
|
||||||
action.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Start crlogic logic
|
|
||||||
logger.info("Start CRLOGIC");
|
|
||||||
template.getStatus().setValue(CrlogicChannelsTemplate.Status.INITIALIZE.toString());
|
|
||||||
try{
|
|
||||||
template.getStatus().waitForValue(CrlogicChannelsTemplate.Status.ACTIVE.toString(), startStopTimeout);
|
|
||||||
}
|
|
||||||
catch(CAException e){
|
|
||||||
logger.info( "Failed to start CRLOGIC. Logic in status: "+template.getStatus().getValue() );
|
|
||||||
if(template.getStatus().getValue().equals(CrlogicChannelsTemplate.Status.FAULT.toString())){
|
|
||||||
logger.info("Error message: "+template.getMessage().getValue());
|
|
||||||
}
|
|
||||||
// Recover to inactive
|
|
||||||
template.getStatus().setValue(CrlogicChannelsTemplate.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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move motor(s) to end / wait until motor is stopped
|
|
||||||
logger.info("Move motor to end ["+realEnd+"]");
|
|
||||||
try{
|
|
||||||
motortemplate.getSetValue().setValue(realEnd, timeout); // Will block until move is done
|
|
||||||
}
|
|
||||||
catch (InterruptedException e) {
|
|
||||||
if(abort & (!abortForce)){
|
|
||||||
// Abort motor move
|
|
||||||
motortemplate.getCommand().setValue(MotorChannelsTemplate.Commands.Stop.ordinal());
|
|
||||||
motortemplate.getCommand().setValue(MotorChannelsTemplate.Commands.Go.ordinal());
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.info("Motor reached end position");
|
|
||||||
|
|
||||||
// Stop crlogic logic
|
|
||||||
logger.info("Stop CRLOGIC");
|
|
||||||
template.getStatus().setValue(CrlogicChannelsTemplate.Status.STOP.toString());
|
|
||||||
// Wait until stopped
|
|
||||||
logger.info("Wait until stopped");
|
|
||||||
try{
|
|
||||||
template.getStatus().waitForValue(CrlogicChannelsTemplate.Status.INACTIVE.toString(), startStopTimeout);
|
|
||||||
}
|
|
||||||
catch(CAException 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);
|
|
||||||
}
|
|
||||||
logger.info("CRLOGIC is now stopped");
|
|
||||||
|
|
||||||
|
|
||||||
// Execute post actions
|
|
||||||
for(Action action: postActions){
|
|
||||||
action.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
logger.info("Restore motor settings");
|
|
||||||
motortemplate.getBaseSpeed().setValue(backupMinSpeed);
|
|
||||||
motortemplate.getVelocity().setValue(backupSpeed);
|
|
||||||
motortemplate.getBacklashDistance().setValue(backupBacklash);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized(this){
|
|
||||||
executionThread = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(CAException e){
|
|
||||||
throw new RuntimeException("Unable to execute crloop", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (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;
|
|
||||||
|
|
||||||
// executionThread variable guarded by "this"
|
|
||||||
if(executionThread != null){
|
|
||||||
executionThread.interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ch.psi.fda.core.Action#destroy()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void destroy() {
|
|
||||||
stopReadoutThread = true;
|
|
||||||
readoutThread.interrupt();
|
|
||||||
// TODO eventually interrupt readout thread
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
ChannelBeanFactory.getFactory().destroyChannelBeans(template);
|
|
||||||
ChannelBeanFactory.getFactory().destroyChannelBeans(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() {
|
|
||||||
|
|
||||||
stopReadoutThread = false;
|
|
||||||
// Start readout Thread
|
|
||||||
readoutThread = new Thread(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
while(!stopReadoutThread){
|
|
||||||
String file;
|
|
||||||
try {
|
|
||||||
file = readQueue.take();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// TODO Read file and
|
|
||||||
try {
|
|
||||||
collectData(smbShare, file);
|
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
readoutThread.start();
|
|
||||||
|
|
||||||
try{
|
|
||||||
// Connect crlogic channels
|
|
||||||
template = new CrlogicChannelsTemplate();
|
|
||||||
logger.info("Connect channels");
|
|
||||||
ChannelBeanFactory.getFactory().createChannelBeans(template, prefix);
|
|
||||||
|
|
||||||
// Connect motor channels
|
|
||||||
motortemplate = new MotorChannelsTemplate();
|
|
||||||
ChannelBeanFactory.getFactory().createChannelBeans(motortemplate, actuator.getName());
|
|
||||||
|
|
||||||
useReadback = motortemplate.getUseReadback().getValue();
|
|
||||||
useEncoder = motortemplate.getUseEncoder().getValue();
|
|
||||||
|
|
||||||
logger.info("Motor type: "+ MotorChannelsTemplate.Type.values()[motortemplate.getType().getValue()]);
|
|
||||||
logger.info("Motor use readback: "+useReadback);
|
|
||||||
logger.info("Motor use encoder: "+useEncoder);
|
|
||||||
|
|
||||||
// TODO build up list of readout resources (based on sensors)
|
|
||||||
readoutResources.clear();
|
|
||||||
// first sensor is the actuator
|
|
||||||
|
|
||||||
// Determine mode of motor
|
|
||||||
if((!useReadback) && (!useEncoder)){
|
|
||||||
// Open loop
|
|
||||||
if(actuator.getReadback()!=null){
|
|
||||||
throw new IllegalArgumentException("Readback not supported if motor is configured in open loop");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
readoutResources.add(actuator.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else if(useReadback && (!useEncoder)){
|
|
||||||
String readback;
|
|
||||||
// use readback link
|
|
||||||
if(actuator.getReadback()!=null){
|
|
||||||
// Use specified readback
|
|
||||||
readback = (actuator.getReadback());
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// Set resouce to readback link
|
|
||||||
readback = (motortemplate.getReadbackLink().getValue());
|
|
||||||
readback = readback.replaceAll(" +.*", ""); // remove NPP etc at the end
|
|
||||||
}
|
|
||||||
|
|
||||||
readoutResources.add(readback);
|
|
||||||
|
|
||||||
// Fill readback encoder settings
|
|
||||||
// Connect to encoder
|
|
||||||
EncoderChannelsTemplate encodertemplate = new EncoderChannelsTemplate();
|
|
||||||
ChannelBeanFactory.getFactory().createChannelBeans(encodertemplate, readback);
|
|
||||||
|
|
||||||
// Read encoder settings
|
|
||||||
if(encodertemplate.getDirection().getValue()==EncoderChannelsTemplate.Direction.Positive.ordinal()){
|
|
||||||
crlogicDataFilter.setEncoderDirection(1);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
crlogicDataFilter.setEncoderDirection(-1);
|
|
||||||
}
|
|
||||||
crlogicDataFilter.setEncoderOffset(encodertemplate.getOffset().getValue());
|
|
||||||
crlogicDataFilter.setEncoderResolution(encodertemplate.getResolution().getValue());
|
|
||||||
|
|
||||||
// Disconnect from encoder
|
|
||||||
ChannelBeanFactory.getFactory().destroyChannelBeans(encodertemplate);
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (useEncoder && (!useReadback)){
|
|
||||||
// use readback link
|
|
||||||
if(actuator.getReadback()!=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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
throw new IllegalArgumentException("Motor configuration not supportet: use readback - "+useReadback+" use encoder - "+useEncoder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill Motor specific settings
|
|
||||||
if(motortemplate.getDirection().getValue()==MotorChannelsTemplate.Direction.Positive.ordinal()){
|
|
||||||
crlogicDataFilter.setMotorDirection(1);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
crlogicDataFilter.setMotorDirection(-1);
|
|
||||||
}
|
|
||||||
crlogicDataFilter.setMotorEncoderResolution(motortemplate.getEncoderResolution().getValue());
|
|
||||||
crlogicDataFilter.setMotorOffset(motortemplate.getOffset().getValue());
|
|
||||||
crlogicDataFilter.setMotorReadbackResolution(motortemplate.getReadbackResolution().getValue());
|
|
||||||
crlogicDataFilter.setMotorResolution(motortemplate.getMotorResolution().getValue());
|
|
||||||
|
|
||||||
// Clear all indices
|
|
||||||
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());
|
|
||||||
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++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Workaround - somehow one has to add an empty thing to the value otherwise the c logic
|
|
||||||
// does not pick up the end
|
|
||||||
readoutResources.add("");
|
|
||||||
}
|
|
||||||
catch(Exception e){
|
|
||||||
throw new RuntimeException("Unable to prepare crloop: ",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (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() {
|
|
||||||
// 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() {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,652 +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.loops.cr;
|
|
||||||
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
import ch.psi.jcae.annotation.CaChannel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class MotorChannelsTemplate {
|
|
||||||
|
|
||||||
public enum Type {SOFT_CHANNEL, MOTOR_SIMULATION, OMS_VME58, OMS_MAXv};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ## Drive section ##
|
|
||||||
* # User coordinates #
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .HLM High limit - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".HLM")
|
|
||||||
private ChannelBean<Double> highLimit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .LLM Low limit - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".LLM")
|
|
||||||
private ChannelBean<Double> lowLimit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .RBV Readback value - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".RBV", monitor=true)
|
|
||||||
private ChannelBean<Double> readbackValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .VAL Set value - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".VAL", monitor=true)
|
|
||||||
private ChannelBean<Double> setValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .RLV Relative move value - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".RLV")
|
|
||||||
private ChannelBean<Double> relativeMoveValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .TWV Teak value - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".TWV")
|
|
||||||
private ChannelBean<Double> tweakValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .TWR Tweak reverse - move left - int
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =".TWR")
|
|
||||||
private ChannelBean<Integer> tweakReverse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .TWF Tweak forward - move right - int
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =".TWF")
|
|
||||||
private ChannelBean<Integer> tweakForward;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .JOGR Jog reverse - int
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =".JOGR")
|
|
||||||
private ChannelBean<Integer> jogReverse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .JOGF Jog forward - int
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =".JOGF")
|
|
||||||
private ChannelBean<Integer> jogForward;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .HOMR Home reverse - int
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =".HOMR")
|
|
||||||
private ChannelBean<Integer> homeReverse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .HOMF Home forward - int
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =".HOMF")
|
|
||||||
private ChannelBean<Integer> homeForward;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .EGU Engineering unit - String
|
|
||||||
*/
|
|
||||||
@CaChannel(type=String.class, name =".EGU")
|
|
||||||
private ChannelBean<String> engineeringUnit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .DTYP Type - String (e.g. "OMS MAXv") see enum Type
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =".DTYP")
|
|
||||||
private ChannelBean<Integer> type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .DESC Description - String
|
|
||||||
*/
|
|
||||||
@CaChannel(type=String.class, name =".DESC")
|
|
||||||
private ChannelBean<String> description;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* # Dial coordinates #
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .DHLM Dial high limit - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".DHLM")
|
|
||||||
private ChannelBean<Double> dialHighLimit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .DLLM Dial low limit - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".DLLM")
|
|
||||||
private ChannelBean<Double> dialLowLimit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .DRBV Dial readback value - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".DRBV", monitor=true)
|
|
||||||
private ChannelBean<Double> dialReadbackValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .DVAL Dial set value - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".DVAL", monitor=true)
|
|
||||||
private ChannelBean<Double> dialSetValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .RVAL Raw value - int
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =".RVAL", monitor=true)
|
|
||||||
private ChannelBean<Integer> rawValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .RRBV Raw readback value - int
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =".RRBV", monitor=true)
|
|
||||||
private ChannelBean<Integer> rawReadbackValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .SPMG Stop/Pause/Move/Go - (0:"Stop", 1:"Pause", 2:"Move", 3:"Go") - 3
|
|
||||||
*/
|
|
||||||
public enum Commands { Stop, Pause, Move, Go };
|
|
||||||
@CaChannel(type=Integer.class, name =".SPMG")
|
|
||||||
private ChannelBean<Integer> command;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ## Calibration section ##
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .SET Set/Use Switch - (0:"Use", 1:"Set") - 0
|
|
||||||
*/
|
|
||||||
public enum Calibration {Use, Set};
|
|
||||||
@CaChannel(type=Integer.class, name =".SET")
|
|
||||||
private ChannelBean<Integer> calibration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .OFF User offset (EGU) - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".OFF")
|
|
||||||
private ChannelBean<Double> offset;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .FOFF Offset-Freeze Switch - (0:"Variable", 1:"Frozen") - 1
|
|
||||||
*/
|
|
||||||
public enum OffsetMode {Variable, Frozen};
|
|
||||||
@CaChannel(type=Integer.class, name =".FOFF")
|
|
||||||
private ChannelBean<Integer> offsetMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .DIR User direction - (0:"Pos", 1:"Neg")
|
|
||||||
*/
|
|
||||||
public enum Direction {Positive, Negative};
|
|
||||||
@CaChannel(type=Integer.class, name =".DIR")
|
|
||||||
private ChannelBean<Integer> direction;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ## Dynamics ##
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .VELO Velocity (EGU/s) - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".VELO")
|
|
||||||
private ChannelBean<Double> velocity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .BVEL Backlash velocity (EGU/s) - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".BVEL")
|
|
||||||
private ChannelBean<Double> backlashVelocity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .VBAS Base speed (EGU/s) - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".VBAS")
|
|
||||||
private ChannelBean<Double> baseSpeed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .ACCL Acceleration time / seconds to velocity - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".ACCL")
|
|
||||||
private ChannelBean<Double> accelerationTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .BACC Backlash acceleration time / seconds to velocity - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".BACC")
|
|
||||||
private ChannelBean<Double> backlashAccelerationTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .BDST Backlash distance (EGU) - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".BDST")
|
|
||||||
private ChannelBean<Double> backlashDistance;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .FRAC Move fraction - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".FRAC")
|
|
||||||
private ChannelBean<Double> moveFracion;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ## Resolution ##
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .MRES Motor resolution - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".MRES")
|
|
||||||
private ChannelBean<Double> motorResolution;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .ERES Encoder resolution - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".ERES")
|
|
||||||
private ChannelBean<Double> encoderResolution;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .RRES Readback resolution - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".RRES")
|
|
||||||
private ChannelBean<Double> readbackResolution;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .RDBD Retry deadband (EGU) - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".RDBD")
|
|
||||||
private ChannelBean<Double> retryDeadband;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .RTRY Max retry count - int
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =".RTRY")
|
|
||||||
private ChannelBean<Integer> maxRetryCount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .RCNT Retry count - int
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =".RCNT", monitor=true)
|
|
||||||
private ChannelBean<Integer> retryCount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .UEIP Use encoder (if present) - (0:"No", 1:"Yes")
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Boolean.class, name =".UEIP")
|
|
||||||
private ChannelBean<Boolean> useEncoder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .URIP Use readback link (if present) - (0:"No", 1:"Yes")
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Boolean.class, name =".URIP")
|
|
||||||
private ChannelBean<Boolean> useReadback;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .DLY Readback delay (s) - double
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Double.class, name =".DLY")
|
|
||||||
private ChannelBean<Double> readbackDelay;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .RDBL Readback link - String
|
|
||||||
*/
|
|
||||||
@CaChannel(type=String.class, name =".RDBL")
|
|
||||||
private ChannelBean<String> readbackLink;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .OMSL Output mode select - (0:"supervisory", 1:"closed_loop")
|
|
||||||
*/
|
|
||||||
public enum OutputMode {Supervisory, Closed_Loop};
|
|
||||||
@CaChannel(type=Integer.class, name =".OMSL")
|
|
||||||
private ChannelBean<Integer> outputMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ## Status ##
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* .DMOV Done move - int
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Boolean.class, name =".DMOV", monitor=true)
|
|
||||||
private ChannelBean<Boolean> moveDone;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the highLimit
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getHighLimit() {
|
|
||||||
return highLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the lowLimit
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getLowLimit() {
|
|
||||||
return lowLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the readbackValue
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getReadbackValue() {
|
|
||||||
return readbackValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the setValue
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getSetValue() {
|
|
||||||
return setValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the relativeMoveValue
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getRelativeMoveValue() {
|
|
||||||
return relativeMoveValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the tweakValue
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getTweakValue() {
|
|
||||||
return tweakValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the tweakReverse
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getTweakReverse() {
|
|
||||||
return tweakReverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the tweakForward
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getTweakForward() {
|
|
||||||
return tweakForward;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the jogReverse
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getJogReverse() {
|
|
||||||
return jogReverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the jogForward
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getJogForward() {
|
|
||||||
return jogForward;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the homeReverse
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getHomeReverse() {
|
|
||||||
return homeReverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the homeForward
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getHomeForward() {
|
|
||||||
return homeForward;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the engineeringUnit
|
|
||||||
*/
|
|
||||||
public ChannelBean<String> getEngineeringUnit() {
|
|
||||||
return engineeringUnit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the type
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the description
|
|
||||||
*/
|
|
||||||
public ChannelBean<String> getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the dialHighLimit
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getDialHighLimit() {
|
|
||||||
return dialHighLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the dialLowLimit
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getDialLowLimit() {
|
|
||||||
return dialLowLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the dialReadbackValue
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getDialReadbackValue() {
|
|
||||||
return dialReadbackValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the dialSetValue
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getDialSetValue() {
|
|
||||||
return dialSetValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the rawValue
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getRawValue() {
|
|
||||||
return rawValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the rawReadbackValue
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getRawReadbackValue() {
|
|
||||||
return rawReadbackValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the command
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getCommand() {
|
|
||||||
return command;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the calibration
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getCalibration() {
|
|
||||||
return calibration;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the userOffset
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getOffset() {
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the offsetMode
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getOffsetMode() {
|
|
||||||
return offsetMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the direction
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getDirection() {
|
|
||||||
return direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the velocity
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getVelocity() {
|
|
||||||
return velocity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the backlashVelocity
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getBacklashVelocity() {
|
|
||||||
return backlashVelocity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the baseSpeed
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getBaseSpeed() {
|
|
||||||
return baseSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the accelerationTime
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getAccelerationTime() {
|
|
||||||
return accelerationTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the backlashAccelerationTime
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getBacklashAccelerationTime() {
|
|
||||||
return backlashAccelerationTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the backlashDistance
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getBacklashDistance() {
|
|
||||||
return backlashDistance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the moveFracion
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getMoveFracion() {
|
|
||||||
return moveFracion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the motorResolution
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getMotorResolution() {
|
|
||||||
return motorResolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the encoderResolution
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getEncoderResolution() {
|
|
||||||
return encoderResolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the readbackResolution
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getReadbackResolution() {
|
|
||||||
return readbackResolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the retryDeadband
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getRetryDeadband() {
|
|
||||||
return retryDeadband;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the maxRetryCount
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getMaxRetryCount() {
|
|
||||||
return maxRetryCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the retryCount
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getRetryCount() {
|
|
||||||
return retryCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the useEncoder
|
|
||||||
*/
|
|
||||||
public ChannelBean<Boolean> getUseEncoder() {
|
|
||||||
return useEncoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the useReadback
|
|
||||||
*/
|
|
||||||
public ChannelBean<Boolean> getUseReadback() {
|
|
||||||
return useReadback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the readbackDelay
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getReadbackDelay() {
|
|
||||||
return readbackDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the readbackLink
|
|
||||||
*/
|
|
||||||
public ChannelBean<String> getReadbackLink() {
|
|
||||||
return readbackLink;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the outputMode
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getOutputMode() {
|
|
||||||
return outputMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the moveDone
|
|
||||||
*/
|
|
||||||
public ChannelBean<Boolean> getMoveDone() {
|
|
||||||
return moveDone;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,169 +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.loops.cr;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
|
|
||||||
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 ParallelCrlogicStreamMerge {
|
|
||||||
|
|
||||||
private BlockingQueue<Message> dataQueue;
|
|
||||||
|
|
||||||
private DataQueue primaryQueue;
|
|
||||||
private DataQueue secondaryQueue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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){
|
|
||||||
this.primaryQueue = pqueue;
|
|
||||||
this.secondaryQueue = squeue;
|
|
||||||
|
|
||||||
this.dataQueue = new LinkedBlockingQueue<Message>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Merge the streams based on the timestamp
|
|
||||||
* @throws InterruptedException
|
|
||||||
*/
|
|
||||||
public void merge() throws InterruptedException{
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
|
|
||||||
while(! (m instanceof EndOfStreamMessage)){
|
|
||||||
|
|
||||||
if(m instanceof DataMessage){
|
|
||||||
|
|
||||||
DataMessage dm = (DataMessage) m;
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
|
|
||||||
if(mess instanceof EndOfStreamMessage){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mess == null){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
currData = ms.getData();
|
|
||||||
// Remove timestamps
|
|
||||||
currData.remove(0);
|
|
||||||
currData.remove(0);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// No DataMessage
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add data to primary data queue message and put it into the out queue
|
|
||||||
dm.getData().addAll(currData);
|
|
||||||
|
|
||||||
dataQueue.add(dm);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
m = primaryQueue.getQueue().take();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the end of stream message of the primary queue
|
|
||||||
dataQueue.add(m);
|
|
||||||
|
|
||||||
// Clear all remaining messages in secondary queue
|
|
||||||
secondaryQueue.getQueue().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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,397 +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.loops.cr;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
import gov.aps.jca.Monitor;
|
|
||||||
|
|
||||||
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.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
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.jcae.ChannelBean;
|
|
||||||
import ch.psi.jcae.MonitorListenerDoubleTimestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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
|
|
||||||
* other on different IOC's have not arrived yet. - The sequence of
|
|
||||||
* monitors fired for one channel is according to the sequence of the
|
|
||||||
* causes. No monitor package is overtaking an other package on the
|
|
||||||
* network.
|
|
||||||
*
|
|
||||||
* - No monitor events are lost on the network (while using monitors you
|
|
||||||
* cannot guarantee this)
|
|
||||||
*
|
|
||||||
* The data queue returned by this logic includes two items for the
|
|
||||||
* timestamp and nanoseconds offset. These two items are the first two
|
|
||||||
* items of a message The id's are: crTimestampMilliseconds
|
|
||||||
* crTimestampOffsetNanoseconds
|
|
||||||
*/
|
|
||||||
public class ScrlogicLoop implements ActionLoop {
|
|
||||||
|
|
||||||
private static String ID_TIMESTAMP_MILLISECONDS = "crTimestampMilliseconds";
|
|
||||||
private static String ID_TIMESTAMP_OFFSET_NANOSECONDS = "crTimestampOffsetNanoseconds";
|
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
private static final Logger logger = Logger.getLogger(ScrlogicLoop.class.getName());
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of monitors that were attached to the sensor channels (i.e
|
|
||||||
* workaround)
|
|
||||||
*/
|
|
||||||
private final List<Monitor> monitors = new ArrayList<Monitor>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of blocking queues that hold the data for one sensor (channel)
|
|
||||||
*/
|
|
||||||
private final List<BlockingQueue<TimestampedValue>> queues = new ArrayList<BlockingQueue<TimestampedValue>>();
|
|
||||||
|
|
||||||
private CountDownLatch latch;
|
|
||||||
|
|
||||||
public ScrlogicLoop(List<Sensor> sensors) {
|
|
||||||
this.sensors = sensors;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see ch.psi.fda.core.Action#execute()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void execute() throws InterruptedException {
|
|
||||||
|
|
||||||
// Clear all queues
|
|
||||||
queues.clear();
|
|
||||||
latch = new CountDownLatch(1);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Attach monitors to the channels (this is actually a workaround)
|
|
||||||
for (Sensor sensor : sensors) {
|
|
||||||
if (sensor instanceof ChannelAccessDoubleSensor) {
|
|
||||||
ChannelAccessDoubleSensor s = (ChannelAccessDoubleSensor) sensor;
|
|
||||||
ChannelBean<Double> b = s.getChannel();
|
|
||||||
// Create data queue for the channel
|
|
||||||
final BlockingQueue<TimestampedValue> q = new LinkedBlockingQueue<TimestampedValue>();
|
|
||||||
queues.add(q);
|
|
||||||
|
|
||||||
Monitor m = b
|
|
||||||
.attachMonitor(new MonitorListenerDoubleTimestamp() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void valueChanged(Double value, Date timestamp, long nanosecondsOffset) {
|
|
||||||
// Add values to channel queue
|
|
||||||
q.add(new TimestampedValue(value, timestamp.getTime(), nanosecondsOffset));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
monitors.add(m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (CAException e) {
|
|
||||||
new RuntimeException("Unable to create monitor for channels", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("Start data acquisition");
|
|
||||||
|
|
||||||
latch.await();
|
|
||||||
|
|
||||||
// Remove monitors
|
|
||||||
try {
|
|
||||||
for (int i = 0; i < sensors.size(); i++) {
|
|
||||||
Sensor sensor = sensors.get(i);
|
|
||||||
if (sensor instanceof ChannelAccessDoubleSensor) {
|
|
||||||
ChannelAccessDoubleSensor s = (ChannelAccessDoubleSensor) sensor;
|
|
||||||
ChannelBean<Double> b = s.getChannel();
|
|
||||||
try{
|
|
||||||
b.removeMonitor(monitors.get(i));
|
|
||||||
}
|
|
||||||
catch(IllegalArgumentException e){
|
|
||||||
logger.log(Level.SEVERE, "Unable to detach monitor", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (CAException e) {
|
|
||||||
new RuntimeException(e);
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
// Clear all monitors in the list
|
|
||||||
monitors.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge data
|
|
||||||
merge();
|
|
||||||
|
|
||||||
// Clear data queues
|
|
||||||
for (BlockingQueue<TimestampedValue> q : queues) {
|
|
||||||
q.clear();
|
|
||||||
}
|
|
||||||
queues.clear();
|
|
||||||
|
|
||||||
// Put end of stream to the queue
|
|
||||||
dataQueue.add(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 (Sensor s : sensors) {
|
|
||||||
s.destroy();
|
|
||||||
}
|
|
||||||
sensors.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see ch.psi.fda.core.ActionLoop#prepare()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void prepare() {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (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 (Sensor s : sensors) {
|
|
||||||
m.getComponents().add(new ComponentMetadata(s.getId()));
|
|
||||||
}
|
|
||||||
return new DataQueue(dataQueue, m);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasNext(){
|
|
||||||
for (int i = 0; i < queues.size(); i++) {
|
|
||||||
if(!queues.get(i).isEmpty()){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Merge data collected by different monitor
|
|
||||||
*
|
|
||||||
* @throws InterruptedException
|
|
||||||
*/
|
|
||||||
private void merge() throws InterruptedException {
|
|
||||||
|
|
||||||
// Array to hold temporary channel values
|
|
||||||
TimestampedValue[] cvalues = new TimestampedValue[queues.size()];
|
|
||||||
TimestampedValueComparator comparator = new TimestampedValueComparator();
|
|
||||||
|
|
||||||
// Oldest value written
|
|
||||||
TimestampedValue globalOldest = null;
|
|
||||||
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
|
|
||||||
|
|
||||||
// Oldest value of this run
|
|
||||||
TimestampedValue oldest = null;
|
|
||||||
// Queue index of the oldest value of this run
|
|
||||||
indexes.clear();
|
|
||||||
|
|
||||||
// Find oldest element in any of the queues
|
|
||||||
for (int i = 0; i < queues.size(); i++) {
|
|
||||||
|
|
||||||
BlockingQueue<TimestampedValue> q = queues.get(i);
|
|
||||||
TimestampedValue ttcheck = q.peek();
|
|
||||||
|
|
||||||
if (ttcheck != null) {
|
|
||||||
if (oldest == null) {
|
|
||||||
// Update the oldest variable with current element
|
|
||||||
oldest = ttcheck;
|
|
||||||
indexes.clear();
|
|
||||||
indexes.add(i);
|
|
||||||
} else if (comparator.compare(ttcheck, oldest) < 0) {
|
|
||||||
// Check whether timestamp is less (older) than the current oldest timestamp.
|
|
||||||
oldest = ttcheck;
|
|
||||||
indexes.clear();
|
|
||||||
indexes.add(i);
|
|
||||||
} else if (comparator.compare(ttcheck, oldest) == 0) {
|
|
||||||
// SAME TIMESTAMP
|
|
||||||
indexes.add(i);
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// logger.info("Index: "+index+" Permits: "+semaphore.availablePermits());
|
|
||||||
// System.out.println("indexes: "+indexes.size());
|
|
||||||
|
|
||||||
if (indexes.size() > 0) {
|
|
||||||
long timestamp = 0l;
|
|
||||||
long nanoOffset = 0l;
|
|
||||||
|
|
||||||
for (Integer index : indexes) {
|
|
||||||
// Get next older value
|
|
||||||
cvalues[index] = queues.get(index).poll();
|
|
||||||
|
|
||||||
if (globalOldest != null) {
|
|
||||||
if (comparator.compare(cvalues[index], globalOldest) >= 0) {
|
|
||||||
// Update the global oldest variable
|
|
||||||
globalOldest = cvalues[index];
|
|
||||||
timestamp = cvalues[index].getTimestamp();
|
|
||||||
nanoOffset = cvalues[index].getNanosecondsOffset();
|
|
||||||
} else {
|
|
||||||
// Monitors did not fire in sequence (an newer
|
|
||||||
// monitor overtook an older (from an other IOC))
|
|
||||||
logger.warning("Timestamped value out of sequence - discard value !!!!");
|
|
||||||
// Continue with next value ...
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
globalOldest = cvalues[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assemble data message ...
|
|
||||||
DataMessage message = new DataMessage();
|
|
||||||
|
|
||||||
message.getData().add(new Double(timestamp));
|
|
||||||
message.getData().add(new Double(nanoOffset));
|
|
||||||
|
|
||||||
for (int y = 0; y < cvalues.length; y++) {
|
|
||||||
if (cvalues[y] != null) {
|
|
||||||
message.getData().add(new Double(cvalues[y].getValue()));
|
|
||||||
} else {
|
|
||||||
message.getData().add(Double.NaN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// System.out.println(message);
|
|
||||||
dataQueue.add(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,103 +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.loops.cr;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
import ch.psi.jcae.annotation.CaChannel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class VSC16ScalerChannelsTemplate {
|
|
||||||
|
|
||||||
|
|
||||||
public enum Command {Done, Count};
|
|
||||||
/**
|
|
||||||
* Command
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =".CNT")
|
|
||||||
private ChannelBean<Integer> command;
|
|
||||||
|
|
||||||
|
|
||||||
public enum Mode {OneShot, AutoCount};
|
|
||||||
/**
|
|
||||||
* Count mode
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name =".CONT")
|
|
||||||
private ChannelBean<Integer> mode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Channel description
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Boolean.class, name={".NM1", ".NM2", ".NM3", ".NM4", ".NM5", ".NM6", ".NM7", ".NM8", ".NM9", ".NM10", ".NM11", ".NM12", ".NM13", ".NM14", ".NM15", ".NM16"})
|
|
||||||
private List<ChannelBean<Boolean>> channelDescription;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Channel gate
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Boolean.class, name={".G1", ".G2", ".G3", ".G4", ".G5", ".G6", ".G7", ".G8", ".G9", ".G10", ".G11", ".G12", ".G13", ".G14", ".G15", ".G16"})
|
|
||||||
private List<ChannelBean<Boolean>> channelGate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Channel preset count
|
|
||||||
* If gate is on scaler will only count until this value
|
|
||||||
*/
|
|
||||||
@CaChannel(type=Integer.class, name={".PR1", ".PR2", ".PR3", ".PR4", ".PR5", ".PR6", ".PR7", ".PR8", ".PR9", ".PR10", ".PR11", ".PR12", ".PR13", ".PR14", ".PR15", ".PR16"})
|
|
||||||
private List<ChannelBean<Integer>> channelPresetCount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the command
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getCommand() {
|
|
||||||
return command;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the mode
|
|
||||||
*/
|
|
||||||
public ChannelBean<Integer> getMode() {
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the channelDescription
|
|
||||||
*/
|
|
||||||
public List<ChannelBean<Boolean>> getChannelDescription() {
|
|
||||||
return channelDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the channelGate
|
|
||||||
*/
|
|
||||||
public List<ChannelBean<Boolean>> getChannelGate() {
|
|
||||||
return channelGate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the channelPresetCount
|
|
||||||
*/
|
|
||||||
public List<ChannelBean<Integer>> getChannelPresetCount() {
|
|
||||||
return channelPresetCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,83 +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.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Structure to hold the metadata of a component of a message.
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class DataMessageMetadata implements Serializable {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mapping of a script parameter to a channel bean.
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class JythonParameterMappingChannel extends JythonParameterMapping {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Id of the component to map to this variable
|
|
||||||
*/
|
|
||||||
private String channel;
|
|
||||||
private Class<?> type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor accepting varible/id pair
|
|
||||||
* @param variable
|
|
||||||
* @param channel
|
|
||||||
* @param type
|
|
||||||
*/
|
|
||||||
public JythonParameterMappingChannel(String variable, String channel, Class<?> type){
|
|
||||||
super(variable);
|
|
||||||
this.channel = channel;
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the channel
|
|
||||||
*/
|
|
||||||
public String 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,144 +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.logging.Logger;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
import ch.psi.fda.core.EngineConfiguration;
|
|
||||||
import ch.psi.fda.core.Sensor;
|
|
||||||
import ch.psi.jcae.ChannelBeanFactory;
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 ChannelBean<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(String id, String channelName, int numberOfElements){
|
|
||||||
try {
|
|
||||||
this.channel = ChannelBeanFactory.getFactory().createChannelBean(double[].class, channelName, false);
|
|
||||||
this.numberOfElements = numberOfElements;
|
|
||||||
this.id = id;
|
|
||||||
} catch (CAException 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);
|
|
||||||
} 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 (CAException 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 (CAException e) {
|
|
||||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,132 +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.logging.Logger;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
import ch.psi.fda.core.EngineConfiguration;
|
|
||||||
import ch.psi.fda.core.Sensor;
|
|
||||||
import ch.psi.jcae.ChannelBeanFactory;
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 ChannelBean<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(String id, String channelName){
|
|
||||||
try {
|
|
||||||
channel = ChannelBeanFactory.getFactory().createChannelBean(Double.class, channelName, false);
|
|
||||||
this.id = id;
|
|
||||||
} catch (CAException 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 (CAException 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 (CAException e) {
|
|
||||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get channel object of sensor
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public ChannelBean<Double> getChannel(){
|
|
||||||
return channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,124 +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.logging.Logger;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
import ch.psi.fda.core.EngineConfiguration;
|
|
||||||
import ch.psi.fda.core.Sensor;
|
|
||||||
import ch.psi.jcae.ChannelBeanFactory;
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 ChannelBean<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(String id, String channelName){
|
|
||||||
try {
|
|
||||||
channel = ChannelBeanFactory.getFactory().createChannelBean(String.class, channelName, false);
|
|
||||||
this.id = id;
|
|
||||||
} catch (CAException 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());
|
|
||||||
|
|
||||||
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 (CAException 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 (CAException e) {
|
|
||||||
throw new RuntimeException("Unable to destroy channel ["+channel.getName()+"]",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,136 +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.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();
|
|
||||||
}
|
|
||||||
|
|
||||||
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,84 +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 out a named (Epics) 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 OTFNamedChannelSensor implements Sensor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the channel
|
|
||||||
*/
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Global id of the sensor
|
|
||||||
*/
|
|
||||||
private final String id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
* @param id Global id of the sensor
|
|
||||||
* @param name Name of the (Epics) channel
|
|
||||||
*/
|
|
||||||
public OTFNamedChannelSensor(String id, String name){
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ch.psi.fda.core.Sensor#read()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object read() {
|
|
||||||
// Always return 0 if read() method is called.
|
|
||||||
return 0d;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the name of the channel
|
|
||||||
*/
|
|
||||||
public String getName() {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,84 +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 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 {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Index of the scaler channel. The index starts at 0;
|
|
||||||
*/
|
|
||||||
private final int index;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Global id of the sensor
|
|
||||||
*/
|
|
||||||
private final String id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
* @param id Global id of the sensor
|
|
||||||
* @param index Index of the scaler channel. Index starts at 0.
|
|
||||||
*/
|
|
||||||
public OTFScalerChannelSensor(String id, int index){
|
|
||||||
this.id = id;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the index of the scaler channel
|
|
||||||
*/
|
|
||||||
public int getIndex() {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,200 +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.serializer;
|
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
|
||||||
|
|
||||||
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.EndOfStreamMessage;
|
|
||||||
import ch.psi.fda.core.messages.Message;
|
|
||||||
import ch.psi.fda.core.messages.StreamDelimiterMessage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialize data received by a DataQueue
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class DataSerializerTXT implements DataSerializer{
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(DataSerializerTXT.class.getName());
|
|
||||||
|
|
||||||
private File file;
|
|
||||||
|
|
||||||
private boolean appendSuffix = true;
|
|
||||||
|
|
||||||
|
|
||||||
private boolean first = true;
|
|
||||||
private File outfile;
|
|
||||||
|
|
||||||
private DataMessageMetadata meta;
|
|
||||||
|
|
||||||
private int icount;
|
|
||||||
private String basename;
|
|
||||||
private String extension;
|
|
||||||
private boolean newfile;
|
|
||||||
private boolean dataInBetween;
|
|
||||||
private BufferedWriter writer;
|
|
||||||
private StringBuffer b;
|
|
||||||
private StringBuffer b1;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param metadata
|
|
||||||
* @param file
|
|
||||||
* @param appendSuffix Flag whether to append a _0000 suffix after the original file name
|
|
||||||
*/
|
|
||||||
public DataSerializerTXT(DataMessageMetadata meta, File file, boolean appendSuffix){
|
|
||||||
this.meta = meta;
|
|
||||||
this.file = file;
|
|
||||||
this.appendSuffix = appendSuffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onMessage(Message message){
|
|
||||||
try{
|
|
||||||
if(first){
|
|
||||||
first=false;
|
|
||||||
// Write header
|
|
||||||
b = new StringBuffer();
|
|
||||||
b1 = new StringBuffer();
|
|
||||||
b.append("#");
|
|
||||||
b1.append("#");
|
|
||||||
for(ComponentMetadata c: meta.getComponents()){
|
|
||||||
|
|
||||||
b.append(c.getId());
|
|
||||||
b.append("\t");
|
|
||||||
|
|
||||||
b1.append(c.getDimension());
|
|
||||||
b1.append("\t");
|
|
||||||
}
|
|
||||||
b.setCharAt(b.length()-1, '\n');
|
|
||||||
b1.setCharAt(b1.length()-1, '\n');
|
|
||||||
|
|
||||||
|
|
||||||
icount = 0;
|
|
||||||
newfile = true;
|
|
||||||
dataInBetween = false;
|
|
||||||
writer = null;
|
|
||||||
|
|
||||||
// Get basename of the file
|
|
||||||
basename = this.file.getAbsolutePath(); // Determine file name
|
|
||||||
extension = basename.replaceAll("^.*\\.", ""); // Determine extension
|
|
||||||
basename = basename.replaceAll("\\."+extension+"$", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message instanceof DataMessage){
|
|
||||||
dataInBetween = true;
|
|
||||||
if(newfile){
|
|
||||||
// Open new file and write header
|
|
||||||
// Construct file name
|
|
||||||
if(appendSuffix){
|
|
||||||
outfile = new File(String.format("%s_%04d.%s", basename, icount, extension));
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
outfile = new File(String.format("%s.%s", basename, extension));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open file
|
|
||||||
logger.fine("Open new data file: "+outfile.getAbsolutePath());
|
|
||||||
writer = new BufferedWriter(new FileWriter(outfile));
|
|
||||||
|
|
||||||
// Write header
|
|
||||||
writer.write(b.toString());
|
|
||||||
writer.write(b1.toString());
|
|
||||||
|
|
||||||
newfile=false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write message to file - each message will result in one line
|
|
||||||
DataMessage m = (DataMessage) message;
|
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
for(Object o: m.getData()){
|
|
||||||
if(o.getClass().isArray()){
|
|
||||||
// If the array object is of type double[] display its content
|
|
||||||
if(o instanceof double[]){
|
|
||||||
double[] oa = (double[]) o;
|
|
||||||
for(double o1 : oa){
|
|
||||||
buffer.append(o1);
|
|
||||||
buffer.append(" "); // Use space instead of tab
|
|
||||||
}
|
|
||||||
buffer.replace(buffer.length()-1,buffer.length()-1 , "\t"); // Replace last space with tab
|
|
||||||
}
|
|
||||||
else if(o instanceof Object[]){
|
|
||||||
// TODO need to be recursive ...
|
|
||||||
Object[] oa = (Object[])o;
|
|
||||||
for(Object o1 : oa){
|
|
||||||
buffer.append(o1);
|
|
||||||
buffer.append(" "); // Use space instead of tab
|
|
||||||
}
|
|
||||||
buffer.replace(buffer.length()-1,buffer.length()-1 , "\t"); // Replace last space with tab
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
buffer.append("-"); // Not supported
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
buffer.append(o);
|
|
||||||
buffer.append("\t");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(buffer.length()>0){
|
|
||||||
buffer.deleteCharAt(buffer.length()-1); // Remove last character (i.e. \t)
|
|
||||||
buffer.append("\n"); // Append newline
|
|
||||||
}
|
|
||||||
writer.write(buffer.toString());
|
|
||||||
}
|
|
||||||
else if(message instanceof StreamDelimiterMessage){
|
|
||||||
StreamDelimiterMessage m = (StreamDelimiterMessage) message;
|
|
||||||
logger.info("Delimiter - number: "+m.getNumber()+" iflag: "+m.isIflag());
|
|
||||||
if(m.isIflag() && appendSuffix){
|
|
||||||
// Only increase iflag counter if there was data in between
|
|
||||||
// subsequent StreamDelimiterMessages.
|
|
||||||
if(dataInBetween){
|
|
||||||
icount++;
|
|
||||||
}
|
|
||||||
dataInBetween = false;
|
|
||||||
|
|
||||||
// Set flag to open new file
|
|
||||||
newfile = true;
|
|
||||||
|
|
||||||
// Close file
|
|
||||||
writer.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (message instanceof EndOfStreamMessage){
|
|
||||||
if(writer!=null){
|
|
||||||
// Close file
|
|
||||||
writer.close(); //If the stream was closed previously this has no effect
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException("Data serializer had a problem writing to the specified file",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,211 +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.serializer;
|
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
|
||||||
|
|
||||||
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.StreamDelimiterMessage;
|
|
||||||
import ch.psi.fda.core.messages.Message;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialize data received by a DataQueue
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class DataSerializerTXTSplit implements DataSerializer{
|
|
||||||
|
|
||||||
private DataMessageMetadata metadata;
|
|
||||||
private File file;
|
|
||||||
|
|
||||||
private int maxdim = 0;
|
|
||||||
|
|
||||||
private boolean first = true;
|
|
||||||
|
|
||||||
private List<String> header;
|
|
||||||
private List<String> data;
|
|
||||||
|
|
||||||
public DataSerializerTXTSplit(DataMessageMetadata metadata, File file){
|
|
||||||
this.metadata = metadata;
|
|
||||||
this.file = file;
|
|
||||||
|
|
||||||
|
|
||||||
// Determine maximum dimension
|
|
||||||
for(ComponentMetadata m: metadata.getComponents()){
|
|
||||||
if(m.getDimension()>maxdim){
|
|
||||||
maxdim=m.getDimension();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(maxdim<1){
|
|
||||||
throw new RuntimeException("Split serializer only supports data > 1 dimension");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onMessage(Message message) {
|
|
||||||
try{
|
|
||||||
|
|
||||||
if(first){
|
|
||||||
first=false;
|
|
||||||
|
|
||||||
header = new ArrayList<String>();
|
|
||||||
data = new ArrayList<String>();
|
|
||||||
|
|
||||||
// Write header
|
|
||||||
StringBuffer b = new StringBuffer();
|
|
||||||
StringBuffer b1 = new StringBuffer();
|
|
||||||
b.append("#");
|
|
||||||
b1.append("#");
|
|
||||||
for(ComponentMetadata c: metadata.getComponents()){
|
|
||||||
|
|
||||||
b.append(c.getId());
|
|
||||||
b.append("\t");
|
|
||||||
|
|
||||||
b1.append(c.getDimension());
|
|
||||||
b1.append("\t");
|
|
||||||
}
|
|
||||||
b.setCharAt(b.length()-1, '\n');
|
|
||||||
b1.setCharAt(b1.length()-1, '\n');
|
|
||||||
header.add(b.toString());
|
|
||||||
header.add(b1.toString());
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write data
|
|
||||||
// Read Message
|
|
||||||
|
|
||||||
if(message instanceof DataMessage){
|
|
||||||
|
|
||||||
// Write message to file - each message will result in one line
|
|
||||||
DataMessage m = (DataMessage) message;
|
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
for(Object o: m.getData()){
|
|
||||||
if(o.getClass().isArray()){
|
|
||||||
// If the array object is of type double[] display its content
|
|
||||||
if(o instanceof double[]){
|
|
||||||
double[] oa = (double[]) o;
|
|
||||||
for(double o1 : oa){
|
|
||||||
buffer.append(o1);
|
|
||||||
buffer.append(" "); // Use space instead of tab
|
|
||||||
}
|
|
||||||
buffer.replace(buffer.length()-1,buffer.length()-1 , "\t"); // Replace last space with tab
|
|
||||||
}
|
|
||||||
else if(o instanceof Object[]){
|
|
||||||
// TODO need to be recursive ...
|
|
||||||
Object[] oa = (Object[])o;
|
|
||||||
for(Object o1 : oa){
|
|
||||||
buffer.append(o1);
|
|
||||||
buffer.append(" "); // Use space instead of tab
|
|
||||||
}
|
|
||||||
buffer.replace(buffer.length()-1,buffer.length()-1 , "\t"); // Replace last space with tab
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
buffer.append("-"); // Not supported
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
buffer.append(o);
|
|
||||||
buffer.append("\t");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.deleteCharAt(buffer.length()-1); // Remove last character (i.e. \t)
|
|
||||||
buffer.append("\n"); // Append newline
|
|
||||||
data.add(buffer.toString());
|
|
||||||
}
|
|
||||||
else if(message instanceof StreamDelimiterMessage){
|
|
||||||
StreamDelimiterMessage m = (StreamDelimiterMessage) message;
|
|
||||||
if(m.getNumber()==maxdim-1){
|
|
||||||
writeData(header, data);
|
|
||||||
// Clear data
|
|
||||||
data.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException("Data serializer had a problem writing to the specified file",e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeData(List<String> header, List<String> data) throws IOException{
|
|
||||||
|
|
||||||
// WORKAROUND BEGIN
|
|
||||||
File outfile;
|
|
||||||
// if(appendSuffix){
|
|
||||||
// Append a count suffix to the file. If there is already a file with
|
|
||||||
// this suffix increase the counter for the suffix
|
|
||||||
int cnt = 0;
|
|
||||||
String fname = this.file.getAbsolutePath(); // Determine file name
|
|
||||||
String extension = fname.replaceAll("^.*\\.", ""); // Determine extension
|
|
||||||
fname = fname.replaceAll("\\."+extension+"$", "");
|
|
||||||
|
|
||||||
outfile = new File(String.format("%s_%04d.%s", fname, cnt, extension));
|
|
||||||
|
|
||||||
while(outfile.exists()){
|
|
||||||
cnt++;
|
|
||||||
outfile = new File(String.format("%s_%04d.%s", fname, cnt, extension));
|
|
||||||
}
|
|
||||||
// }
|
|
||||||
// else{
|
|
||||||
// outfile = this.file;
|
|
||||||
// }
|
|
||||||
// WORKAROUND END
|
|
||||||
|
|
||||||
// Open file
|
|
||||||
BufferedWriter writer = new BufferedWriter(new FileWriter(outfile));
|
|
||||||
|
|
||||||
// Write header
|
|
||||||
for(String s: header){
|
|
||||||
writer.write(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write data
|
|
||||||
for(String s: data){
|
|
||||||
writer.write(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Close file
|
|
||||||
writer.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable/disable the generation of the _0000 suffix in front of the extension of the out file
|
|
||||||
* @param appendSuffix the appendSuffix to set
|
|
||||||
*/
|
|
||||||
public void setAppendSuffix(boolean appendSuffix) {
|
|
||||||
// this.appendSuffix = appendSuffix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,570 +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.visualizer;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
|
||||||
|
|
||||||
import ch.psi.fda.core.messages.DataMessage;
|
|
||||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
|
||||||
import ch.psi.fda.core.messages.StreamDelimiterMessage;
|
|
||||||
import ch.psi.fda.core.messages.EndOfStreamMessage;
|
|
||||||
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.plot.Plot;
|
|
||||||
import ch.psi.plot.xy.LinePlot;
|
|
||||||
import ch.psi.plot.xy.XYSeriesCollectionP;
|
|
||||||
import ch.psi.plot.xy.XYSeriesP;
|
|
||||||
import ch.psi.plot.xyz.MatrixPlot;
|
|
||||||
import ch.psi.plot.xyz.MatrixPlotData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Visualizer for visualizing data
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Visualizer {
|
|
||||||
|
|
||||||
private static Logger logger = Logger.getLogger(Visualizer.class.getName());
|
|
||||||
|
|
||||||
private List<Plot> plots = new ArrayList<Plot>();
|
|
||||||
|
|
||||||
private boolean updateAtStreamElement = true;
|
|
||||||
private boolean updateAtStreamDelimiter = true;
|
|
||||||
private boolean updateAtEndOfStream = false;
|
|
||||||
|
|
||||||
private int ecount;
|
|
||||||
private boolean clearPlot;
|
|
||||||
private List<SeriesDataFilter> filters;
|
|
||||||
|
|
||||||
public Visualizer(DataMessageMetadata meta, List<Visualization> vl){
|
|
||||||
filters = mapVisualizations(meta, vl);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onDataMessage(final DataMessage message){
|
|
||||||
// Clear is here as the plot should not be cleared after the last point is plotted
|
|
||||||
// but just before the first point of the next plot (cycle)
|
|
||||||
if (clearPlot) {
|
|
||||||
for (Plot plot: plots) {
|
|
||||||
if(plot instanceof MatrixPlot){
|
|
||||||
((MatrixPlotData) ((MatrixPlot)plot).getData()).clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clearPlot = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(SeriesDataFilter filter: filters){
|
|
||||||
if(filter instanceof XYSeriesDataFilter){
|
|
||||||
XYSeriesDataFilter xyfilter = (XYSeriesDataFilter) filter;
|
|
||||||
|
|
||||||
if(xyfilter.getActualSeries()==null || xyfilter.isNewseries()){
|
|
||||||
// First series that is filled by this filter!
|
|
||||||
XYSeriesP s = new XYSeriesP(xyfilter.getSeriesName() + " " + ecount + "-" + xyfilter.getCount());
|
|
||||||
((LinePlot)xyfilter.getPlot()).getData().addSeries(s);
|
|
||||||
xyfilter.setActualSeries(s);
|
|
||||||
xyfilter.setNewseries(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
XYSeriesP series = xyfilter.getActualSeries(); // TODO Does not work with multiple series filter per plot !!!!
|
|
||||||
|
|
||||||
// There might be other values than double in the data, therefore we have to check for it
|
|
||||||
Object dX = message.getData().get(xyfilter.getIndexX());
|
|
||||||
Object dY = message.getData().get(xyfilter.getIndexY());
|
|
||||||
Double dataX = Double.NaN;
|
|
||||||
Double dataY = Double.NaN;
|
|
||||||
if(dX instanceof Double){
|
|
||||||
dataX = (Double) dX;
|
|
||||||
}
|
|
||||||
if(dY instanceof Double){
|
|
||||||
dataY = (Double) dY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Data to the series
|
|
||||||
series.add(dataX , dataY, updateAtStreamElement);
|
|
||||||
}
|
|
||||||
if(filter instanceof XYSeriesArrayDataFilter){
|
|
||||||
final XYSeriesArrayDataFilter xyfilter = (XYSeriesArrayDataFilter) filter;
|
|
||||||
|
|
||||||
// Ensure that there is no concurrent modification exception or synchronization problems with the
|
|
||||||
// Swing update task
|
|
||||||
SwingUtilities.invokeLater(new Runnable(){
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
XYSeriesP series = new XYSeriesP(xyfilter.getSeriesName() + "-" + xyfilter.getCount()); // Series name must be unique
|
|
||||||
xyfilter.incrementCount();
|
|
||||||
|
|
||||||
// ((LinePlot)xyfilter.getPlot()).getData().removeAllSeries(); // Remove all series from the data
|
|
||||||
// If we can agree only to display one series at a time also a clear() on the actual series is better
|
|
||||||
XYSeriesCollectionP sc = ((LinePlot)xyfilter.getPlot()).getData();
|
|
||||||
sc.addSeries(series);
|
|
||||||
|
|
||||||
// Remove outdated series
|
|
||||||
if(sc.getSeriesCount()>xyfilter.getMaxSeries()){
|
|
||||||
// Remove oldest series
|
|
||||||
sc.removeSeries(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
double[] data = (double[]) message.getData().get(xyfilter.getIndexY());
|
|
||||||
// Copy data starting from offset to size
|
|
||||||
int size = data.length;
|
|
||||||
int offset = xyfilter.getOffset();
|
|
||||||
if(xyfilter.getSize()>0 && offset+xyfilter.getSize()<data.length){
|
|
||||||
size = offset + xyfilter.getSize();
|
|
||||||
}
|
|
||||||
for(int i=offset;i<size;i++){
|
|
||||||
series.add(i,data[i], false); // Do not fire change event - this would degrade performance drastically
|
|
||||||
}
|
|
||||||
series.fireSeriesChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if(filter instanceof XYZSeriesDataFilter){
|
|
||||||
XYZSeriesDataFilter xyzfilter = (XYZSeriesDataFilter) filter;
|
|
||||||
try{
|
|
||||||
((MatrixPlot)xyzfilter.getPlot()).getData().addData((Double) message.getData().get(xyzfilter.getIndexX()),(Double) message.getData().get(xyzfilter.getIndexY()), (Double) message.getData().get(xyzfilter.getIndexZ()));
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
// Ignore if something goes wrong while adding a datapoint
|
|
||||||
logger.log(Level.WARNING, "Unable to plot datapoint in matrix plot", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(filter instanceof XYZSeriesArrayDataFilter){
|
|
||||||
XYZSeriesArrayDataFilter xyzfilter = (XYZSeriesArrayDataFilter) filter;
|
|
||||||
try{
|
|
||||||
double[] data = (double[]) message.getData().get(xyzfilter.getIndexZ());
|
|
||||||
double y = (Double) message.getData().get(xyzfilter.getIndexY());
|
|
||||||
int offset = xyzfilter.getOffset();
|
|
||||||
int size = xyzfilter.getSize();
|
|
||||||
for(int i=offset;i<offset+size; i++){
|
|
||||||
((MatrixPlot)xyzfilter.getPlot()).getData().addData(i, y, data[i]);
|
|
||||||
}
|
|
||||||
// Update data if update by point is enabled
|
|
||||||
if(updateAtStreamElement){
|
|
||||||
xyzfilter.getPlot().update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
// Ignore if something goes wrong while adding a datapoint
|
|
||||||
logger.log(Level.WARNING, "Unable to plot datapoint in matrix plot", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onStreamDelimiterMessage(StreamDelimiterMessage message){
|
|
||||||
for(SeriesDataFilter filter: filters){
|
|
||||||
if(filter instanceof XYSeriesDataFilter){
|
|
||||||
// Create new series
|
|
||||||
XYSeriesDataFilter xyfilter = (XYSeriesDataFilter) filter;
|
|
||||||
if (message.getNumber() == xyfilter.getDimensionX()) {
|
|
||||||
// Indicate to create new series at the next message
|
|
||||||
xyfilter.setCount(xyfilter.getCount()+1); // Increment count of the filter
|
|
||||||
xyfilter.setNewseries(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update matrix plot at the end of each line
|
|
||||||
if(updateAtStreamDelimiter){
|
|
||||||
for (Plot plot: plots) {
|
|
||||||
if(plot instanceof MatrixPlot){
|
|
||||||
((MatrixPlot)plot).update();
|
|
||||||
}
|
|
||||||
else if(plot instanceof LinePlot){
|
|
||||||
((LinePlot) plot).update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear matrix plot if iflag is encountered
|
|
||||||
// TODO: One need to check whether the iflag belongs to a delimiter
|
|
||||||
// of a higher dimension than the highest dimension (axis) that
|
|
||||||
// is involved in the plot
|
|
||||||
if (message.isIflag()) {
|
|
||||||
clearPlot = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onEndOfStreamMessage(EndOfStreamMessage message){
|
|
||||||
ecount++;
|
|
||||||
|
|
||||||
// Update plots if updateAtEndOfStream flag is set
|
|
||||||
if(updateAtEndOfStream){
|
|
||||||
// Update matrix plots
|
|
||||||
for (Plot plot: plots) {
|
|
||||||
if(plot instanceof MatrixPlot){
|
|
||||||
((MatrixPlot)plot).update();
|
|
||||||
((MatrixPlot)plot).adaptColorMapScale(); // Update color scale at the end
|
|
||||||
}
|
|
||||||
else if(plot instanceof LinePlot){
|
|
||||||
((LinePlot) plot).update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void configure(){
|
|
||||||
ecount = 0;
|
|
||||||
clearPlot = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve id string of the passed object
|
|
||||||
* @param object
|
|
||||||
* @return Id string of object
|
|
||||||
*/
|
|
||||||
private 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get configured visualizations
|
|
||||||
* Note: This method is public because it is also used by the VisualizationEngine
|
|
||||||
* @param vl List of configured visualizations
|
|
||||||
* @return List of visualization configuration
|
|
||||||
*/
|
|
||||||
private List<SeriesDataFilter> mapVisualizations(DataMessageMetadata meta, 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());
|
|
||||||
plots.add(plot);
|
|
||||||
|
|
||||||
// Create data filter for visualization
|
|
||||||
String idX = getId(lp.getX());
|
|
||||||
int indexX = meta.getIndex(idX);
|
|
||||||
int dimX = meta.getComponents().get(indexX).getDimension();
|
|
||||||
|
|
||||||
List<Object> l = lp.getY();
|
|
||||||
for(Object o: l){
|
|
||||||
String idY = getId(o);
|
|
||||||
int indexY = meta.getIndex(idY);
|
|
||||||
int dimY = meta.getComponents().get(indexY).getDimension();
|
|
||||||
|
|
||||||
XYSeriesDataFilter filter = new XYSeriesDataFilter(idX, idY, indexX, indexY, plot);
|
|
||||||
filter.setDimensionX(dimX);
|
|
||||||
filter.setDimensionY(dimY);
|
|
||||||
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());
|
|
||||||
plots.add(plot);
|
|
||||||
|
|
||||||
// Create data filter for visualization
|
|
||||||
List<Object> l = lp.getY();
|
|
||||||
for(Object o: l){
|
|
||||||
String idY = getId(o);
|
|
||||||
int indexY = meta.getIndex(idY);
|
|
||||||
int dimY = meta.getComponents().get(indexY).getDimension();
|
|
||||||
|
|
||||||
XYSeriesArrayDataFilter filter = new XYSeriesArrayDataFilter(idY, indexY, plot);
|
|
||||||
filter.setDimensionY(dimY);
|
|
||||||
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);
|
|
||||||
plots.add(plot);
|
|
||||||
|
|
||||||
// Create data filter for visualization
|
|
||||||
int indexX = meta.getIndex(idX);
|
|
||||||
int indexY = meta.getIndex(idY);
|
|
||||||
int indexZ = meta.getIndex(idZ);
|
|
||||||
|
|
||||||
int dimX = meta.getComponents().get(indexX).getDimension();
|
|
||||||
int dimY = meta.getComponents().get(indexY).getDimension();
|
|
||||||
int dimZ = meta.getComponents().get(indexZ).getDimension();
|
|
||||||
|
|
||||||
XYZSeriesDataFilter filter = new XYZSeriesDataFilter(idX, idY, idZ, indexX, indexY, indexZ, plot);
|
|
||||||
filter.setDimensionX(dimX);
|
|
||||||
filter.setDimensionY(dimY);
|
|
||||||
filter.setDimensionZ(dimZ);
|
|
||||||
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);
|
|
||||||
plots.add(plot);
|
|
||||||
|
|
||||||
// Create data filter for visualization
|
|
||||||
int indexY = meta.getIndex(idY);
|
|
||||||
int indexZ = meta.getIndex(idZ);
|
|
||||||
|
|
||||||
int dimY = meta.getComponents().get(indexY).getDimension();
|
|
||||||
int dimZ = meta.getComponents().get(indexZ).getDimension();
|
|
||||||
|
|
||||||
XYZSeriesArrayDataFilter filter = new XYZSeriesArrayDataFilter(idY, idZ, indexY, indexZ, offset, size, plot);
|
|
||||||
filter.setDimensionY(dimY);
|
|
||||||
filter.setDimensionZ(dimZ);
|
|
||||||
filters.add(filter);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// Visualization type (currently) not supported
|
|
||||||
throw new RuntimeException(v.getClass().getName()+" is not supported as visualization type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filters;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the plot panels for the visualizations
|
|
||||||
* @return List of configured JPanels
|
|
||||||
*/
|
|
||||||
public List<JPanel> getPlotPanels(){
|
|
||||||
List<JPanel> panels = new ArrayList<JPanel>();
|
|
||||||
for(Plot plot: plots){
|
|
||||||
panels.add(plot.getChartPanel());
|
|
||||||
}
|
|
||||||
|
|
||||||
return panels;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the updateAtStreamElement
|
|
||||||
*/
|
|
||||||
public boolean isUpdateAtStreamElement() {
|
|
||||||
return updateAtStreamElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param updateAtStreamElement the updateAtStreamElement to set
|
|
||||||
*/
|
|
||||||
public void setUpdateAtStreamElement(boolean updateAtStreamElement) {
|
|
||||||
this.updateAtStreamElement = updateAtStreamElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the updateAtStreamDelimiter
|
|
||||||
*/
|
|
||||||
public boolean isUpdateAtStreamDelimiter() {
|
|
||||||
return updateAtStreamDelimiter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param updateAtStreamDelimiter the updateAtStreamDelimiter to set
|
|
||||||
*/
|
|
||||||
public void setUpdateAtStreamDelimiter(boolean updateAtStreamDelimiter) {
|
|
||||||
this.updateAtStreamDelimiter = updateAtStreamDelimiter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the updateAtEndOfStream
|
|
||||||
*/
|
|
||||||
public boolean isUpdateAtEndOfStream() {
|
|
||||||
return updateAtEndOfStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param updateAtEndOfStream the updateAtEndOfStream to set
|
|
||||||
*/
|
|
||||||
public void setUpdateAtEndOfStream(boolean updateAtEndOfStream) {
|
|
||||||
this.updateAtEndOfStream = updateAtEndOfStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,187 +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.visualizer;
|
|
||||||
|
|
||||||
import ch.psi.plot.Plot;
|
|
||||||
import ch.psi.plot.xy.XYSeriesP;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metadata of a group of XYSeries.
|
|
||||||
* This metadata holds the information needed by the DataVisualizer
|
|
||||||
* to plot series.
|
|
||||||
*
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class XYSeriesDataFilter implements SeriesDataFilter{
|
|
||||||
|
|
||||||
private final String idX;
|
|
||||||
private final String idY;
|
|
||||||
|
|
||||||
// Name of the series generated by this filter
|
|
||||||
private String seriesName = "";
|
|
||||||
|
|
||||||
// Index of stream message components used for x and y
|
|
||||||
private final int indexX;
|
|
||||||
private final int indexY;
|
|
||||||
|
|
||||||
// Dimension of the x,y value - used to determine whether a new series should be created for this filter
|
|
||||||
private int dimensionX;
|
|
||||||
private int dimensionY;
|
|
||||||
|
|
||||||
// Number of series generated for this filter
|
|
||||||
private int count = 0;
|
|
||||||
|
|
||||||
// Plot the data of this filter goes to
|
|
||||||
private final Plot plot;
|
|
||||||
|
|
||||||
// TODO WORKAROUND - XYZ filter must not have this property !!!!
|
|
||||||
private XYSeriesP actualSeries = null;
|
|
||||||
private boolean newseries = false;
|
|
||||||
|
|
||||||
|
|
||||||
public XYSeriesDataFilter(String idX, String idY, int indexX, int indexY, Plot plot){
|
|
||||||
this.idX = idX;
|
|
||||||
this.idY = idY;
|
|
||||||
this.indexX = indexX;
|
|
||||||
this.indexY = indexY;
|
|
||||||
this.plot = plot;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the xId
|
|
||||||
*/
|
|
||||||
public String getIdX() {
|
|
||||||
return idX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the yId
|
|
||||||
*/
|
|
||||||
public String getIdY() {
|
|
||||||
return idY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the seriesName
|
|
||||||
*/
|
|
||||||
public String getSeriesName() {
|
|
||||||
return seriesName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param seriesName the seriesName to set
|
|
||||||
*/
|
|
||||||
public void setSeriesName(String seriesName) {
|
|
||||||
this.seriesName = seriesName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the indexX
|
|
||||||
*/
|
|
||||||
public int getIndexX() {
|
|
||||||
return indexX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the indexY
|
|
||||||
*/
|
|
||||||
public int getIndexY() {
|
|
||||||
return indexY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the dimensionX
|
|
||||||
*/
|
|
||||||
public int getDimensionX() {
|
|
||||||
return dimensionX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the dimensionY
|
|
||||||
*/
|
|
||||||
public int getDimensionY() {
|
|
||||||
return dimensionY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param dimensionY the dimensionY to set
|
|
||||||
*/
|
|
||||||
public void setDimensionY(int dimensionY) {
|
|
||||||
this.dimensionY = dimensionY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param dimensionX the dimensionX to set
|
|
||||||
*/
|
|
||||||
public void setDimensionX(int dimensionX) {
|
|
||||||
this.dimensionX = dimensionX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the count
|
|
||||||
*/
|
|
||||||
public int getCount() {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param count the count to set
|
|
||||||
*/
|
|
||||||
public void setCount(int count) {
|
|
||||||
this.count = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the plot
|
|
||||||
*/
|
|
||||||
public Plot getPlot() {
|
|
||||||
return plot;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the actualSeries
|
|
||||||
*/
|
|
||||||
public XYSeriesP getActualSeries() {
|
|
||||||
return actualSeries;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param actualSeries the actualSeries to set
|
|
||||||
*/
|
|
||||||
public void setActualSeries(XYSeriesP actualSeries) {
|
|
||||||
this.actualSeries = actualSeries;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the newseries
|
|
||||||
*/
|
|
||||||
public boolean isNewseries() {
|
|
||||||
return newseries;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param newseries the newseries to set
|
|
||||||
*/
|
|
||||||
public void setNewseries(boolean newseries) {
|
|
||||||
this.newseries = newseries;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
BASEDIR=$(cd $(dirname $0);pwd)
|
|
||||||
|
|
||||||
EPICS_DISPLAY_PATH=/work/sls/config/medm:$EPICS_DISPLAY_PATH
|
|
||||||
export EPICS_DISPLAY_PATH
|
|
||||||
|
|
||||||
# OTFSCAN MEDM
|
|
||||||
medm -x -macro "P=MTEST-HW3-OTFX" G_OTFSCAN_user.adl &
|
|
||||||
|
|
||||||
# Motor MEDM
|
|
||||||
medm -x -macro "P=MTEST-HW3:, M=MOT1" motorx_more.adl &
|
|
||||||
#medm -x -macro "ENC=MTEST-HW3:EC1" G_ECM_514A_encoder.adl &
|
|
||||||
|
|
||||||
medm -x -macro "P=MTEST-HW3:, M=MOT2" motorx_more.adl &
|
|
||||||
#medm -x -macro "ENC=MTEST-HW3:EC2" G_ECM_514A_encoder.adl &
|
|
||||||
|
|
||||||
medm -x -macro "P=MTEST-PC-MOTOR:, M=MOT1" motorx_more.adl &
|
|
||||||
|
|
||||||
# Scaler MEDM
|
|
||||||
medm -x -macro "P=MTEST-HW3:, S=JS" scaler16.adl &
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# Load test template
|
|
||||||
dbLoadTemplate("MTEST-PC-FDA_test.subs")
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
file test.template {
|
|
||||||
{
|
|
||||||
P = MTEST-PC-FDA:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
MODULE = MTEST-PC-FDA
|
|
||||||
export MODULE
|
|
||||||
|
|
||||||
build:
|
|
||||||
|
|
||||||
clean:
|
|
||||||
|
|
||||||
install: build
|
|
||||||
swit -V -ioc MTEST-PC-FDA
|
|
||||||
|
|
||||||
help:
|
|
||||||
@echo "The following targets are available with this Makefile:-"
|
|
||||||
@echo "make (calls default target)"
|
|
||||||
@echo "make build (default)"
|
|
||||||
@echo "make install"
|
|
||||||
@echo "make clean"
|
|
||||||
@echo "make help"
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
# Binary Output
|
|
||||||
record(bo, "$(P)BO") {
|
|
||||||
field(DESC, "Binary Output")
|
|
||||||
}
|
|
||||||
|
|
||||||
# Binary Output
|
|
||||||
record(bo, "$(P)BO2") {
|
|
||||||
field(DESC, "Binary Output 2")
|
|
||||||
field(VAL, "0")
|
|
||||||
}
|
|
||||||
|
|
||||||
# Analog Output
|
|
||||||
record(ao, "$(P)AO") {
|
|
||||||
field(PREC, "6")
|
|
||||||
field(DESC, "Analog Output")
|
|
||||||
}
|
|
||||||
|
|
||||||
# String Output
|
|
||||||
record(stringout, "$(P)SOUT") {
|
|
||||||
}
|
|
||||||
|
|
||||||
# Double Waveform (100 Elements)
|
|
||||||
record(waveform, "$(P)DWAVE") {
|
|
||||||
field(DESC, "Double Waveform")
|
|
||||||
field(PREC, "6")
|
|
||||||
field(NELM, "100")
|
|
||||||
field(FTVL, "DOUBLE")
|
|
||||||
}
|
|
||||||
|
|
||||||
# Integer Waveform (100 Elements)
|
|
||||||
record(waveform, "$(P)LWAVE") {
|
|
||||||
field(DESC, "Long Waveform")
|
|
||||||
field(NELM, "100")
|
|
||||||
field(FTVL, "LONG")
|
|
||||||
}
|
|
||||||
|
|
||||||
# Character Waveform (100 Elements)
|
|
||||||
record(waveform, "$(P)CWAVE") {
|
|
||||||
field(DESC, "Character Waveform")
|
|
||||||
field(NELM, "100")
|
|
||||||
field(FTVL, "CHAR")
|
|
||||||
}
|
|
||||||
@@ -1,209 +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.aq;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
|
||||||
|
|
||||||
import ch.psi.fda.aq.Collector;
|
|
||||||
import ch.psi.fda.core.messages.ComponentMetadata;
|
|
||||||
import ch.psi.fda.core.messages.ControlMessage;
|
|
||||||
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;
|
|
||||||
|
|
||||||
public class CollectorTest {
|
|
||||||
|
|
||||||
private static Logger logger = Logger.getLogger(CollectorTest.class.getName());
|
|
||||||
private EventBus bus;
|
|
||||||
|
|
||||||
private BlockingQueue<Message> q1;
|
|
||||||
private BlockingQueue<Message> q2;
|
|
||||||
private BlockingQueue<Message> q3;
|
|
||||||
|
|
||||||
private DataMessageMetadata m1;
|
|
||||||
private DataMessageMetadata m2;
|
|
||||||
private DataMessageMetadata m3;
|
|
||||||
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
bus = new EventBus();
|
|
||||||
|
|
||||||
|
|
||||||
// Create blocking queues
|
|
||||||
q1 = new LinkedBlockingQueue<Message>();
|
|
||||||
q2 = new LinkedBlockingQueue<Message>();
|
|
||||||
q3 = new LinkedBlockingQueue<Message>();
|
|
||||||
|
|
||||||
m1 = new DataMessageMetadata();
|
|
||||||
m1.getComponents().add(new ComponentMetadata("id2-0"));
|
|
||||||
m2 = new DataMessageMetadata();
|
|
||||||
m2.getComponents().add(new ComponentMetadata("id1-0"));
|
|
||||||
m3 = new DataMessageMetadata();
|
|
||||||
m3.getComponents().add(new ComponentMetadata("id0-0"));
|
|
||||||
|
|
||||||
// Dimension y 1,2,3
|
|
||||||
DataMessage m = new DataMessage();
|
|
||||||
m.getData().add(1d);
|
|
||||||
q1.put(m);
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(2d);
|
|
||||||
q1.put(m);
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(3d);
|
|
||||||
q1.put(m);
|
|
||||||
q1.put(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
// Dimension x 0.1,0.2
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.1);
|
|
||||||
q2.put(m);
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.2);
|
|
||||||
q2.put(m);
|
|
||||||
q2.put(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.1);
|
|
||||||
q2.put(m);
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.2);
|
|
||||||
q2.put(m);
|
|
||||||
q2.put(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.1);
|
|
||||||
q2.put(m);
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.2);
|
|
||||||
q2.put(m);
|
|
||||||
q2.put(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
// Dimension
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.01);
|
|
||||||
q3.put(m);
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.02);
|
|
||||||
q3.put(m);
|
|
||||||
q3.put(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.01);
|
|
||||||
q3.put(m);
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.02);
|
|
||||||
q3.put(m);
|
|
||||||
q3.put(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.01);
|
|
||||||
q3.put(m);
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.02);
|
|
||||||
q3.put(m);
|
|
||||||
q3.put(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.01);
|
|
||||||
q3.put(m);
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.02);
|
|
||||||
q3.put(m);
|
|
||||||
q3.put(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.01);
|
|
||||||
q3.put(m);
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.02);
|
|
||||||
q3.put(m);
|
|
||||||
q3.put(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.01);
|
|
||||||
q3.put(m);
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(0.02);
|
|
||||||
q3.put(m);
|
|
||||||
q3.put(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.aq.Collector#run()}.
|
|
||||||
* @throws InterruptedException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testRun() throws InterruptedException {
|
|
||||||
Collector collector = new Collector(bus);
|
|
||||||
collector.getQueues().add(new DataQueue(q1, m1));
|
|
||||||
collector.getQueues().add(new DataQueue(q2, m2));
|
|
||||||
collector.getQueues().add(new DataQueue(q3, m3));
|
|
||||||
|
|
||||||
// Check component metadata of output queue
|
|
||||||
int c=2;
|
|
||||||
for(ComponentMetadata cm: collector.getMetadata().getComponents()){
|
|
||||||
logger.info(cm.toString());
|
|
||||||
if(cm.getDimension() != c){
|
|
||||||
fail("Dimension number does not match required dimension number");
|
|
||||||
}
|
|
||||||
if(! cm.getId().equals("id"+c+"-0")){
|
|
||||||
fail("Id does not match required id");
|
|
||||||
}
|
|
||||||
c--;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// check wether messages arrive
|
|
||||||
bus.register(new Object(){
|
|
||||||
@Subscribe
|
|
||||||
public void onMessage(Message m){
|
|
||||||
if(m instanceof DataMessage){
|
|
||||||
DataMessage x = (DataMessage) m;
|
|
||||||
logger.info( x.toString() );
|
|
||||||
}
|
|
||||||
else if(m instanceof ControlMessage){
|
|
||||||
logger.info("---- "+m.toString()+" ----");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
collector.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,103 +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 gov.aps.jca.CAException;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import ch.psi.fda.TestChannels;
|
|
||||||
import ch.psi.fda.core.actions.JythonAction;
|
|
||||||
import ch.psi.fda.core.scripting.JythonParameterMappingChannel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class JythonActionTest {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.actions.JythonAction#execute()}.
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testExecute() throws CAException {
|
|
||||||
String script = "import math\ndef process(o):\n print o.getValue()\n o.setValue(-1.0)\n print o.getValue()\n val=math.cos(10.0) + math.sin(o.getValue())\n print val\n o.setValue(val)";
|
|
||||||
List<JythonParameterMappingChannel> mapping = new ArrayList<JythonParameterMappingChannel>();
|
|
||||||
mapping.add(new JythonParameterMappingChannel("o", TestChannels.ANALOG_OUT, Double.class));
|
|
||||||
JythonAction action = new JythonAction(script, mapping);
|
|
||||||
|
|
||||||
// Execute action
|
|
||||||
action.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether too much mappings are detected
|
|
||||||
* Test method for {@link ch.psi.fda.core.actions.JythonAction#execute()}.
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
@Test(expected=IllegalArgumentException.class)
|
|
||||||
public void testWrongMapping1() throws CAException {
|
|
||||||
String script = "import math\ndef process(o):\n print o.getValue()\n o.setValue(-1.0)\n print o.getValue()\n val=math.cos(10.0) + math.sin(o.getValue())\n print val\n o.setValue(val)";
|
|
||||||
List<JythonParameterMappingChannel> mapping = new ArrayList<JythonParameterMappingChannel>();
|
|
||||||
mapping.add(new JythonParameterMappingChannel("o", TestChannels.ANALOG_OUT, Double.class));
|
|
||||||
mapping.add(new JythonParameterMappingChannel("b", TestChannels.ANALOG_OUT, Double.class));
|
|
||||||
JythonAction action = new JythonAction(script, mapping);
|
|
||||||
|
|
||||||
// Execute action
|
|
||||||
action.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether a mapping to a wrong variable is detected
|
|
||||||
* Test method for {@link ch.psi.fda.core.actions.JythonAction#execute()}.
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
@Test(expected=IllegalArgumentException.class)
|
|
||||||
public void testWrongMapping2() throws CAException {
|
|
||||||
String script = "import math\ndef process(o):\n print o.getValue()\n o.setValue(-1.0)\n print o.getValue()\n val=math.cos(10.0) + math.sin(o.getValue())\n print val\n o.setValue(val)";
|
|
||||||
List<JythonParameterMappingChannel> mapping = new ArrayList<JythonParameterMappingChannel>();
|
|
||||||
mapping.add(new JythonParameterMappingChannel("ooo", TestChannels.ANALOG_OUT, Double.class));
|
|
||||||
JythonAction action = new JythonAction(script, mapping);
|
|
||||||
|
|
||||||
// Execute action
|
|
||||||
action.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright 2012 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;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import ch.psi.fda.TestConfiguration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class DistributedFileTest {
|
|
||||||
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(DistributedFileTest.class.getName());
|
|
||||||
|
|
||||||
DistributedFile file;
|
|
||||||
DistributedFile smbfile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
file = new DistributedFile("src/test/resources");
|
|
||||||
smbfile = new DistributedFile(TestConfiguration.getInstance().getSmbShare());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#getCanonicalPath()}.
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testGetCanonicalPath() throws IOException {
|
|
||||||
logger.info(file.getCanonicalPath());
|
|
||||||
logger.info(smbfile.getCanonicalPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#exists()}.
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testExists() throws IOException {
|
|
||||||
if(!file.exists()){
|
|
||||||
fail("Indicating wrong file status (file actually exists)");
|
|
||||||
}
|
|
||||||
if(!smbfile.exists()){
|
|
||||||
fail("Indicating wrong file status (file actually exists)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#isDirectory()}.
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testIsDirectory() throws IOException {
|
|
||||||
if(!file.isDirectory()){
|
|
||||||
fail("Indicating wrong file type (file is directory)");
|
|
||||||
}
|
|
||||||
if(!smbfile.isDirectory()){
|
|
||||||
fail("Indicating wrong file type (file is directory)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#listFiles()}.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testListFiles() {
|
|
||||||
// fail("Not yet implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#getName()}.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testGetName() {
|
|
||||||
logger.info(file.getName());
|
|
||||||
logger.info(smbfile.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#isFile()}.
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testIsFile() throws IOException {
|
|
||||||
if(file.isFile()){
|
|
||||||
fail("Indicating wrong file type (file is directory)");
|
|
||||||
}
|
|
||||||
if(smbfile.isFile()){
|
|
||||||
fail("Indicating wrong file type (file is directory)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#delete()}.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testDelete() {
|
|
||||||
// fail("Not yet implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.loops.DistributedFile#getInputStream()}.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testGetInputStream() {
|
|
||||||
// fail("Not yet implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,242 +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.loops;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import ch.psi.fda.TestConfiguration;
|
|
||||||
import ch.psi.fda.core.actors.OTFActuator;
|
|
||||||
import ch.psi.fda.core.loops.OTFLoop;
|
|
||||||
import ch.psi.fda.core.messages.ControlMessage;
|
|
||||||
import ch.psi.fda.core.messages.DataMessage;
|
|
||||||
import ch.psi.fda.core.messages.DataMessageMetadata;
|
|
||||||
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.ChannelBean;
|
|
||||||
import ch.psi.jcae.ChannelBeanFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class OTFLoopTest {
|
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
private static Logger logger = Logger.getLogger(OTFLoopTest.class.getName());
|
|
||||||
|
|
||||||
class TestCollector implements Runnable{
|
|
||||||
|
|
||||||
private final BlockingQueue<Message> queue;
|
|
||||||
public TestCollector(BlockingQueue<Message> queue){
|
|
||||||
this.queue = queue;
|
|
||||||
}
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see java.lang.Runnable#run()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
while(true){
|
|
||||||
Message m = queue.take();
|
|
||||||
if(m instanceof DataMessage){
|
|
||||||
DataMessage x = (DataMessage) m;
|
|
||||||
logger.fine( x.toString() );
|
|
||||||
}
|
|
||||||
else if(m instanceof ControlMessage){
|
|
||||||
logger.fine("---- "+m.toString()+" ----");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.log(Level.SEVERE, "An Exception occured while reading data from the data queue", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final TestConfiguration configuration = TestConfiguration.getInstance();
|
|
||||||
|
|
||||||
|
|
||||||
private OTFLoop loopZigZag;
|
|
||||||
private OTFLoop loop;
|
|
||||||
private ChannelBean<Integer> statusChannel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
|
|
||||||
statusChannel = ChannelBeanFactory.getFactory().createChannelBean(Integer.class, configuration.getOtfPrefix()+":USTAT", false);
|
|
||||||
|
|
||||||
OTFActuator actor = new OTFActuator("id", configuration.getMotor1(), null, 0, 8, 0.5, 0.5, 0);
|
|
||||||
OTFReadbackSensor s1 = new OTFReadbackSensor("id0");
|
|
||||||
OTFScalerChannelSensor s2 = new OTFScalerChannelSensor("id1", 0);
|
|
||||||
OTFScalerChannelSensor s3 = new OTFScalerChannelSensor("id2", 1);
|
|
||||||
MillisecondTimestampSensor s4 = new MillisecondTimestampSensor("id3");
|
|
||||||
OTFNamedChannelSensor s5 = new OTFNamedChannelSensor("id4", configuration.getAnalogIn1());
|
|
||||||
|
|
||||||
|
|
||||||
// ZigZag loop
|
|
||||||
loopZigZag = new OTFLoop(configuration.getOtfPrefix(), configuration.getServer(), configuration.getShare(), configuration.getSmbShare(), true);
|
|
||||||
loopZigZag.setActor(actor);
|
|
||||||
loopZigZag.getSensors().add(s1);
|
|
||||||
loopZigZag.getSensors().add(s2);
|
|
||||||
loopZigZag.getSensors().add(s3);
|
|
||||||
loopZigZag.getSensors().add(s4);
|
|
||||||
loopZigZag.getSensors().add(s5);
|
|
||||||
|
|
||||||
|
|
||||||
// Normal loop
|
|
||||||
loop = new OTFLoop(configuration.getOtfPrefix(), configuration.getServer(), configuration.getShare(), configuration.getSmbShare(), false);
|
|
||||||
loop.setActor(actor);
|
|
||||||
loop.getSensors().add(s1);
|
|
||||||
loop.getSensors().add(s2);
|
|
||||||
loop.getSensors().add(s3);
|
|
||||||
loop.getSensors().add(s4);
|
|
||||||
loop.getSensors().add(s5);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.loops.OTFLoop#execute()}.
|
|
||||||
* Test ordinary 1D OTF scan
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testExecute() throws CAException, InterruptedException {
|
|
||||||
|
|
||||||
Thread t = new Thread(new TestCollector(loop.getDataQueue().getQueue()));
|
|
||||||
t.start();
|
|
||||||
|
|
||||||
loop.prepare();
|
|
||||||
|
|
||||||
loop.execute();
|
|
||||||
|
|
||||||
loop.cleanup();
|
|
||||||
|
|
||||||
if(statusChannel.getValue()!=1){
|
|
||||||
fail("OTF C Logic status is not on INACTIVE");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.loops.OTFLoop#execute()}.
|
|
||||||
* Test OTF ZigZag mode
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testExecuteZigZag() throws CAException, InterruptedException {
|
|
||||||
|
|
||||||
Thread t = new Thread(new TestCollector(loopZigZag.getDataQueue().getQueue()));
|
|
||||||
t.start();
|
|
||||||
|
|
||||||
loopZigZag.prepare();
|
|
||||||
|
|
||||||
loopZigZag.execute();
|
|
||||||
loopZigZag.execute();
|
|
||||||
|
|
||||||
loopZigZag.cleanup();
|
|
||||||
|
|
||||||
if(statusChannel.getValue()!=1){
|
|
||||||
fail("OTF C Logic status is not on INACTIVE");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.loops.OTFLoop#execute()}.
|
|
||||||
* Test abort functionality while executing an OTF scan
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testExecuteAbort() throws CAException, InterruptedException {
|
|
||||||
|
|
||||||
// Data collector thread
|
|
||||||
Thread t = new Thread(new TestCollector(loop.getDataQueue().getQueue()));
|
|
||||||
t.start();
|
|
||||||
|
|
||||||
// Thread to simulate asynchronous abort operation
|
|
||||||
Thread t1 = new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
Thread.sleep(6000); // Wait some seconds before aborting the loop
|
|
||||||
loop.abort();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.log(Level.SEVERE, "An Exception occured while testing the abort functionality", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
t1.start();
|
|
||||||
|
|
||||||
loop.prepare();
|
|
||||||
|
|
||||||
loop.execute();
|
|
||||||
|
|
||||||
loop.cleanup();
|
|
||||||
|
|
||||||
if(statusChannel.getValue()!=1){
|
|
||||||
fail("OTF C Logic status is not on INACTIVE");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.loops.ActorSensorLoop#getDataMessageMetadata()}.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testGetDataMessageMetadata(){
|
|
||||||
DataMessageMetadata m = loop.getDataQueue().getDataMessageMetadata();
|
|
||||||
|
|
||||||
int numberOfSensors = 5;
|
|
||||||
if(m.getComponents().size() != numberOfSensors){
|
|
||||||
fail("Loop returned wrong number of components inside the data message metadata");
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean fail = false;
|
|
||||||
for(int x=0;x<numberOfSensors; x++){
|
|
||||||
if(! m.getComponents().get(x).getId().equals("id"+x)){
|
|
||||||
fail = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fail){
|
|
||||||
fail("Ids of the component metadata elements inside the data message metadata is not correct");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,136 +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.loops.cr;
|
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
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 ParallelCrlogicStreamMergeTest {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.loops.cr.ParallelCrlogicStreamMerge#merge()}.
|
|
||||||
* @throws InterruptedException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testMerge() throws InterruptedException {
|
|
||||||
|
|
||||||
BlockingQueue<Message> dataQueue = new LinkedBlockingQueue<Message>();
|
|
||||||
DataMessage dm = new DataMessage();
|
|
||||||
dm.getData().add(0.0035d);
|
|
||||||
dm.getData().add(10.000000123);
|
|
||||||
dataQueue.add(dm);
|
|
||||||
|
|
||||||
dm = new DataMessage();
|
|
||||||
dm.getData().add(0.015);
|
|
||||||
dm.getData().add(10.000000143);
|
|
||||||
dataQueue.add(dm);
|
|
||||||
|
|
||||||
dm = new DataMessage();
|
|
||||||
dm.getData().add(0.026);
|
|
||||||
dm.getData().add(10.000000163);
|
|
||||||
dataQueue.add(dm);
|
|
||||||
|
|
||||||
dataQueue.add(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
DataMessageMetadata dmm = new DataMessageMetadata();
|
|
||||||
dmm.getComponents().add(new ComponentMetadata("cractuator"));
|
|
||||||
dmm.getComponents().add(new ComponentMetadata("tstamp"));
|
|
||||||
DataQueue dqueue = new DataQueue(dataQueue, dmm);
|
|
||||||
|
|
||||||
|
|
||||||
BlockingQueue<Message> dataQueue2 = new LinkedBlockingQueue<Message>();
|
|
||||||
DataMessage dm2 = new DataMessage();
|
|
||||||
dm2.getData().add(9000d);
|
|
||||||
dm2.getData().add(122d);
|
|
||||||
dm2.getData().add(0.1d);
|
|
||||||
dataQueue2.add(dm2);
|
|
||||||
|
|
||||||
dm2 = new DataMessage();
|
|
||||||
dm2.getData().add(10000d);
|
|
||||||
dm2.getData().add(122d);
|
|
||||||
dm2.getData().add(1d);
|
|
||||||
dataQueue2.add(dm2);
|
|
||||||
|
|
||||||
dm2 = new DataMessage();
|
|
||||||
dm2.getData().add(10000d);
|
|
||||||
dm2.getData().add(153d);
|
|
||||||
dm2.getData().add(2d);
|
|
||||||
dataQueue2.add(dm2);
|
|
||||||
|
|
||||||
dm2 = new DataMessage();
|
|
||||||
dm2.getData().add(10000d);
|
|
||||||
dm2.getData().add(162d);
|
|
||||||
dm2.getData().add(3d);
|
|
||||||
dataQueue2.add(dm2);
|
|
||||||
|
|
||||||
dataQueue2.add(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
DataMessageMetadata dmm2 = new DataMessageMetadata();
|
|
||||||
dmm2.getComponents().add(new ComponentMetadata("milli"));
|
|
||||||
dmm2.getComponents().add(new ComponentMetadata("nano"));
|
|
||||||
dmm2.getComponents().add(new ComponentMetadata("sensor1"));
|
|
||||||
|
|
||||||
DataQueue dqueue2 = new DataQueue(dataQueue2, dmm2);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ParallelCrlogicStreamMerge streamMerge = new ParallelCrlogicStreamMerge(dqueue, dqueue2);
|
|
||||||
streamMerge.merge();
|
|
||||||
|
|
||||||
// Print merged queue
|
|
||||||
BlockingQueue<Message> queue = streamMerge.getDataQueue().getQueue();
|
|
||||||
Message m = queue.take();
|
|
||||||
while(! (m instanceof EndOfStreamMessage)){
|
|
||||||
System.out.println(m.toString());
|
|
||||||
m = queue.take();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,152 +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.loops.cr;
|
|
||||||
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import ch.psi.fda.TestConfiguration;
|
|
||||||
import ch.psi.fda.core.Sensor;
|
|
||||||
import ch.psi.fda.core.actors.OTFActuator;
|
|
||||||
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.sensors.MillisecondTimestampSensor;
|
|
||||||
import ch.psi.fda.core.sensors.OTFNamedChannelSensor;
|
|
||||||
import ch.psi.fda.core.sensors.OTFScalerChannelSensor;
|
|
||||||
import ch.psi.jcae.ChannelBeanFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ParallelCrlogicTest {
|
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
private static final Logger logger = Logger.getLogger(ParallelCrlogicTest.class.getName());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Ignore
|
|
||||||
@Test(timeout=60000)
|
|
||||||
public void testExecute() throws InterruptedException, CAException{
|
|
||||||
|
|
||||||
TestConfiguration c = TestConfiguration.getInstance();
|
|
||||||
|
|
||||||
boolean zigZag = false;
|
|
||||||
|
|
||||||
String readback = null;
|
|
||||||
double start = 0;
|
|
||||||
double end = 2;
|
|
||||||
double stepSize = 0.01;
|
|
||||||
double integrationTime = 0.01;
|
|
||||||
double additionalBacklash = 0;
|
|
||||||
|
|
||||||
List<Sensor> sensors = new ArrayList<Sensor>();
|
|
||||||
ChannelAccessDoubleSensor s2 = new ChannelAccessDoubleSensor("mot1", c.getMotor1()+".RVAL");
|
|
||||||
ChannelAccessDoubleSensor s1 = new ChannelAccessDoubleSensor("mot2", c.getMotor1()+".RBV");
|
|
||||||
ChannelAccessDoubleSensor s3 = new ChannelAccessDoubleSensor("mot2", "ARIDI-PCT:CURRENT");
|
|
||||||
|
|
||||||
sensors.add(s1);
|
|
||||||
sensors.add(s2);
|
|
||||||
sensors.add(s3);
|
|
||||||
|
|
||||||
ScrlogicLoop scrlogic = new ScrlogicLoop(sensors);
|
|
||||||
|
|
||||||
|
|
||||||
CrlogicLoop crlogic = new CrlogicLoop(c.getCrlogicPrefix(), c.getServer(), c.getShare(), c.getSmbShare(), zigZag);
|
|
||||||
crlogic.setActor(new OTFActuator("cmot", c.getMotor1(), readback, start, end, stepSize, integrationTime, additionalBacklash));
|
|
||||||
crlogic.getSensors().add(new OTFNamedChannelSensor("trigger", "TRIGGER0"));
|
|
||||||
crlogic.getSensors().add(new OTFScalerChannelSensor("scaler0", 0));
|
|
||||||
crlogic.getSensors().add(new OTFScalerChannelSensor("scaler1", 1));
|
|
||||||
crlogic.getSensors().add(new MillisecondTimestampSensor("timestamp"));
|
|
||||||
|
|
||||||
|
|
||||||
// Initialize scaler template
|
|
||||||
VSC16ScalerChannelsTemplate scalertemplate = new VSC16ScalerChannelsTemplate();
|
|
||||||
ChannelBeanFactory.getFactory().createChannelBeans(scalertemplate, c.getPrefixScaler());
|
|
||||||
|
|
||||||
|
|
||||||
ParallelCrlogic pcrlogic = new ParallelCrlogic(crlogic, scrlogic);
|
|
||||||
|
|
||||||
logger.info("Start scaler");
|
|
||||||
scalertemplate.getCommand().setValueNoWait(VSC16ScalerChannelsTemplate.Command.Count.ordinal());
|
|
||||||
|
|
||||||
pcrlogic.prepare();
|
|
||||||
pcrlogic.execute();
|
|
||||||
pcrlogic.cleanup();
|
|
||||||
|
|
||||||
logger.info("Stop scaler");
|
|
||||||
scalertemplate.getCommand().setValue(VSC16ScalerChannelsTemplate.Command.Done.ordinal());
|
|
||||||
|
|
||||||
System.out.println("PARALLEL CRLOGIC data:");
|
|
||||||
BlockingQueue<Message> queue = pcrlogic.getDataQueue().getQueue();
|
|
||||||
Message m = queue.take();
|
|
||||||
while(! (m instanceof EndOfStreamMessage)){
|
|
||||||
System.out.println(m.toString());
|
|
||||||
m = queue.take();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy scaler template
|
|
||||||
ChannelBeanFactory.getFactory().destroyChannelBeans(scalertemplate);
|
|
||||||
|
|
||||||
pcrlogic.destroy();
|
|
||||||
|
|
||||||
|
|
||||||
// System.out.println("CRLOGIC data:");
|
|
||||||
// BlockingQueue<Message> queue = crlogic.getDataQueue().getQueue();
|
|
||||||
// Message m = queue.take();
|
|
||||||
// while(! (m instanceof EndOfStreamMessage)){
|
|
||||||
// System.out.println(m.toString());
|
|
||||||
// m = queue.take();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// System.out.println("SCRLOGIC data:");
|
|
||||||
// queue = scrlogic.getDataQueue().getQueue();
|
|
||||||
// m = queue.take();
|
|
||||||
// while(! (m instanceof EndOfStreamMessage)){
|
|
||||||
// System.out.println(m.toString());
|
|
||||||
// m = queue.take();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,86 +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 static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import ch.psi.fda.TestChannels;
|
|
||||||
import ch.psi.fda.core.sensors.ChannelAccessDoubleArraySensor;
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
import ch.psi.jcae.ChannelBeanFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test class for the ScalarDoubleSensorChannelAccess class.
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ChannelAccessDoubleArraySensorTest {
|
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
private static Logger logger = Logger.getLogger(ChannelAccessDoubleArraySensorTest.class.getName());
|
|
||||||
|
|
||||||
private static final String channelName = TestChannels.DOUBLE_WAVEFORM;
|
|
||||||
private static final int numberOfPoints = 10;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.sensors.ChannelAccessDoubleSensor#read()}.
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testRead() throws CAException, InterruptedException {
|
|
||||||
ChannelAccessDoubleArraySensor sensor = new ChannelAccessDoubleArraySensor("id0", channelName, numberOfPoints);
|
|
||||||
ChannelBean<double[]> channel = ChannelBeanFactory.getFactory().createChannelBean(double[].class, channelName, false);
|
|
||||||
|
|
||||||
// Prepare sensor channel
|
|
||||||
double[] setValue = new double[] { 0.1,0.2,0.3,4,5,6,77,88,99,10.2};
|
|
||||||
channel.setValue(setValue);
|
|
||||||
|
|
||||||
// Get sensor readout value
|
|
||||||
double[] value = (double[]) sensor.read();
|
|
||||||
for(int i=0;i<setValue.length;i++){
|
|
||||||
logger.finest("Sensor value["+i+"]: "+value[i]);
|
|
||||||
if(Math.abs(value[i] - setValue[i])>0.0000001){ // The precision of the channel is 6
|
|
||||||
fail("Sensor readout value does not match actual value");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +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 static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import ch.psi.fda.TestChannels;
|
|
||||||
import ch.psi.fda.core.sensors.ChannelAccessDoubleSensor;
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
import ch.psi.jcae.ChannelBeanFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test class for the ScalarDoubleSensorChannelAccess class.
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ChannelAccessDoubleSensorTest {
|
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
private static Logger logger = Logger.getLogger(ChannelAccessDoubleSensorTest.class.getName());
|
|
||||||
|
|
||||||
private static final String channelName = TestChannels.ANALOG_OUT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.sensors.ChannelAccessDoubleSensor#read()}.
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testRead() throws CAException, InterruptedException {
|
|
||||||
ChannelAccessDoubleSensor sensor = new ChannelAccessDoubleSensor("id0", channelName);
|
|
||||||
ChannelBean<Double> channel = ChannelBeanFactory.getFactory().createChannelBean(Double.class, channelName, false);
|
|
||||||
|
|
||||||
// Prepare sensor channel
|
|
||||||
Double setValue = 0.1d;
|
|
||||||
channel.setValue(setValue);
|
|
||||||
|
|
||||||
// Get sensor readout value
|
|
||||||
Double value = (Double) sensor.read();
|
|
||||||
logger.finest("Sensor value: "+value);
|
|
||||||
if(!value.equals(setValue)){
|
|
||||||
fail("Sensor readout value does not match actual value");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,77 +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 static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import ch.psi.fda.TestChannels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test class for the ScalarDoubleSensorChannelAccess class.
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ChannelAccessStringSensorTest {
|
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
private static Logger logger = Logger.getLogger(ChannelAccessStringSensorTest.class.getName());
|
|
||||||
|
|
||||||
private static final String channelName = TestChannels.ANALOG_OUT+".NAME";
|
|
||||||
private static final String actualValue = TestChannels.ANALOG_OUT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.sensors.ChannelAccessDoubleSensor#read()}.
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testRead() throws CAException, InterruptedException {
|
|
||||||
ChannelAccessStringSensor sensor = new ChannelAccessStringSensor("id0", channelName);
|
|
||||||
|
|
||||||
// Get sensor readout value
|
|
||||||
String value = (String) sensor.read();
|
|
||||||
logger.info("Sensor value: "+value);
|
|
||||||
if(!value.equals(actualValue)){
|
|
||||||
fail("Sensor readout "+value+" value does not match actual value "+actualValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,133 +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 static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import gov.aps.jca.CAException;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import ch.psi.fda.TestChannels;
|
|
||||||
import ch.psi.fda.core.Action;
|
|
||||||
import ch.psi.fda.core.sensors.ChannelAccessDoubleSensor;
|
|
||||||
import ch.psi.fda.core.sensors.ComplexSensor;
|
|
||||||
import ch.psi.jcae.ChannelBean;
|
|
||||||
import ch.psi.jcae.ChannelBeanFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test class for the ScalarDoubleSensorChannelAccess class.
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ComplexSensorTest {
|
|
||||||
|
|
||||||
// Get Logger
|
|
||||||
private static Logger logger = Logger.getLogger(ComplexSensorTest.class.getName());
|
|
||||||
|
|
||||||
private static final String channelName = TestChannels.ANALOG_OUT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.core.sensors.ChannelAccessDoubleSensor#read()}.
|
|
||||||
* @throws CAException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testRead() throws CAException, InterruptedException {
|
|
||||||
|
|
||||||
final HashMap<String, Long> timestamps = new HashMap<String,Long>();
|
|
||||||
|
|
||||||
ChannelAccessDoubleSensor s1 = new ChannelAccessDoubleSensor("id0", channelName);
|
|
||||||
ComplexSensor sensor = new ComplexSensor("id2", s1);
|
|
||||||
|
|
||||||
// Add pre action
|
|
||||||
sensor.getPreActions().add(new Action() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() {
|
|
||||||
logger.info("PreAction");
|
|
||||||
timestamps.put("pre", System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void abort() {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add post action
|
|
||||||
sensor.getPostActions().add(new Action() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() {
|
|
||||||
logger.info("PostAction");
|
|
||||||
timestamps.put("post", System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void abort() {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create channel bean for test sensor channel
|
|
||||||
ChannelBean<Double> channel = ChannelBeanFactory.getFactory().createChannelBean(Double.class, channelName, false);
|
|
||||||
|
|
||||||
// Prepare sensor channel
|
|
||||||
Double setValue = 0.1d;
|
|
||||||
channel.setValue(setValue);
|
|
||||||
|
|
||||||
// Get sensor readout value
|
|
||||||
Double value = (Double) sensor.read();
|
|
||||||
|
|
||||||
logger.finest("Sensor value: "+value);
|
|
||||||
if(!value.equals(setValue)){
|
|
||||||
fail("Sensor readout value does not match actual value");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(timestamps.get("post")<timestamps.get("pre")){
|
|
||||||
fail("Post got executed before pre");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,303 +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.visualizer;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
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;
|
|
||||||
import ch.psi.fda.model.v1.MatrixPlot;
|
|
||||||
import ch.psi.fda.model.v1.PseudoPositioner;
|
|
||||||
import ch.psi.fda.model.v1.Visualization;
|
|
||||||
import ch.psi.fda.visualizer.Visualizer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All test cases in this test class are meant to be executed manually
|
|
||||||
* Remove @Ignore in front of the test function to be able to run it.
|
|
||||||
*
|
|
||||||
* @author ebner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class DataVisualizerTest {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.visualizer.Visualizer#run()}.
|
|
||||||
* @throws InterruptedException
|
|
||||||
*/
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
public void testRun() throws InterruptedException {
|
|
||||||
final BlockingQueue<Message> q = new LinkedBlockingQueue<Message>();
|
|
||||||
DataMessageMetadata dm = new DataMessageMetadata();
|
|
||||||
dm.getComponents().add(new ComponentMetadata("id1", 0));
|
|
||||||
dm.getComponents().add(new ComponentMetadata("id2", 0));
|
|
||||||
dm.getComponents().add(new ComponentMetadata("id3", 0));
|
|
||||||
DataQueue queue = new DataQueue(q,dm);
|
|
||||||
|
|
||||||
// Create visualization
|
|
||||||
List<Visualization> vlist = new ArrayList<Visualization>();
|
|
||||||
ch.psi.fda.model.v1.LinePlot p = new ch.psi.fda.model.v1.LinePlot();
|
|
||||||
p.setX("id1");
|
|
||||||
p.getY().add("id2");
|
|
||||||
vlist.add(p);
|
|
||||||
p = new ch.psi.fda.model.v1.LinePlot();
|
|
||||||
p.setX("id1");
|
|
||||||
p.getY().add("id3");
|
|
||||||
vlist.add(p);
|
|
||||||
|
|
||||||
// Create visualizer
|
|
||||||
Visualizer visualizer = new Visualizer(queue.getDataMessageMetadata(), vlist);
|
|
||||||
|
|
||||||
JFrame f = new JFrame();
|
|
||||||
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
||||||
f.setSize(600, 400);
|
|
||||||
JPanel pan = new JPanel();
|
|
||||||
for(JPanel pp: visualizer.getPlotPanels()){
|
|
||||||
pan.add(pp);
|
|
||||||
}
|
|
||||||
f.add(pan);
|
|
||||||
f.setVisible(true);
|
|
||||||
|
|
||||||
|
|
||||||
// Thread creating data
|
|
||||||
Thread t = new Thread(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
DataMessage m;
|
|
||||||
for(double t=0;t<4;t++){
|
|
||||||
for(double i =0;i<100;i=i+0.1){
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(i);
|
|
||||||
m.getData().add(t+Math.sin(i));
|
|
||||||
m.getData().add(t+Math.cos(i));
|
|
||||||
q.add(m);
|
|
||||||
try {
|
|
||||||
Thread.sleep(10);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException("Sleep interrupted",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
q.add(new StreamDelimiterMessage(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
q.add(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Start data thread
|
|
||||||
t.start();
|
|
||||||
|
|
||||||
|
|
||||||
// visualizer.visualize();
|
|
||||||
|
|
||||||
t.join();
|
|
||||||
|
|
||||||
Thread.sleep(10000);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
public void testRunArray() throws InterruptedException {
|
|
||||||
final BlockingQueue<Message> q = new LinkedBlockingQueue<Message>();
|
|
||||||
DataMessageMetadata dm = new DataMessageMetadata();
|
|
||||||
dm.getComponents().add(new ComponentMetadata("id1", 0));
|
|
||||||
DataQueue queue = new DataQueue(q,dm);
|
|
||||||
|
|
||||||
// Create visualization
|
|
||||||
List<Visualization> vlist = new ArrayList<Visualization>();
|
|
||||||
ch.psi.fda.model.v1.LinePlotArray p = new ch.psi.fda.model.v1.LinePlotArray();
|
|
||||||
p.getY().add("id1");
|
|
||||||
p.setMaxSeries(10);
|
|
||||||
vlist.add(p);
|
|
||||||
|
|
||||||
// Create visualizer
|
|
||||||
Visualizer visualizer = new Visualizer(queue.getDataMessageMetadata(), vlist);
|
|
||||||
|
|
||||||
JFrame f = new JFrame();
|
|
||||||
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
||||||
f.setSize(600, 400);
|
|
||||||
JPanel pan = new JPanel();
|
|
||||||
for(JPanel pp: visualizer.getPlotPanels()){
|
|
||||||
pan.add(pp);
|
|
||||||
}
|
|
||||||
f.add(pan);
|
|
||||||
f.setVisible(true);
|
|
||||||
|
|
||||||
|
|
||||||
// Thread creating data
|
|
||||||
Thread t = new Thread(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
DataMessage m;
|
|
||||||
int npoints = 10000;
|
|
||||||
for(double t=0;t<10;t++){
|
|
||||||
double[] values = new double[npoints];
|
|
||||||
|
|
||||||
for(int i=0;i<npoints;i++){
|
|
||||||
values[i]= Math.sin(i*0.01)+Math.cos(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(values);
|
|
||||||
q.add(m);
|
|
||||||
|
|
||||||
try {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException("Sleep interrupted",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
q.add(new StreamDelimiterMessage(0));
|
|
||||||
q.add(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Start data thread
|
|
||||||
t.start();
|
|
||||||
|
|
||||||
|
|
||||||
// visualizer.visualize();
|
|
||||||
|
|
||||||
t.join();
|
|
||||||
|
|
||||||
Thread.sleep(10000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link ch.psi.fda.visualizer.Visualizer#run()}.
|
|
||||||
* @throws InterruptedException
|
|
||||||
*/
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
public void testRun2D() throws InterruptedException {
|
|
||||||
final BlockingQueue<Message> q = new LinkedBlockingQueue<Message>();
|
|
||||||
DataMessageMetadata dm = new DataMessageMetadata();
|
|
||||||
dm.getComponents().add(new ComponentMetadata("id1", 1));
|
|
||||||
dm.getComponents().add(new ComponentMetadata("id2", 0));
|
|
||||||
dm.getComponents().add(new ComponentMetadata("id3", 0));
|
|
||||||
DataQueue queue = new DataQueue(q,dm);
|
|
||||||
|
|
||||||
List<Visualization> vlist = new ArrayList<Visualization>();
|
|
||||||
ch.psi.fda.model.v1.LinePlot p = new ch.psi.fda.model.v1.LinePlot();
|
|
||||||
p.setX("id2");
|
|
||||||
p.getY().add("id3");
|
|
||||||
vlist.add(p);
|
|
||||||
|
|
||||||
// 0d,4d,5,0d,100d,1001
|
|
||||||
|
|
||||||
PseudoPositioner pos = new PseudoPositioner();
|
|
||||||
pos.setId("id1");
|
|
||||||
pos.setCounts(5);
|
|
||||||
|
|
||||||
PseudoPositioner pos1 = new PseudoPositioner();
|
|
||||||
pos1.setId("id2");
|
|
||||||
pos1.setCounts(1000);
|
|
||||||
|
|
||||||
MatrixPlot mp = new MatrixPlot();
|
|
||||||
mp.setX(pos);
|
|
||||||
mp.setY(pos1);
|
|
||||||
mp.setZ("id3");
|
|
||||||
vlist.add(mp);
|
|
||||||
|
|
||||||
// Create visualizer
|
|
||||||
Visualizer visualizer = new Visualizer(queue.getDataMessageMetadata(), vlist);
|
|
||||||
|
|
||||||
JFrame f = new JFrame();
|
|
||||||
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
||||||
f.setSize(600, 400);
|
|
||||||
// f.add(plot.getPlotPanel());
|
|
||||||
JPanel pan = new JPanel();
|
|
||||||
for(JPanel pp: visualizer.getPlotPanels()){
|
|
||||||
pan.add(pp);
|
|
||||||
}
|
|
||||||
f.add(pan);
|
|
||||||
f.setVisible(true);
|
|
||||||
|
|
||||||
|
|
||||||
// Thread creating data
|
|
||||||
Thread t = new Thread(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
DataMessage m;
|
|
||||||
for(double t=1;t<=5;t++){
|
|
||||||
for(double i=1;i<=1000;i++){
|
|
||||||
m = new DataMessage();
|
|
||||||
m.getData().add(t);
|
|
||||||
m.getData().add(i);
|
|
||||||
m.getData().add(t+Math.cos(i));
|
|
||||||
q.add(m);
|
|
||||||
try {
|
|
||||||
Thread.sleep(10);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException("Sleep interrupted",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
q.add(new StreamDelimiterMessage(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
q.add(new EndOfStreamMessage());
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Start data thread
|
|
||||||
t.start();
|
|
||||||
|
|
||||||
|
|
||||||
// visualizer.visualize();
|
|
||||||
|
|
||||||
t.join();
|
|
||||||
|
|
||||||
Thread.sleep(10000);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# Specify the handlers to create in the root logger
|
|
||||||
##handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler
|
|
||||||
handlers = java.util.logging.ConsoleHandler
|
|
||||||
|
|
||||||
# Set the default logging level for the root logger
|
|
||||||
.level=ALL
|
|
||||||
|
|
||||||
# Set the default logging level for new ConsoleHandler instances
|
|
||||||
java.util.logging.ConsoleHandler.level=ALL
|
|
||||||
|
|
||||||
# Set the default formatter for new ConsoleHandler instances
|
|
||||||
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
|
|
||||||
|
|
||||||
# Set the default logging level for new FileHandler instances
|
|
||||||
##java.util.logging.FileHandler.level=ALL
|
|
||||||
|
|
||||||
# Set the default formatter for new ConsoleHandler instances
|
|
||||||
##java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
|
|
||||||
|
|
||||||
# Naming of the output file:
|
|
||||||
##java.util.logging.FileHandler.pattern=/Users/ebner/Workspace/Eclipse/workspace-xasec/ch.psi.x10/resources/logs/fda-%u.%g.log
|
|
||||||
|
|
||||||
# Limiting size of output file in bytes (10000kb):
|
|
||||||
##java.util.logging.FileHandler.limit=10000000
|
|
||||||
|
|
||||||
# Number of output files to cycle through, by appending an
|
|
||||||
# integer to the base file name:
|
|
||||||
##java.util.logging.FileHandler.count=10
|
|
||||||
|
|
||||||
# Set the default logging level for the logger named com.mycompany
|
|
||||||
ch.psi.fda.level=ALL
|
|
||||||
com.cosylab.epics.level=ALL
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# Test properties file
|
|
||||||
ch.psi.jcae.ContextFactory.addressList=129.129.130.255 129.129.130.37 129.129.145.26 129.129.130.88 129.129.130.142
|
|
||||||
|
|
||||||
ch.psi.jcae.ChannelBeanFactory.retries=4
|
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#Thu Mar 17 08:20:35 CET 2016
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-bin.zip
|
||||||
164
gradlew
vendored
Executable file
@@ -0,0 +1,164 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn ( ) {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die ( ) {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||||
|
if $cygwin ; then
|
||||||
|
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >&-
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >&-
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||||
|
function splitJvmOpts() {
|
||||||
|
JVM_OPTS=("$@")
|
||||||
|
}
|
||||||
|
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||||
|
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||||
90
gradlew.bat
vendored
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windowz variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
goto execute
|
||||||
|
|
||||||
|
:4NT_args
|
||||||
|
@rem Get arguments from the 4NT Shell from JP Software
|
||||||
|
set CMD_LINE_ARGS=%$
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
54
src/main/assembly/assembly.xml
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
|
||||||
|
|
||||||
|
|
||||||
|
<id>bin</id>
|
||||||
|
<!-- Generates a zip package containing the needed files -->
|
||||||
|
<formats>
|
||||||
|
<format>zip</format>
|
||||||
|
</formats>
|
||||||
|
|
||||||
|
<!-- Adds dependencies to zip package under lib directory -->
|
||||||
|
<dependencySets>
|
||||||
|
<dependencySet>
|
||||||
|
<outputDirectory>lib</outputDirectory>
|
||||||
|
<unpack>false</unpack>
|
||||||
|
</dependencySet>
|
||||||
|
</dependencySets>
|
||||||
|
|
||||||
|
<fileSets>
|
||||||
|
<!-- Adds startup scripts to the root directory of zip package -->
|
||||||
|
<fileSet>
|
||||||
|
<fileMode>0755</fileMode>
|
||||||
|
<directory>src/main/assembly/bin</directory>
|
||||||
|
<outputDirectory>bin</outputDirectory>
|
||||||
|
<includes>
|
||||||
|
<include>*</include>
|
||||||
|
</includes>
|
||||||
|
</fileSet>
|
||||||
|
<!-- <fileSet>
|
||||||
|
<directory>src/main/assembly/www</directory>
|
||||||
|
<outputDirectory>www</outputDirectory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*</include>
|
||||||
|
</includes>
|
||||||
|
</fileSet> -->
|
||||||
|
<!-- <fileSet>
|
||||||
|
<fileMode>0755</fileMode>
|
||||||
|
<directory>src/main/assembly/var</directory>
|
||||||
|
<outputDirectory>var</outputDirectory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*</include>
|
||||||
|
</includes>
|
||||||
|
</fileSet> -->
|
||||||
|
<!-- adds jar package to the root directory of zip package -->
|
||||||
|
<!-- <fileSet>
|
||||||
|
<directory>target</directory>
|
||||||
|
<outputDirectory></outputDirectory>
|
||||||
|
<includes>
|
||||||
|
<include>*.jar</include>
|
||||||
|
</includes>
|
||||||
|
</fileSet> -->
|
||||||
|
</fileSets>
|
||||||
|
</assembly>
|
||||||
40
src/main/assembly/bin/convert
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CURRENTDIR=`pwd`
|
||||||
|
|
||||||
|
# Resolve symlinks
|
||||||
|
BASEDIR=$0
|
||||||
|
while [ -h "$BASEDIR" ]; do
|
||||||
|
ls=`ls -ld "$BASEDIR"`
|
||||||
|
link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
|
||||||
|
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
|
||||||
|
BASEDIR="$link"
|
||||||
|
else
|
||||||
|
BASEDIR="`dirname "$BASEDIR"`/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
BASEDIR=`dirname "$BASEDIR"`
|
||||||
|
|
||||||
|
SCRIPTNAME=`basename ${0}`
|
||||||
|
|
||||||
|
APPLICATION_HOME=$BASEDIR/../..
|
||||||
|
|
||||||
|
LIB_DIR=`find $BASEDIR/../lib -name "*.jar"`
|
||||||
|
LIB_DIR=`echo $LIB_DIR | sed -e 's/ /:/g'`
|
||||||
|
|
||||||
|
CLASSPATH=${APPLICATION_HOME}/config/:$LIB_DIR
|
||||||
|
|
||||||
|
ARGUMENTS=
|
||||||
|
VM_ARGUMENTS=
|
||||||
|
for i in $@
|
||||||
|
do
|
||||||
|
if [ `expr $i : '-D.*'` != '0' ] ;then
|
||||||
|
# Extract VM options
|
||||||
|
VM_ARGUMENTS="$VM_ARGUMENTS $i"
|
||||||
|
else
|
||||||
|
ARGUMENTS="$ARGUMENTS $i"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Execute java
|
||||||
|
java -Xmx1024m -XX:MaxPermSize=128m -cp $CLASSPATH -Djava.util.logging.config.file=${APPLICATION_HOME}/config/logging.properties $VM_ARGUMENTS ch.psi.fda.ui.ConversionMain $ARGUMENTS
|
||||||
40
src/main/assembly/bin/scan
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CURRENTDIR=`pwd`
|
||||||
|
|
||||||
|
# Resolve symlinks
|
||||||
|
BASEDIR=$0
|
||||||
|
while [ -h "$BASEDIR" ]; do
|
||||||
|
ls=`ls -ld "$BASEDIR"`
|
||||||
|
link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
|
||||||
|
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
|
||||||
|
BASEDIR="$link"
|
||||||
|
else
|
||||||
|
BASEDIR="`dirname "$BASEDIR"`/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
BASEDIR=`dirname "$BASEDIR"`
|
||||||
|
|
||||||
|
SCRIPTNAME=`basename ${0}`
|
||||||
|
|
||||||
|
APPLICATION_HOME=$BASEDIR/../..
|
||||||
|
|
||||||
|
LIB_DIR=`find $BASEDIR/../lib -name "*.jar"`
|
||||||
|
LIB_DIR=`echo $LIB_DIR | sed -e 's/ /:/g'`
|
||||||
|
|
||||||
|
CLASSPATH=${APPLICATION_HOME}/config/:$LIB_DIR
|
||||||
|
|
||||||
|
ARGUMENTS=
|
||||||
|
VM_ARGUMENTS=
|
||||||
|
for i in $@
|
||||||
|
do
|
||||||
|
if [ `expr $i : '-D.*'` != '0' ] ;then
|
||||||
|
# Extract VM options
|
||||||
|
VM_ARGUMENTS="$VM_ARGUMENTS $i"
|
||||||
|
else
|
||||||
|
ARGUMENTS="$ARGUMENTS $i"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Execute java
|
||||||
|
java -Xmx1024m -XX:MaxPermSize=128m -Dch.psi.fda.home=${APPLICATION_HOME} -Djava.util.logging.config.file=${APPLICATION_HOME}/config/logging.properties $VM_ARGUMENTS -cp $CLASSPATH ch.psi.fda.ui.RemoteAcquisitionMain $ARGUMENTS
|
||||||
40
src/main/assembly/bin/scan_local
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CURRENTDIR=`pwd`
|
||||||
|
|
||||||
|
# Resolve symlinks
|
||||||
|
BASEDIR=$0
|
||||||
|
while [ -h "$BASEDIR" ]; do
|
||||||
|
ls=`ls -ld "$BASEDIR"`
|
||||||
|
link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
|
||||||
|
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
|
||||||
|
BASEDIR="$link"
|
||||||
|
else
|
||||||
|
BASEDIR="`dirname "$BASEDIR"`/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
BASEDIR=`dirname "$BASEDIR"`
|
||||||
|
|
||||||
|
SCRIPTNAME=`basename ${0}`
|
||||||
|
|
||||||
|
APPLICATION_HOME=$BASEDIR/../..
|
||||||
|
|
||||||
|
LIB_DIR=`find $BASEDIR/../lib -name "*.jar"`
|
||||||
|
LIB_DIR=`echo $LIB_DIR | sed -e 's/ /:/g'`
|
||||||
|
|
||||||
|
CLASSPATH=${APPLICATION_HOME}/config/:$LIB_DIR
|
||||||
|
|
||||||
|
ARGUMENTS=
|
||||||
|
VM_ARGUMENTS=
|
||||||
|
for i in $@
|
||||||
|
do
|
||||||
|
if [ `expr $i : '-D.*'` != '0' ] ;then
|
||||||
|
# Extract VM options
|
||||||
|
VM_ARGUMENTS="$VM_ARGUMENTS $i"
|
||||||
|
else
|
||||||
|
ARGUMENTS="$ARGUMENTS $i"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Execute java
|
||||||
|
java -Xmx1024m -XX:MaxPermSize=128m -Dch.psi.fda.home=${APPLICATION_HOME} -Djava.util.logging.config.file=${APPLICATION_HOME}/config/logging.properties $VM_ARGUMENTS -cp $CLASSPATH ch.psi.fda.ui.AcquisitionMain $ARGUMENTS
|
||||||
42
src/main/assembly/bin/server
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CURRENTDIR=`pwd`
|
||||||
|
|
||||||
|
# Resolve symlinks
|
||||||
|
BASEDIR=$0
|
||||||
|
while [ -h "$BASEDIR" ]; do
|
||||||
|
ls=`ls -ld "$BASEDIR"`
|
||||||
|
link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
|
||||||
|
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
|
||||||
|
BASEDIR="$link"
|
||||||
|
else
|
||||||
|
BASEDIR="`dirname "$BASEDIR"`/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
BASEDIR=`dirname "$BASEDIR"`
|
||||||
|
|
||||||
|
SCRIPTNAME=`basename ${0}`
|
||||||
|
|
||||||
|
APPLICATION_HOME=$BASEDIR/../..
|
||||||
|
|
||||||
|
LIB_DIR=`find $BASEDIR/../lib -name "*.jar"`
|
||||||
|
LIB_DIR=`echo $LIB_DIR | sed -e 's/ /:/g'`
|
||||||
|
|
||||||
|
CLASSPATH=${APPLICATION_HOME}/config/:$LIB_DIR
|
||||||
|
|
||||||
|
ARGUMENTS=
|
||||||
|
VM_ARGUMENTS=
|
||||||
|
for i in $@
|
||||||
|
do
|
||||||
|
if [ `expr $i : '-D.*'` != '0' ] ;then
|
||||||
|
# Extract VM options
|
||||||
|
VM_ARGUMENTS="$VM_ARGUMENTS $i"
|
||||||
|
else
|
||||||
|
ARGUMENTS="$ARGUMENTS $i"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
#HUB_BASE=$BASEDIR/../
|
||||||
|
#export HUB_BASE
|
||||||
|
java $VM_ARGUMENTS -cp $CLASSPATH -Dch.psi.fda.home=${APPLICATION_HOME} -Djava.util.logging.config.file=${APPLICATION_HOME}/config/logging.properties ch.psi.fda.rest.FdaServer $ARGUMENTS
|
||||||
40
src/main/assembly/bin/viewer
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CURRENTDIR=`pwd`
|
||||||
|
|
||||||
|
# Resolve symlinks
|
||||||
|
BASEDIR=$0
|
||||||
|
while [ -h "$BASEDIR" ]; do
|
||||||
|
ls=`ls -ld "$BASEDIR"`
|
||||||
|
link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
|
||||||
|
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
|
||||||
|
BASEDIR="$link"
|
||||||
|
else
|
||||||
|
BASEDIR="`dirname "$BASEDIR"`/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
BASEDIR=`dirname "$BASEDIR"`
|
||||||
|
|
||||||
|
SCRIPTNAME=`basename ${0}`
|
||||||
|
|
||||||
|
APPLICATION_HOME=$BASEDIR/../..
|
||||||
|
|
||||||
|
LIB_DIR=`find $BASEDIR/../lib -name "*.jar"`
|
||||||
|
LIB_DIR=`echo $LIB_DIR | sed -e 's/ /:/g'`
|
||||||
|
|
||||||
|
CLASSPATH=${APPLICATION_HOME}/config/:$LIB_DIR
|
||||||
|
|
||||||
|
ARGUMENTS=
|
||||||
|
VM_ARGUMENTS=
|
||||||
|
for i in $@
|
||||||
|
do
|
||||||
|
if [ `expr $i : '-D.*'` != '0' ] ;then
|
||||||
|
# Extract VM options
|
||||||
|
VM_ARGUMENTS="$VM_ARGUMENTS $i"
|
||||||
|
else
|
||||||
|
ARGUMENTS="$ARGUMENTS $i"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Execute java
|
||||||
|
java -Xmx1024m -XX:MaxPermSize=128m -cp $CLASSPATH -Djava.util.logging.config.file=${APPLICATION_HOME}/config/logging.properties $VM_ARGUMENTS ch.psi.fda.ui.VisualizationZMQMain $ARGUMENTS
|
||||||
40
src/main/assembly/bin/visualize
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CURRENTDIR=`pwd`
|
||||||
|
|
||||||
|
# Resolve symlinks
|
||||||
|
BASEDIR=$0
|
||||||
|
while [ -h "$BASEDIR" ]; do
|
||||||
|
ls=`ls -ld "$BASEDIR"`
|
||||||
|
link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
|
||||||
|
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
|
||||||
|
BASEDIR="$link"
|
||||||
|
else
|
||||||
|
BASEDIR="`dirname "$BASEDIR"`/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
BASEDIR=`dirname "$BASEDIR"`
|
||||||
|
|
||||||
|
SCRIPTNAME=`basename ${0}`
|
||||||
|
|
||||||
|
APPLICATION_HOME=$BASEDIR/../..
|
||||||
|
|
||||||
|
LIB_DIR=`find $BASEDIR/../lib -name "*.jar"`
|
||||||
|
LIB_DIR=`echo $LIB_DIR | sed -e 's/ /:/g'`
|
||||||
|
|
||||||
|
CLASSPATH=${APPLICATION_HOME}/config/:$LIB_DIR
|
||||||
|
|
||||||
|
ARGUMENTS=
|
||||||
|
VM_ARGUMENTS=
|
||||||
|
for i in $@
|
||||||
|
do
|
||||||
|
if [ `expr $i : '-D.*'` != '0' ] ;then
|
||||||
|
# Extract VM options
|
||||||
|
VM_ARGUMENTS="$VM_ARGUMENTS $i"
|
||||||
|
else
|
||||||
|
ARGUMENTS="$ARGUMENTS $i"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Execute java
|
||||||
|
java -Xmx1024m -XX:MaxPermSize=128m -cp $CLASSPATH -Djava.util.logging.config.file=${APPLICATION_HOME}/config/logging.properties $VM_ARGUMENTS ch.psi.fda.ui.VisualizationMain $ARGUMENTS
|
||||||
BIN
src/main/assembly/www/apple-touch-icon-114x114-precomposed.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/main/assembly/www/apple-touch-icon-144x144-precomposed.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/main/assembly/www/apple-touch-icon-57x57-precomposed.png
Normal file
|
After Width: | Height: | Size: 730 B |
BIN
src/main/assembly/www/apple-touch-icon-72x72-precomposed.png
Normal file
|
After Width: | Height: | Size: 854 B |
BIN
src/main/assembly/www/apple-touch-icon-precomposed.png
Normal file
|
After Width: | Height: | Size: 730 B |
BIN
src/main/assembly/www/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 730 B |
1109
src/main/assembly/www/css/bootstrap-responsive.css
vendored
Normal file
9
src/main/assembly/www/css/bootstrap-responsive.min.css
vendored
Normal file
6158
src/main/assembly/www/css/bootstrap.css
vendored
Normal file
9
src/main/assembly/www/css/bootstrap.min.css
vendored
Normal file
22
src/main/assembly/www/css/main.css
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Author's custom styles
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BIN
src/main/assembly/www/favicon.ico
Normal file
|
After Width: | Height: | Size: 766 B |
BIN
src/main/assembly/www/img/glyphicons-halflings-white.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
src/main/assembly/www/img/glyphicons-halflings.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
222
src/main/assembly/www/index.html
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
||||||
|
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
||||||
|
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
|
||||||
|
<!--[if gt IE 8]><!-->
|
||||||
|
<html class="no-js">
|
||||||
|
<!--<![endif]-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<title></title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link rel="stylesheet" href="css/bootstrap-responsive.min.css">
|
||||||
|
<link rel="stylesheet" href="css/main.css">
|
||||||
|
|
||||||
|
<script src="js/vendor/modernizr-2.6.2-respond-1.1.0.min.js"></script>
|
||||||
|
<script src="js/jquery-2.0.0.min.js"></script>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
var base = '../hub';
|
||||||
|
var stream;
|
||||||
|
|
||||||
|
function getVersion() {
|
||||||
|
$.get(base+'/version', function(data) {
|
||||||
|
$('#version').empty();
|
||||||
|
$('#version').append(data)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBeamlines() {
|
||||||
|
$.get(base, function(data) {
|
||||||
|
/* update beamlines selection */
|
||||||
|
|
||||||
|
$('#selectionBeamline').empty();
|
||||||
|
for (var i in data){
|
||||||
|
beamline = data[i];
|
||||||
|
$('#selectionBeamline').append('<option value="'+beamline+'">'+beamline+'</option>')
|
||||||
|
}
|
||||||
|
/* $('#selectionBeamline')[0].selectedIndex=0; */
|
||||||
|
connectStream(data[0]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateKeys(beamline, keys){
|
||||||
|
keytag = $('#beamlineKeys');
|
||||||
|
keytag.empty();
|
||||||
|
table='<table class="table table-hover"><thead><tr><td>Key</td><td>Value</td></tr></thead><tbody>';
|
||||||
|
|
||||||
|
for(k in keys){
|
||||||
|
table=table+'<tr><td>'+k+'</td><td>'+
|
||||||
|
'<div class="input-append">'+
|
||||||
|
'<input type="text" value="'+keys[k]+'" onchange="setKey(\''+beamline+'\',\''+k+'\',$(this).val())">'+
|
||||||
|
//'<button class="btn" type="button" onclick="setKey(\''+beamline+'\',\''+k+'\',$(this).prev().val())">Update</button>'+
|
||||||
|
'<button class="btn" type="button" onclick="deleteKey(\''+beamline+'\',\''+k+'\')">Delete</button>'+
|
||||||
|
'</div>'+
|
||||||
|
'</td></tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
table = table+'<tr>'+
|
||||||
|
'<td><input id="keyToAdd" type="text" placeholder="Key"></td>'+
|
||||||
|
'<td><div class="input-append">'+
|
||||||
|
'<input id="valueToAdd"type="text" placeholder="Value">'+
|
||||||
|
'<button class="btn" type="button" onclick="setKey(\''+beamline+'\',$(\'#keyToAdd\').val(),$(\'#valueToAdd\').val())">Add</button>'+
|
||||||
|
'</div></td>'+
|
||||||
|
'</tr>';
|
||||||
|
|
||||||
|
table = table+'</table></tbody>';
|
||||||
|
keytag.append(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
function connectStream(beamline) {
|
||||||
|
closeStream();
|
||||||
|
stream = new EventSource(base + '/' + beamline + '/stream');
|
||||||
|
stream.onmessage = function(event) {
|
||||||
|
keys=JSON.parse(event.data)
|
||||||
|
updateKeys(beamline, keys);
|
||||||
|
|
||||||
|
};
|
||||||
|
getKeys(beamline);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeStream() {
|
||||||
|
try {
|
||||||
|
stream.close();
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getKeys(beamline){
|
||||||
|
$.get(base+'/'+beamline+'/keys', function(data) {
|
||||||
|
updateKeys(beamline, data );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setKey(beamline, key, value){
|
||||||
|
$.ajax({
|
||||||
|
url: base+'/'+beamline+'/keys/'+key,
|
||||||
|
type: 'PUT',
|
||||||
|
data: value,
|
||||||
|
success: function(result) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteKey(beamline, key){
|
||||||
|
$.ajax({
|
||||||
|
url: base+'/'+beamline+'/keys/'+key,
|
||||||
|
type: 'DELETE',
|
||||||
|
success: function(result) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addBeamline(beamline){
|
||||||
|
getKeys(beamline); /*create beamline*/
|
||||||
|
getBeamlines();
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteBeamline(beamline){
|
||||||
|
$.ajax({
|
||||||
|
url: base+'/'+beamline,
|
||||||
|
type: 'DELETE',
|
||||||
|
success: function(result) {
|
||||||
|
getBeamlines(); /* Update beamline list */
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- <script>
|
||||||
|
var source = new EventSource('../server-sent-events/');
|
||||||
|
source.onmessage = function(e) {
|
||||||
|
$('#messagefield') = e.data;
|
||||||
|
};
|
||||||
|
</script> -->
|
||||||
|
|
||||||
|
<!--[if lt IE 7]>
|
||||||
|
<p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p>
|
||||||
|
<![endif]-->
|
||||||
|
|
||||||
|
<!-- This code is taken from http://twitter.github.com/bootstrap/examples/hero.html -->
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse"
|
||||||
|
data-target=".nav-collapse"> <span class="icon-bar"></span> <span
|
||||||
|
class="icon-bar"></span> <span class="icon-bar"></span>
|
||||||
|
</a> <a class="brand" href="#">hub</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<!-- Main hero unit for a primary marketing message or call to action -->
|
||||||
|
<!-- <div class="hero-unit">
|
||||||
|
<p>This is the central Hub administration page ...</p>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<!-- Example row of columns -->
|
||||||
|
<div class="row">
|
||||||
|
<div class="span5">
|
||||||
|
<h2>Key Group</h2>
|
||||||
|
<div>
|
||||||
|
<select id="selectionBeamline">
|
||||||
|
<!-- <option value="sydney">Sydney</option> -->
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div id="beamlineKeys"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="span5">
|
||||||
|
<h2>Key Group Management</h2>
|
||||||
|
<div class="input-append">
|
||||||
|
<input class="span2" id="appendedInputButton" placeholder="Key Group" type="text">
|
||||||
|
<button id="addBeamlineBtn" class="btn" type="button" onclick="addBeamline($(this).prev().val());$(this).prev().val('')">Add</button>
|
||||||
|
<button id="addBeamlineBtn" class="btn" type="button" onclick="deleteBeamline($(this).prev().prev().val());$(this).prev().prev().val('')">Delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>Hub - Version <span id='version'></span> - © Paul Scherrer Institute 2013</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- /container -->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/* update beamlines */
|
||||||
|
getVersion();
|
||||||
|
getBeamlines();
|
||||||
|
$('#selectionBeamline').change(function(){connectStream($('#selectionBeamline').val())});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
window.jQuery
|
||||||
|
|| document
|
||||||
|
.write('<script src="js/vendor/jquery-1.9.1.min.js"><\/script>')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="js/vendor/bootstrap.min.js"></script>
|
||||||
|
|
||||||
|
<script src="js/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
6
src/main/assembly/www/js/jquery-2.0.0.min.js
vendored
Normal file
1
src/main/assembly/www/js/main.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
2268
src/main/assembly/www/js/vendor/bootstrap.js
vendored
Normal file
6
src/main/assembly/www/js/vendor/bootstrap.min.js
vendored
Normal file
5
src/main/assembly/www/js/vendor/jquery-1.9.1.min.js
vendored
Normal file
11
src/main/assembly/www/js/vendor/modernizr-2.6.2-respond-1.1.0.min.js
vendored
Normal file
17
src/main/java/ch/psi/fda/DescriptorProvider.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package ch.psi.fda;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import ch.psi.fda.edescriptor.EDescriptor;
|
||||||
|
import ch.psi.fda.vdescriptor.VDescriptor;
|
||||||
|
|
||||||
|
public interface DescriptorProvider {
|
||||||
|
|
||||||
|
public void load(File ... files );
|
||||||
|
|
||||||
|
public EDescriptor getEDescriptor();
|
||||||
|
public VDescriptor getVDescriptor();
|
||||||
|
|
||||||
|
public Class<?> getEDescriptorClass();
|
||||||
|
|
||||||
|
}
|
||||||
28
src/main/java/ch/psi/fda/EContainer.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package ch.psi.fda;
|
||||||
|
|
||||||
|
public interface EContainer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize execution container like required resources, etc.
|
||||||
|
*/
|
||||||
|
public void initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the logic implemented by the ExecutionContainer
|
||||||
|
* Execute is a blocking function and must not return before the actual logic is executed
|
||||||
|
*/
|
||||||
|
public void execute();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to abort the execution of the logic
|
||||||
|
*/
|
||||||
|
public void abort();
|
||||||
|
|
||||||
|
public boolean isActive();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy execution container and free all allocated resources
|
||||||
|
*/
|
||||||
|
public void destroy();
|
||||||
|
|
||||||
|
}
|
||||||