This commit is contained in:
darksnake 2017-05-16 16:53:57 +03:00
parent 75bb7a9876
commit 1e58b43fd6
23 changed files with 490 additions and 467 deletions

View File

@ -17,8 +17,6 @@ package inr.numass.cryotemp;
import hep.dataforge.context.Context; import hep.dataforge.context.Context;
import hep.dataforge.control.collectors.RegularPointCollector; import hep.dataforge.control.collectors.RegularPointCollector;
import hep.dataforge.control.connections.Connection;
import hep.dataforge.control.connections.LoaderConnection;
import hep.dataforge.control.connections.Roles; import hep.dataforge.control.connections.Roles;
import hep.dataforge.control.connections.StorageConnection; import hep.dataforge.control.connections.StorageConnection;
import hep.dataforge.control.devices.PortSensor; import hep.dataforge.control.devices.PortSensor;
@ -36,10 +34,10 @@ import hep.dataforge.storage.api.PointLoader;
import hep.dataforge.storage.api.Storage; import hep.dataforge.storage.api.Storage;
import hep.dataforge.storage.commons.LoaderFactory; import hep.dataforge.storage.commons.LoaderFactory;
import hep.dataforge.tables.DataPoint; import hep.dataforge.tables.DataPoint;
import hep.dataforge.tables.PointListener;
import hep.dataforge.tables.TableFormat; import hep.dataforge.tables.TableFormat;
import hep.dataforge.tables.TableFormatBuilder; import hep.dataforge.tables.TableFormatBuilder;
import hep.dataforge.utils.DateTimeUtils; import hep.dataforge.utils.DateTimeUtils;
import inr.numass.control.StorageHelper;
import java.time.Duration; import java.time.Duration;
import java.util.Collection; import java.util.Collection;
@ -52,7 +50,6 @@ import java.util.Map;
* @author Alexander Nozik * @author Alexander Nozik
*/ */
@RoleDef(name = Roles.STORAGE_ROLE) @RoleDef(name = Roles.STORAGE_ROLE)
@RoleDef(name = Roles.POINT_LISTENER_ROLE)
@RoleDef(name = Roles.VIEW_ROLE, objectType = PKT8View.class) @RoleDef(name = Roles.VIEW_ROLE, objectType = PKT8View.class)
@ValueDef(name = "port", def = "virtual", info = "The name of the port for this PKT8") @ValueDef(name = "port", def = "virtual", info = "The name of the port for this PKT8")
public class PKT8Device extends PortSensor<PKT8Result> { public class PKT8Device extends PortSensor<PKT8Result> {
@ -67,6 +64,7 @@ public class PKT8Device extends PortSensor<PKT8Result> {
*/ */
private final Map<String, PKT8Channel> channels = new HashMap<>(); private final Map<String, PKT8Channel> channels = new HashMap<>();
private RegularPointCollector collector; private RegularPointCollector collector;
private StorageHelper storageHelper;
/** /**
* Cached values * Cached values
@ -82,6 +80,18 @@ public class PKT8Device extends PortSensor<PKT8Result> {
setMetaBase(meta); setMetaBase(meta);
} }
private PointLoader buildLoader(StorageConnection connection) {
Storage storage = connection.getStorage();
String suffix = DateTimeUtils.fileSuffix();
try {
return LoaderFactory.buildPointLoder(storage,
"cryotemp_" + suffix, "", "timestamp", getTableFormat());
} catch (StorageException e) {
throw new RuntimeException("Failed to build loader from storage", e);
}
}
@Override @Override
public void init() throws ControlException { public void init() throws ControlException {
@ -104,7 +114,7 @@ public class PKT8Device extends PortSensor<PKT8Result> {
//update parameters from meta //update parameters from meta
if (meta().hasValue("pga")) { if (meta().hasValue("pga")) {
getLogger().info("Setting dynamic range to " + meta().getInt("pga")); getLogger().info("Setting dynamic range to " + meta().getInt("pga"));
String response = getHandler().sendAndWait("g" + meta().getInt("pga"), null, 400).trim(); String response = getHandler().sendAndWait("g" + meta().getInt("pga"), 400, null).trim();
if (response.contains("=")) { if (response.contains("=")) {
updateState(PGA, Integer.parseInt(response.substring(4))); updateState(PGA, Integer.parseInt(response.substring(4)));
} else { } else {
@ -116,12 +126,11 @@ public class PKT8Device extends PortSensor<PKT8Result> {
setBUF(meta().getInt("abuf", 100)); setBUF(meta().getInt("abuf", 100));
// setting up the collector // setting up the collector
storageHelper = new StorageHelper(this, this::buildLoader);
Duration duration = Duration.parse(meta().getString("averagingDuration", "PT30S")); Duration duration = Duration.parse(meta().getString("averagingDuration", "PT30S"));
collector = new RegularPointCollector((DataPoint dp) -> { collector = new RegularPointCollector((DataPoint dp) -> {
forEachConnection(Roles.POINT_LISTENER_ROLE, PointListener.class, listener -> {
getLogger().debug("Point measurement complete. Pushing..."); getLogger().debug("Point measurement complete. Pushing...");
listener.accept(dp); storageHelper.push(dp);
});
}, duration, channels.values().stream().map(PKT8Channel::getName).toArray(String[]::new)); }, duration, channels.values().stream().map(PKT8Channel::getName).toArray(String[]::new));
} }
@ -140,26 +149,9 @@ public class PKT8Device extends PortSensor<PKT8Result> {
return format; return format;
} }
@Override
public synchronized void connect(Connection connection, String... roles) {
super.connect(connection, roles);
if (connection instanceof StorageConnection) {
//TODO add loader cache to remove loaders on disconnect
Storage storage = ((StorageConnection) connection).getStorage();
String suffix = DateTimeUtils.fileSuffix();
try {
PointLoader pointLoader = LoaderFactory.buildPointLoder(storage,
"cryotemp_" + suffix, "", "timestamp", getTableFormat());
this.connect(new LoaderConnection(pointLoader), Roles.POINT_LISTENER_ROLE);
} catch (StorageException e) {
getLogger().error("Failed to build loader from storage {}", storage.getName());
}
}
}
@Override @Override
public void shutdown() throws ControlException { public void shutdown() throws ControlException {
storageHelper.close();
if (collector != null) { if (collector != null) {
collector.clear(); collector.clear();
collector = null; collector = null;
@ -190,7 +182,7 @@ public class PKT8Device extends PortSensor<PKT8Result> {
getLogger().info("Setting avaraging buffer size to " + buf); getLogger().info("Setting avaraging buffer size to " + buf);
String response; String response;
try { try {
response = getHandler().sendAndWait("b" + buf, null, 400).trim(); response = getHandler().sendAndWait("b" + buf, 400, null).trim();
} catch (Exception ex) { } catch (Exception ex) {
response = ex.getMessage(); response = ex.getMessage();
} }
@ -279,7 +271,7 @@ public class PKT8Device extends PortSensor<PKT8Result> {
getLogger().info("Setting sampling rate to " + spsToStr(sps)); getLogger().info("Setting sampling rate to " + spsToStr(sps));
String response; String response;
try { try {
response = getHandler().sendAndWait("v" + sps, null, 400).trim(); response = getHandler().sendAndWait("v" + sps, 400, null).trim();
} catch (Exception ex) { } catch (Exception ex) {
response = ex.getMessage(); response = ex.getMessage();
} }
@ -333,6 +325,8 @@ public class PKT8Device extends PortSensor<PKT8Result> {
return super.startMeasurement(); return super.startMeasurement();
} }
public class PKT8Measurement extends AbstractMeasurement<PKT8Result> implements PortHandler.PortController { public class PKT8Measurement extends AbstractMeasurement<PKT8Result> implements PortHandler.PortController {
final PortHandler handler; final PortHandler handler;

View File

@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.time.Instant; import java.time.Instant;
import java.util.Comparator;
import java.util.ResourceBundle; import java.util.ResourceBundle;
/** /**
@ -98,7 +99,7 @@ public class PKT8View extends DeviceViewConnection<PKT8Device> implements Initia
lastUpdateLabel.setText(time.toString()); lastUpdateLabel.setText(time.toString());
table.getItems().removeIf(it -> it.channel.equals(result.channel)); table.getItems().removeIf(it -> it.channel.equals(result.channel));
table.getItems().add(result); table.getItems().add(result);
table.getItems().sort((o1, o2) -> o1.channel.compareTo(o2.channel)); table.getItems().sort(Comparator.comparing(o -> o.channel));
}); });
} }
@ -131,7 +132,7 @@ public class PKT8View extends DeviceViewConnection<PKT8Device> implements Initia
stopMeasurement(); stopMeasurement();
} }
} catch (ControlException ex) { } catch (ControlException ex) {
evaluateDeviceException(getDevice(), "Failed to start or stop device", ex); getDevice().getLogger().error("Failed to start or stop device", ex);
} }
} }
} }

View File

@ -122,11 +122,11 @@ public class MagnetController implements PortHandler.PortController {
private String talk(String request) throws PortException { private String talk(String request) throws PortException {
try { try {
return port.sendAndWait(request + "\r", null, timeout).trim(); return port.sendAndWait(request + "\r", timeout, null).trim();
} catch (PortTimeoutException tex) { } catch (PortTimeoutException tex) {
//Single retry on timeout //Single retry on timeout
LoggerFactory.getLogger(getClass()).warn("A timeout exception for request '" + request + "'. Making another atempt."); LoggerFactory.getLogger(getClass()).warn("A timeout exception for request '" + request + "'. Making another atempt.");
return port.sendAndWait(request + "\r", null, timeout).trim(); return port.sendAndWait(request + "\r", timeout, null).trim();
} }
} }

View File

@ -60,7 +60,7 @@ public class Talk {
while (!"exit".equals(nextString)) { while (!"exit".equals(nextString)) {
try { try {
Instant start = DateTimeUtils.now(); Instant start = DateTimeUtils.now();
String answer = handler.sendAndWait(nextString + "\r", null, 1000); String answer = handler.sendAndWait(nextString + "\r", 1000, null);
//String answer = controller.request(nextString); //String answer = controller.request(nextString);
System.out.printf("ANSWER (latency = %s): %s;%n", Duration.between(start, DateTimeUtils.now()), answer.trim()); System.out.printf("ANSWER (latency = %s): %s;%n", Duration.between(start, DateTimeUtils.now()), answer.trim());
} catch (PortException ex) { } catch (PortException ex) {

View File

@ -39,6 +39,7 @@ import hep.dataforge.tables.TableFormat;
import hep.dataforge.tables.TableFormatBuilder; import hep.dataforge.tables.TableFormatBuilder;
import hep.dataforge.utils.DateTimeUtils; import hep.dataforge.utils.DateTimeUtils;
import hep.dataforge.values.Value; import hep.dataforge.values.Value;
import inr.numass.control.StorageHelper;
import java.time.Instant; import java.time.Instant;
import java.util.*; import java.util.*;
@ -259,8 +260,7 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
String response = getHandler().sendAndWait( String response = getHandler().sendAndWait(
request, request,
(String str) -> str.trim().startsWith(commandName), TIMEOUT, (String str) -> str.trim().startsWith(commandName)
TIMEOUT
); );
return new MspResponse(response); return new MspResponse(response);
} }
@ -404,8 +404,7 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
private class PeakJumpMeasurement extends AbstractMeasurement<DataPoint> { private class PeakJumpMeasurement extends AbstractMeasurement<DataPoint> {
private final Map<Integer, Double> measurement = new ConcurrentSkipListMap<>(); private final Map<Integer, Double> measurement = new ConcurrentSkipListMap<>();
private final Map<StorageConnection, PointLoader> loaderMap = new HashMap<>(); private StorageHelper helper = new StorageHelper(MspDevice.this,this::makeLoader);
// private List<PointLoader> loaders = new ArrayList<>();
private final Meta meta; private final Meta meta;
private Map<Integer, String> peakMap; private Map<Integer, String> peakMap;
private double zero = 0; private double zero = 0;
@ -481,13 +480,7 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
boolean stop = sendAndWait("ScanStop").isOK(); boolean stop = sendAndWait("ScanStop").isOK();
afterStop(); afterStop();
responseDelegate = null; responseDelegate = null;
loaderMap.values().forEach(loader -> { helper.close();
try {
loader.close();
} catch (Exception ex) {
getLogger().error("Failed to close Loader", ex);
}
});
return stop; return stop;
} catch (PortException ex) { } catch (PortException ex) {
throw new MeasurementException(ex); throw new MeasurementException(ex);
@ -520,24 +513,15 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
MapPoint.Builder point = new MapPoint.Builder(); MapPoint.Builder point = new MapPoint.Builder();
point.putValue("timestamp", time); point.putValue("timestamp", time);
measurement.entrySet().forEach((entry) -> { measurement.forEach((key, value1) -> {
double val = entry.getValue(); double val = value1;
point.putValue(peakMap.get(entry.getKey()), val); point.putValue(peakMap.get(key), val);
}); });
mspListener.acceptScan(measurement); mspListener.acceptScan(measurement);
//pushing data to storage
if (getState("storing").booleanValue()) { helper.push(point.build());
forEachConnection(Roles.STORAGE_ROLE, StorageConnection.class, (StorageConnection connection) -> {
PointLoader pl = loaderMap.computeIfAbsent(connection, this::makeLoader);
try {
pl.push(point.build());
} catch (StorageException ex) {
getLogger().error("Push to loader failed", ex);
}
});
}
} }
measurement.clear(); measurement.clear();

View File

@ -0,0 +1,51 @@
package inr.numass.control;
import hep.dataforge.control.connections.StorageConnection;
import hep.dataforge.control.devices.AbstractDevice;
import hep.dataforge.exceptions.StorageException;
import hep.dataforge.storage.api.PointLoader;
import hep.dataforge.tables.DataPoint;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
/**
* A helper to store points in multiple loaders
* Created by darksnake on 16-May-17.
*/
public class StorageHelper implements AutoCloseable {
private final AbstractDevice device;
private final Map<StorageConnection, PointLoader> loaderMap = new HashMap<>();
private final Function<StorageConnection, PointLoader> loaderFactory;
public StorageHelper(AbstractDevice device, Function<StorageConnection, PointLoader> loaderFactory) {
this.device = device;
this.loaderFactory = loaderFactory;
}
public void push(DataPoint point) {
if (!device.hasState("storing") || device.getState("storing").booleanValue()) {
device.forEachConnection("storage", StorageConnection.class, connection -> {
PointLoader pl = loaderMap.computeIfAbsent(connection, loaderFactory);
try {
pl.push(point);
} catch (StorageException ex) {
device.getLogger().error("Push to loader failed", ex);
}
});
}
}
@Override
public void close() {
loaderMap.values().forEach(it -> {
try {
it.close();
} catch (Exception ex) {
device.getLogger().error("Failed to close Loader", ex);
}
});
}
}

View File

@ -1,10 +1,10 @@
apply plugin: 'application' apply plugin: 'application'
version = "0.4.2" version = "0.5.0"
if (!hasProperty('mainClass')) { if (!hasProperty('mainClass')) {
//ext.mainClass = 'inr.numass.readvac.app.ConsoleVac' //ext.mainClass = 'inr.numass.readvac.app.ConsoleVac'
ext.mainClass = 'inr.numass.readvac.app.ReadVac' ext.mainClass = 'inr.numass.readvac.fx.ReadVac'
} }
mainClassName = mainClass mainClassName = mainClass

View File

@ -10,6 +10,7 @@ import hep.dataforge.control.devices.PortSensor;
import hep.dataforge.control.measurements.Measurement; import hep.dataforge.control.measurements.Measurement;
import hep.dataforge.control.measurements.SimpleMeasurement; import hep.dataforge.control.measurements.SimpleMeasurement;
import hep.dataforge.control.ports.PortHandler; import hep.dataforge.control.ports.PortHandler;
import hep.dataforge.description.ValueDef;
import hep.dataforge.exceptions.ControlException; import hep.dataforge.exceptions.ControlException;
import hep.dataforge.meta.Meta; import hep.dataforge.meta.Meta;
@ -21,12 +22,13 @@ import java.util.regex.Pattern;
/** /**
* @author Alexander Nozik * @author Alexander Nozik
*/ */
public class VITVacDevice extends PortSensor<Double> { @ValueDef(name = "address", type = "NUMBER", def = "1", info = "A modbus address")
public class MeradatVacDevice extends PortSensor<Double> {
public VITVacDevice() { public MeradatVacDevice() {
} }
public VITVacDevice(Context context, Meta meta) { public MeradatVacDevice(Context context, Meta meta) {
setContext(context); setContext(context);
setMetaBase(meta); setMetaBase(meta);
} }
@ -40,7 +42,7 @@ public class VITVacDevice extends PortSensor<Double> {
@Override @Override
protected Measurement<Double> createMeasurement() { protected Measurement<Double> createMeasurement() {
return new CMVacMeasurement(); return new MeradatMeasurement(meta().getInt("adress", 1));
} }
@Override @Override
@ -48,41 +50,31 @@ public class VITVacDevice extends PortSensor<Double> {
return meta().getString("type", "Vit vacuumeter"); return meta().getString("type", "Vit vacuumeter");
} }
@Override private class MeradatMeasurement extends SimpleMeasurement<Double> {
protected Object computeState(String stateName) throws ControlException {
if (getHandler() == null) { // private static final String VIT_QUERY = ":010300000002FA\r\n";
notifyError("No port connection", null);
return null; private final String query;
private final Pattern response;
private final String base;
public MeradatMeasurement(int address) {
base = String.format(":%02d", address);
query = base + "0300000002FA\r\n";
response = Pattern.compile(base + "0304(\\w{4})(\\w{4})..\r\n");
} }
notifyError("State not found: " + stateName, null);
return null;
//TODO add connection check here
// switch (stateName) {
// case "connection":
// return !talk("T?").isEmpty();
// default:
// notifyError("State not found: " + stateName, null);
// return null;
// }
}
private class CMVacMeasurement extends SimpleMeasurement<Double> {
private static final String VIT_QUERY = ":010300000002FA\r\n";
@Override @Override
protected synchronized Double doMeasure() throws Exception { protected synchronized Double doMeasure() throws Exception {
String answer = getHandler().sendAndWait(VIT_QUERY, timeout()); String answer = getHandler().sendAndWait(query, timeout(), phrase -> phrase.startsWith(base));
if (answer.isEmpty()) { if (answer.isEmpty()) {
this.progressUpdate("No signal"); this.progressUpdate("No signal");
updateState("connection", false); updateState("connection", false);
return null; return null;
} else { } else {
Matcher match = Pattern.compile(":010304(\\w{4})(\\w{4})..\r\n").matcher(answer); Matcher match = response.matcher(answer);
if (match.matches()) { if (match.matches()) {
double base = (double) (Integer.parseInt(match.group(1), 16)) / 10d; double base = (double) (Integer.parseInt(match.group(1), 16)) / 10d;
@ -95,7 +87,8 @@ public class VITVacDevice extends PortSensor<Double> {
this.progressUpdate("OK"); this.progressUpdate("OK");
updateState("connection", true); updateState("connection", true);
return res.doubleValue(); return res.doubleValue();
} else { }
else {
this.progressUpdate("Wrong answer: " + answer); this.progressUpdate("Wrong answer: " + answer);
updateState("connection", false); updateState("connection", false);
return null; return null;

View File

@ -8,21 +8,28 @@ package inr.numass.readvac;
import hep.dataforge.control.collectors.PointCollector; import hep.dataforge.control.collectors.PointCollector;
import hep.dataforge.control.collectors.ValueCollector; import hep.dataforge.control.collectors.ValueCollector;
import hep.dataforge.control.connections.Roles; import hep.dataforge.control.connections.Roles;
import hep.dataforge.control.connections.StorageConnection;
import hep.dataforge.control.devices.annotations.RoleDef; import hep.dataforge.control.devices.annotations.RoleDef;
import hep.dataforge.control.devices.annotations.StateDef;
import hep.dataforge.control.measurements.AbstractMeasurement; import hep.dataforge.control.measurements.AbstractMeasurement;
import hep.dataforge.control.measurements.Measurement; import hep.dataforge.control.measurements.Measurement;
import hep.dataforge.control.measurements.Sensor; import hep.dataforge.control.measurements.Sensor;
import hep.dataforge.exceptions.ControlException; import hep.dataforge.exceptions.ControlException;
import hep.dataforge.exceptions.MeasurementException; import hep.dataforge.exceptions.MeasurementException;
import hep.dataforge.storage.api.PointLoader;
import hep.dataforge.storage.commons.LoaderFactory;
import hep.dataforge.tables.DataPoint; import hep.dataforge.tables.DataPoint;
import hep.dataforge.tables.MapPoint; import hep.dataforge.tables.MapPoint;
import hep.dataforge.tables.PointListener; import hep.dataforge.tables.PointListener;
import hep.dataforge.tables.TableFormatBuilder;
import hep.dataforge.utils.DateTimeUtils; import hep.dataforge.utils.DateTimeUtils;
import hep.dataforge.values.Value; import hep.dataforge.values.Value;
import hep.dataforge.values.ValueType;
import inr.numass.control.StorageHelper;
import java.time.Instant; import java.time.Instant;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@ -31,25 +38,30 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
*
* @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a> * @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a>
*/ */
@RoleDef(name = Roles.STORAGE_ROLE, objectType = PointListener.class, info = "Storage for acquired points") @RoleDef(name = Roles.STORAGE_ROLE, objectType = PointListener.class, info = "Storage for acquired points")
@StateDef(name = "storing", writable = true, info = "Define if this device is currently writes to storage")
public class VacCollectorDevice extends Sensor<DataPoint> { public class VacCollectorDevice extends Sensor<DataPoint> {
private Map<String, Sensor> sensorMap = new HashMap<>(); private Map<String, Sensor<Double>> sensorMap = new LinkedHashMap<>();
public void setSensors(Sensor... sensors) { public void setSensors(Iterable<Sensor<Double>> sensors) {
sensorMap = new LinkedHashMap<>(sensors.length); sensorMap = new LinkedHashMap<>();
for (Sensor sensor : sensors) { for (Sensor<Double> sensor : sensors) {
sensorMap.put(sensor.getName(), sensor); sensorMap.put(sensor.getName(), sensor);
} }
} }
@SuppressWarnings("unchecked")
public void setSensors(Sensor... sensors) {
setSensors(Arrays.asList(sensors));
}
@Override @Override
public void init() throws ControlException { public void init() throws ControlException {
super.init(); super.init();
for (Sensor s : sensorMap.values()) { for (Sensor<Double> s : sensorMap.values()) {
s.init(); s.init();
} }
} }
@ -87,39 +99,34 @@ public class VacCollectorDevice extends Sensor<DataPoint> {
} }
} }
public Collection<Sensor> getSensors() { public Collection<Sensor<Double>> getSensors() {
return sensorMap.values(); return sensorMap.values();
} }
public void setSensors(Iterable<Sensor> sensors) {
sensorMap = new LinkedHashMap<>();
for (Sensor sensor : sensors) {
sensorMap.put(sensor.getName(), sensor);
}
}
private class VacuumMeasurement extends AbstractMeasurement<DataPoint> { private class VacuumMeasurement extends AbstractMeasurement<DataPoint> {
private final ValueCollector collector = new PointCollector(this::result, sensorMap.keySet()); private final ValueCollector collector = new PointCollector(this::result, sensorMap.keySet());
private ScheduledExecutorService executor; private ScheduledExecutorService executor;
private ScheduledFuture<?> currentTask; private ScheduledFuture<?> currentTask;
private StorageHelper helper;
@Override @Override
public void start() { public void start() {
helper = new StorageHelper(VacCollectorDevice.this, this::buildLoader);
executor = Executors executor = Executors
.newSingleThreadScheduledExecutor((Runnable r) -> new Thread(r, "VacuumMeasurement thread")); .newSingleThreadScheduledExecutor((Runnable r) -> new Thread(r, "VacuumMeasurement thread"));
currentTask = executor.scheduleWithFixedDelay(() -> { currentTask = executor.scheduleWithFixedDelay(() -> {
sensorMap.entrySet().stream().parallel().forEach((entry) -> { sensorMap.values().forEach((sensor) -> {
try { try {
Object value; Object value;
if (entry.getValue().meta().getBoolean("disabled", false)) { if(sensor.optBooleanState("disabled").orElse(false)){
value = null; value = null;
} else { } else {
value = entry.getValue().read(); value = sensor.read();
} }
collector.put(entry.getKey(), value); collector.put(sensor.getName(), value);
} catch (Exception ex) { } catch (Exception ex) {
collector.put(entry.getKey(), Value.NULL); collector.put(sensor.getName(), Value.NULL);
} }
}); });
}, 0, meta().getInt("delay", 5000), TimeUnit.MILLISECONDS); }, 0, meta().getInt("delay", 5000), TimeUnit.MILLISECONDS);
@ -133,10 +140,19 @@ public class VacCollectorDevice extends Sensor<DataPoint> {
}); });
} }
private PointLoader buildLoader(StorageConnection connection) {
TableFormatBuilder format = new TableFormatBuilder().setType("timestamp", ValueType.TIME);
getSensors().forEach((s) -> {
format.setType(s.getName(), ValueType.NUMBER);
});
return LoaderFactory.buildPointLoder(connection.getStorage(), "vactms", "", "timestamp", format.build());
}
private DataPoint terminator() { private DataPoint terminator() {
MapPoint.Builder p = new MapPoint.Builder(); MapPoint.Builder p = new MapPoint.Builder();
p.putValue("timestamp", DateTimeUtils.now()); p.putValue("timestamp", DateTimeUtils.now());
sensorMap.keySet().stream().forEach((n) -> { sensorMap.keySet().forEach((n) -> {
p.putValue(n, null); p.putValue(n, null);
}); });
return p.build(); return p.build();
@ -151,6 +167,7 @@ public class VacCollectorDevice extends Sensor<DataPoint> {
currentTask.cancel(force); currentTask.cancel(force);
executor.shutdown(); executor.shutdown();
currentTask = null; currentTask = null;
helper.close();
afterStop(); afterStop();
} }
return isRunning; return isRunning;

View File

@ -0,0 +1,46 @@
package inr.numass.readvac;
import hep.dataforge.context.Context;
import hep.dataforge.control.devices.DeviceFactory;
import hep.dataforge.control.measurements.Sensor;
import hep.dataforge.meta.Meta;
import java.util.List;
import java.util.stream.Collectors;
/**
* A factory for vacuum measurements collector
* Created by darksnake on 16-May-17.
*/
public class VacDeviceFactory implements DeviceFactory<VacCollectorDevice> {
@Override
public String getType() {
return "numass:vac";
}
public Sensor<Double> buildSensor(Context context, Meta sensorConfig) {
switch (sensorConfig.getString("sensorType", "")) {
case "mks":
return new MKSVacDevice(context, sensorConfig);
case "CM32":
return new CM32Device(context, sensorConfig);
case "meradat":
return new MeradatVacDevice(context, sensorConfig);
case "baratron":
return new MKSBaratronDevice(context, sensorConfig);
default:
throw new RuntimeException("Unknown vacuum sensor type");
}
}
@Override
public VacCollectorDevice build(Context context, Meta config) {
List<Sensor<Double>> sensors = config.getMetaList("sensor").stream()
.map(sensorConfig -> buildSensor(context, sensorConfig)).collect(Collectors.toList());
VacCollectorDevice collector = new VacCollectorDevice();
collector.configure(config);
collector.setSensors(sensors);
return collector;
}
}

View File

@ -5,78 +5,90 @@
*/ */
package inr.numass.readvac.fx; package inr.numass.readvac.fx;
import ch.qos.logback.classic.Level; import hep.dataforge.control.devices.DeviceFactory;
import hep.dataforge.context.Context;
import hep.dataforge.control.connections.DeviceConnection;
import hep.dataforge.control.connections.Roles;
import hep.dataforge.exceptions.ControlException;
import hep.dataforge.meta.Meta; import hep.dataforge.meta.Meta;
import inr.numass.control.DeviceViewConnection; import inr.numass.control.DeviceViewConnection;
import inr.numass.control.NumassControlUtils; import inr.numass.control.NumassControlApplication;
import inr.numass.readvac.VacCollectorDevice; import inr.numass.readvac.VacCollectorDevice;
import javafx.application.Application; import inr.numass.readvac.VacDeviceFactory;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.slf4j.LoggerFactory;
import java.util.Locale; import java.util.Objects;
/** /**
* @author Alexander Nozik * @author Alexander Nozik
*/ */
public class ReadVac extends Application { public class ReadVac extends NumassControlApplication<VacCollectorDevice> {
private VacCollectorDevice device;
@Override @Override
public void start(Stage primaryStage) throws Exception { protected DeviceViewConnection<VacCollectorDevice> buildView() {
Locale.setDefault(Locale.US);// чтобы отделение десятичных знаков было точкой return VacCollectorView.build();
ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
rootLogger.setLevel(Level.INFO);
DeviceViewConnection<VacCollectorDevice> controller = buildView();
Scene scene = new Scene(controller.getPane());
primaryStage.setScene(scene);
primaryStage.show();
device = setupDevice(controller);
primaryStage.setTitle("Numass vacuum measurements");
}
private VacCollectorDevice setupDevice(DeviceConnection<VacCollectorDevice> controller) {
Meta config = NumassControlUtils.getConfig(this)
.orElseGet(() -> NumassControlUtils.readResourceMeta("/config/devices.xml"));
Context ctx = NumassControlUtils.setupContext(config);
Meta mspConfig = NumassControlUtils.findDeviceMeta(config, this::acceptDevice)
.orElseThrow(() -> new RuntimeException("Device configuration not found"));
try {
D d = getDeviceFactory().build(ctx, mspConfig);
d.init();
NumassControlUtils.connectStorage(d, config);
Platform.runLater(() -> {
d.connect(controller, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE);
});
return d;
} catch (ControlException e) {
throw new RuntimeException("Failed to build device", e);
}
} }
@Override @Override
public void stop() throws Exception { protected DeviceFactory<VacCollectorDevice> getDeviceFactory() {
super.stop(); return new VacDeviceFactory();
if (device != null) {
device.shutdown();
device.getContext().close();
} }
@Override
protected void setupStage(Stage stage, VacCollectorDevice device) {
stage.setTitle("Numass vacuum measurements");
} }
@Override
protected boolean acceptDevice(Meta meta) {
return Objects.equals(meta.getString("type", ""), "numass:vac");
}
// private VacCollectorDevice device;
//
// @Override
// public void start(Stage primaryStage) throws Exception {
// Locale.setDefault(Locale.US);// чтобы отделение десятичных знаков было точкой
// ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
// rootLogger.setLevel(Level.INFO);
//
// DeviceViewConnection<VacCollectorDevice> controller = buildView();
//
// Scene scene = new Scene(controller.getPane());
//
// primaryStage.setScene(scene);
// primaryStage.show();
//
// device = setupDevice(controller);
// primaryStage.setTitle("Numass vacuum measurements");
// }
//
//
// private VacCollectorDevice setupDevice(DeviceConnection<VacCollectorDevice> controller) {
// Meta config = NumassControlUtils.getConfig(this)
// .orElseGet(() -> NumassControlUtils.readResourceMeta("/config/devices.xml"));
//
// Context ctx = NumassControlUtils.setupContext(config);
// Meta mspConfig = NumassControlUtils.findDeviceMeta(config, this::acceptDevice)
// .orElseThrow(() -> new RuntimeException("Device configuration not found"));
//
//
// try {
// D d = getDeviceFactory().build(ctx, mspConfig);
// d.init();
// NumassControlUtils.connectStorage(d, config);
// Platform.runLater(() -> {
// d.connect(controller, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE);
// });
// return d;
// } catch (ControlException e) {
// throw new RuntimeException("Failed to build device", e);
// }
// }
//
// @Override
// public void stop() throws Exception {
// super.stop();
// if (device != null) {
// device.shutdown();
// device.getContext().close();
// }
// }
// VacCollectorView controller; // VacCollectorView controller;
// Logger logger = LoggerFactory.getLogger("ReadVac"); // Logger logger = LoggerFactory.getLogger("ReadVac");
@ -92,7 +104,7 @@ public class ReadVac extends Application {
// public void start(Stage primaryStage) throws Exception { // public void start(Stage primaryStage) throws Exception {
// String configFileName = getParameters().getNamed().get("config"); // String configFileName = getParameters().getNamed().get("config");
// if (configFileName == null) { // if (configFileName == null) {
// configFileName = "vac-config.xml"; // configFileName = "devices.xml";
// } // }
// File configFile = new File(configFileName); // File configFile = new File(configFileName);
// Meta config; // Meta config;
@ -104,54 +116,7 @@ public class ReadVac extends Application {
// //
// Context context = Global.instance(); // Context context = Global.instance();
// //
// Meta p1Meta = config.getMeta("p1",
// new MetaBuilder("p1")
// .setValue("port", "com::/dev/ttyUSB0")
// .setValue("name", "P1")
// .build()
// );
//
// Sensor<Double> p1 = new MKSVacDevice(context, p1Meta);
//
// Meta p2Meta = config.getMeta("p2",
// new MetaBuilder("p2")
// .setValue("port", "tcp::192.168.111.32:4002")
// .setValue("name", "P2")
// .build()
// );
//
// Sensor<Double> p2 = new CM32Device(context,p2Meta);
//
// Meta p3Meta = config.getMeta("p3",
// new MetaBuilder("p3")
// .setValue("port", "tcp::192.168.111.32:4003")
// .setValue("name", "P3")
// .build()
// );
//
// Sensor<Double> p3 = new CM32Device(context, p3Meta);
//
// Meta pxMeta = config.getMeta("px",
// new MetaBuilder("px")
// .setValue("port", "tcp::192.168.111.32:4003")
// .setValue("name", "Px")
// .build()
// );
//
// Sensor<Double> px = new VITVacDevice(context,pxMeta);
//
// Meta baratronMeta = config.getMeta("baratron",
// new MetaBuilder("baratron")
// .setValue("port", "tcp::192.168.111.33:4004")
// .setValue("name", "Baratron")
// .build()
// );
//
// Sensor<Double> baratron = new MKSBaratronDevice(context,baratronMeta);
//
// VacCollectorDevice collector = new VacCollectorDevice();
// collector.configure(config);
// collector.setSensors(p1, p2, p3, px, baratron);
// collector.init(); // collector.init();
// //
// FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/VacCollector.fxml")); // FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/VacCollector.fxml"));

View File

@ -5,6 +5,7 @@
*/ */
package inr.numass.readvac.fx; package inr.numass.readvac.fx;
import hep.dataforge.control.connections.Roles;
import hep.dataforge.control.measurements.Sensor; import hep.dataforge.control.measurements.Sensor;
import hep.dataforge.control.virtual.Virtual; import hep.dataforge.control.virtual.Virtual;
import inr.numass.readvac.VacCollectorDevice; import inr.numass.readvac.VacCollectorDevice;
@ -60,7 +61,7 @@ public class TestVac extends Application {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/VacCollector.fxml")); FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/VacCollector.fxml"));
loader.load(); loader.load();
controller = loader.getController(); controller = loader.getController();
controller.setDevice(collector); collector.connect(controller, Roles.VIEW_ROLE);
Scene scene = new Scene(loader.getRoot(), 800, 600); Scene scene = new Scene(loader.getRoot(), 800, 600);

View File

@ -5,10 +5,8 @@
*/ */
package inr.numass.readvac.fx; package inr.numass.readvac.fx;
import hep.dataforge.control.connections.LoaderConnection;
import hep.dataforge.control.connections.Roles; import hep.dataforge.control.connections.Roles;
import hep.dataforge.control.devices.Device; import hep.dataforge.control.devices.Device;
import hep.dataforge.control.devices.DeviceListener;
import hep.dataforge.control.measurements.Measurement; import hep.dataforge.control.measurements.Measurement;
import hep.dataforge.control.measurements.MeasurementListener; import hep.dataforge.control.measurements.MeasurementListener;
import hep.dataforge.control.measurements.Sensor; import hep.dataforge.control.measurements.Sensor;
@ -23,33 +21,29 @@ import hep.dataforge.plots.data.TimePlottableGroup;
import hep.dataforge.plots.fx.FXPlotFrame; import hep.dataforge.plots.fx.FXPlotFrame;
import hep.dataforge.plots.fx.PlotContainer; import hep.dataforge.plots.fx.PlotContainer;
import hep.dataforge.plots.jfreechart.JFreeChartFrame; import hep.dataforge.plots.jfreechart.JFreeChartFrame;
import hep.dataforge.storage.api.PointLoader;
import hep.dataforge.storage.api.Storage;
import hep.dataforge.storage.commons.LoaderFactory;
import hep.dataforge.storage.commons.StorageManager;
import hep.dataforge.tables.DataPoint; import hep.dataforge.tables.DataPoint;
import hep.dataforge.tables.TableFormatBuilder;
import hep.dataforge.values.Value; import hep.dataforge.values.Value;
import hep.dataforge.values.ValueType; import inr.numass.control.DeviceViewConnection;
import inr.numass.readvac.VacCollectorDevice; import inr.numass.readvac.VacCollectorDevice;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.ChoiceBox; import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton; import javafx.scene.control.ToggleButton;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.stage.DirectoryChooser;
import javafx.util.Duration; import javafx.util.Duration;
import org.controlsfx.control.Notifications; import org.controlsfx.control.Notifications;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -58,24 +52,33 @@ import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.function.BiFunction;
/** /**
* FXML Controller class * A view controller for Vac collector
* *
* @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a> * @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a>
*/ */
public class VacCollectorView implements Initializable, DeviceListener, MeasurementListener<DataPoint> { public class VacCollectorView extends DeviceViewConnection<VacCollectorDevice> implements Initializable, MeasurementListener<DataPoint> {
public static VacCollectorView build() {
try {
FXMLLoader loader = new FXMLLoader(VacCollectorView.class.getResource("/fxml/VacCollector.fxml"));
loader.load();
return loader.getController();
} catch (IOException e) {
throw new Error(e);
}
}
private final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ISO_LOCAL_DATE_TIME; private final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
private final String[] intervalNames = {"1 sec", "5 sec", "10 sec", "30 sec", "1 min"}; private final String[] intervalNames = {"1 sec", "5 sec", "10 sec", "30 sec", "1 min"};
private final int[] intervals = {1000, 5000, 10000, 30000, 60000}; private final int[] intervals = {1000, 5000, 10000, 30000, 60000};
private final List<VacuumeterView> views = new ArrayList<>(); private final List<VacuumeterView> views = new ArrayList<>();
// private LoaderConnection storageConnection;
private VacCollectorDevice device;
private TimePlottableGroup plottables; private TimePlottableGroup plottables;
// private BiFunction<VacCollectorDevice, Storage, PointLoader> loaderFactory;
@FXML
private BorderPane root;
@FXML @FXML
private AnchorPane plotHolder; private AnchorPane plotHolder;
@FXML @FXML
@ -91,6 +94,12 @@ public class VacCollectorView implements Initializable, DeviceListener, Measurem
@FXML @FXML
private ToggleButton logButton; private ToggleButton logButton;
@Override
public Node getFXNode() {
return root;
}
/** /**
* Initializes the controller class. * Initializes the controller class.
*/ */
@ -118,24 +127,19 @@ public class VacCollectorView implements Initializable, DeviceListener, Measurem
Notifications.create().darkStyle().hideAfter(Duration.seconds(2d)).text(message).showError(); Notifications.create().darkStyle().hideAfter(Duration.seconds(2d)).text(message).showError();
} }
public VacCollectorDevice getDevice() { @Override
return device; public void open(VacCollectorDevice device) throws Exception {
} super.open(device);
public void setDevice(VacCollectorDevice device) {
this.device = device;
device.getSensors().stream().map((sensor) -> { device.getSensors().stream().map((sensor) -> {
VacuumeterView controller; VacuumeterView view;
if (sensor.meta().getBoolean("powerButton", false)) { if (sensor.hasState("power")) {
controller = new PoweredVacuumeterView(); view = new PoweredVacuumeterView();
} else { } else {
controller = new VacuumeterView(); view = new VacuumeterView();
} }
sensor.connect(controller, Roles.DEVICE_LISTENER_ROLE, Roles.MEASUREMENT_CONSUMER_ROLE); sensor.connect(view, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE, Roles.MEASUREMENT_CONSUMER_ROLE);
return controller; return view;
}).forEach((controller) -> { }).forEach(views::add);
views.add(controller);
});
setupView(); setupView();
} }
@ -153,13 +157,6 @@ public class VacCollectorView implements Initializable, DeviceListener, Measurem
public void onMeasurementResult(Measurement<DataPoint> measurement, DataPoint result, Instant time) { public void onMeasurementResult(Measurement<DataPoint> measurement, DataPoint result, Instant time) {
if (plottables != null) { if (plottables != null) {
plottables.put(result); plottables.put(result);
//workaround to fix autorange problem
// for (String n : result.names()) {
// Value val = result.getValue(n);
// if (val.doubleValue() > 0) {
// plottables.put(n, val);
// }
// }
} }
Platform.runLater(() -> timeLabel.setText(TIME_FORMAT.format(LocalDateTime.ofInstant(time, ZoneOffset.UTC)))); Platform.runLater(() -> timeLabel.setText(TIME_FORMAT.format(LocalDateTime.ofInstant(time, ZoneOffset.UTC))));
} }
@ -167,11 +164,11 @@ public class VacCollectorView implements Initializable, DeviceListener, Measurem
private void setupView() { private void setupView() {
vacBoxHolder.getChildren().clear(); vacBoxHolder.getChildren().clear();
plottables = new TimePlottableGroup(); plottables = new TimePlottableGroup();
views.forEach((controller) -> { views.forEach((view) -> {
vacBoxHolder.getChildren().add(controller.getComponent()); vacBoxHolder.getChildren().add(view.getComponent());
TimePlottable plot = new TimePlottable(controller.getTitle(), TimePlottable plot = new TimePlottable(view.getTitle(),
controller.getName()); view.getDevice().getName());
plot.configure(controller.meta()); plot.configure(view.getDevice().meta());
plottables.add(plot); plottables.add(plot);
}); });
plottables.setValue("thickness", 3); plottables.setValue("thickness", 3);
@ -208,10 +205,6 @@ public class VacCollectorView implements Initializable, DeviceListener, Measurem
} }
} }
public void setLoaderFactory(BiFunction<VacCollectorDevice, Storage, PointLoader> loaderFactory) {
this.loaderFactory = loaderFactory;
}
@FXML @FXML
private void onStartStopToggle(ActionEvent event) { private void onStartStopToggle(ActionEvent event) {
if (startStopButton.isSelected() != getDevice().isMeasuring()) { if (startStopButton.isSelected() != getDevice().isMeasuring()) {
@ -221,7 +214,7 @@ public class VacCollectorView implements Initializable, DeviceListener, Measurem
try { try {
startMeasurement(); startMeasurement();
} catch (ControlException ex) { } catch (ControlException ex) {
getLogger().error("Failed to start measurement", ex); getDevice().getLogger().error("Failed to start measurement", ex);
startStopButton.setSelected(false); startStopButton.setSelected(false);
} }
} else { } else {
@ -233,56 +226,51 @@ public class VacCollectorView implements Initializable, DeviceListener, Measurem
@FXML @FXML
private void onStoreToggle(ActionEvent event) { private void onStoreToggle(ActionEvent event) {
if (storeButton.isSelected()) { getDevice().setState("storing", storeButton.isSelected());
//creating storage on UI thread // if (storeButton.isSelected()) {
if (!device.meta().hasMeta("storage")) { // //creating storage on UI thread
getLogger().info("Storage not defined. Starting storage selection dialog"); // if (!device.meta().hasMeta("storage")) {
DirectoryChooser chooser = new DirectoryChooser(); // getLogger().info("Storage not defined. Starting storage selection dialog");
File storageDir = chooser.showDialog(plotHolder.getScene().getWindow()); // DirectoryChooser chooser = new DirectoryChooser();
if (storageDir == null) { // File storageDir = chooser.showDialog(plotHolder.getScene().getWindow());
storeButton.setSelected(false); // if (storageDir == null) {
throw new RuntimeException("User canceled directory selection"); // storeButton.setSelected(false);
} // throw new RuntimeException("User canceled directory selection");
device.getConfig().putNode(new MetaBuilder("storage") // }
.putValue("path", storageDir.getAbsolutePath())); // device.getConfig().putNode(new MetaBuilder("storage")
} // .putValue("path", storageDir.getAbsolutePath()));
Meta storageConfig = device.meta().getMeta("storage"); // }
Storage localStorage = StorageManager.buildFrom(device.getContext()) // Meta storageConfig = device.meta().getMeta("storage");
.buildStorage(storageConfig); // Storage localStorage = StorageManager.buildFrom(device.getContext())
//Start storage creation on non-UI thread // .buildStorage(storageConfig);
new Thread(() -> { // //Start storage creation on non-UI thread
try { // new Thread(() -> {
// try {
PointLoader loader; //
// PointLoader loader;
if (loaderFactory != null) { //
loader = loaderFactory.apply(device, localStorage); // if (loaderFactory != null) {
} else { // loader = loaderFactory.apply(device, localStorage);
TableFormatBuilder format = new TableFormatBuilder().setType("timestamp", ValueType.TIME); // } else {
device.getSensors().forEach((s) -> { // TableFormatBuilder format = new TableFormatBuilder().setType("timestamp", ValueType.TIME);
format.setType(s.getName(), ValueType.NUMBER); // device.getSensors().forEach((s) -> {
}); // format.setType(s.getName(), ValueType.NUMBER);
// });
loader = LoaderFactory.buildPointLoder(localStorage, "vactms", //
device.meta().getString("storage.shelf", ""), "timestamp", format.build()); // loader = LoaderFactory.buildPointLoder(localStorage, "vactms",
} // device.meta().getString("storage.shelf", ""), "timestamp", format.build());
storageConnection = new LoaderConnection(loader); // }
device.connect(storageConnection, Roles.STORAGE_ROLE); // storageConnection = new LoaderConnection(loader);
} catch (Exception ex) { // device.connect(storageConnection, Roles.STORAGE_ROLE);
getLogger().error("Failed to start data storing", ex); // } catch (Exception ex) {
storeButton.setSelected(false); // getLogger().error("Failed to start data storing", ex);
} // storeButton.setSelected(false);
}).start(); // }
} else if (storageConnection != null) { // }).start();
device.disconnect(storageConnection); // } else if (storageConnection != null) {
} // device.disconnect(storageConnection);
// }
} }
/**
* @return the logger
*/
private Logger getLogger() {
return device.getLogger();
}
} }

View File

@ -5,16 +5,13 @@
*/ */
package inr.numass.readvac.fx; package inr.numass.readvac.fx;
import hep.dataforge.control.connections.DeviceConnection;
import hep.dataforge.control.connections.MeasurementConsumer; import hep.dataforge.control.connections.MeasurementConsumer;
import hep.dataforge.control.devices.Device; import hep.dataforge.control.devices.Device;
import hep.dataforge.control.devices.DeviceListener;
import hep.dataforge.control.measurements.Measurement; import hep.dataforge.control.measurements.Measurement;
import hep.dataforge.control.measurements.MeasurementListener; import hep.dataforge.control.measurements.MeasurementListener;
import hep.dataforge.meta.Meta; import hep.dataforge.control.measurements.Sensor;
import hep.dataforge.meta.Metoid;
import hep.dataforge.names.Named;
import hep.dataforge.values.Value; import hep.dataforge.values.Value;
import inr.numass.control.DeviceViewConnection;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML; import javafx.fxml.FXML;
@ -22,6 +19,7 @@ import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import org.controlsfx.control.ToggleSwitch; import org.controlsfx.control.ToggleSwitch;
@ -37,7 +35,7 @@ import java.util.ResourceBundle;
/** /**
* @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a> * @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a>
*/ */
public class VacuumeterView extends DeviceConnection implements DeviceListener, MeasurementConsumer, MeasurementListener<Double>, Initializable, Named, Metoid { public class VacuumeterView extends DeviceViewConnection<Sensor<Double>> implements MeasurementConsumer, MeasurementListener<Double>, Initializable {
private static final DecimalFormat FORMAT = new DecimalFormat("0.###E0"); private static final DecimalFormat FORMAT = new DecimalFormat("0.###E0");
private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ISO_LOCAL_TIME; private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ISO_LOCAL_TIME;
@ -45,27 +43,24 @@ public class VacuumeterView extends DeviceConnection implements DeviceListener,
protected Node node; protected Node node;
@FXML @FXML
Label deviceNameLabel; private BorderPane root;
@FXML @FXML
Label unitLabel; protected Label deviceNameLabel;
@FXML @FXML
Label valueLabel; protected Label unitLabel;
@FXML @FXML
Label status; private Label valueLabel;
@FXML @FXML
ToggleSwitch disableButton; private Label status;
@FXML
private ToggleSwitch disableButton;
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void accept(Device device, String measurementName, Measurement measurement) { public void accept(Device device, String measurementName, Measurement measurement) {
measurement.addListener(this); measurement.addListener(this);
if (device.meta().hasValue("color")) { getDevice().meta().optValue("color").ifPresent(colorValue ->valueLabel.setTextFill(Color.valueOf(colorValue.stringValue())));
valueLabel.setTextFill(Color.valueOf(device.meta().getString("color")));
}
} }
@Override @Override
@ -91,9 +86,9 @@ public class VacuumeterView extends DeviceConnection implements DeviceListener,
Platform.runLater(() -> { Platform.runLater(() -> {
unitLabel.setText(getDevice().meta().getString("units", "mbar")); unitLabel.setText(getDevice().meta().getString("units", "mbar"));
deviceNameLabel.setText(getDevice().getName()); deviceNameLabel.setText(getDevice().getName());
disableButton.setSelected(!getDevice().meta().getBoolean("disabled", false)); disableButton.setSelected(!getDevice().optBooleanState("disabled").orElse(false));
disableButton.selectedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> { disableButton.selectedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
getDevice().getConfig().setValue("disabled", !newValue); getDevice().setState("disabled",!newValue);
if (!newValue) { if (!newValue) {
valueLabel.setText("---"); valueLabel.setText("---");
} }
@ -137,17 +132,13 @@ public class VacuumeterView extends DeviceConnection implements DeviceListener,
}); });
} }
@Override
public String getName() {
return getDevice().getName();
}
@Override
public Meta meta() {
return getDevice().meta();
}
public String getTitle() { public String getTitle() {
return meta().getString("title", getName()); return getDevice().meta().getString("title", getDevice().getName());
}
@Override
public Node getFXNode() {
return root;
} }
} }

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<config>
<device type="numass:vac">
<sensor name="P1" color="red" port="com::/dev/ttyUSB0" sensorType="mks"/>
<sensor name="P2" color="blue" port="tcp::192.168.111.32:4002" sensorType="CM32"/>
<sensor name="P3" color="green" port="tcp::192.168.111.32:4003" sensorType="CM32"/>
<!--<sensor name="Px" color="black" port="com::/dev/ttyUSB1" sensorType="meradat"/> -->
<sensor name="Px" color="black" port="tcp::192.168.111.33:4003" sensorType="meradat" address="1"/>
<sensor name="Baratron" color="cyan" port="tcp::192.168.111.33:4004" sensorType="baratron"/>
<!--<sensor name="collector" color="magenta" port="tcp::192.168.111.33:4003" sensorType="meradat" address="5"/>-->
</device>
</config>

View File

@ -1,63 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import org.controlsfx.control.*?>
<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.geometry.*?> <?import javafx.geometry.*?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import org.controlsfx.control.ToggleSwitch?>
<?import java.net.URL?> <?import java.net.URL?>
<?import javafx.geometry.Insets?> <BorderPane fx:id="root" styleClass="vacBox" xmlns="http://javafx.com/javafx/8.0.40"
<?import javafx.scene.control.Label?> xmlns:fx="http://javafx.com/fxml/1">
<?import javafx.scene.control.Separator?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<AnchorPane styleClass="vacBox" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<stylesheets> <stylesheets>
<URL value="@/styles/vacstyles.css"/> <URL value="@/styles/vacstyles.css"/>
</stylesheets> </stylesheets>
<children> <center>
<VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <VBox>
<children>
<AnchorPane styleClass="namePane"> <AnchorPane styleClass="namePane">
<children> <Label id="name" fx:id="deviceNameLabel" alignment="CENTER" prefHeight="40.0" text="device Name"
<Label id="name" fx:id="deviceNameLabel" alignment="CENTER" prefHeight="40.0" text="device Name" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="0.0" /> AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="50.0"
<ToggleSwitch fx:id="disableButton" alignment="CENTER" layoutX="140.0" layoutY="20.0" prefWidth="40.0" selected="true" AnchorPane.bottomAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0" /> AnchorPane.topAnchor="0.0"/>
</children> <ToggleSwitch fx:id="disableButton" alignment="CENTER" layoutX="140.0" layoutY="20.0"
prefWidth="40.0" selected="true" AnchorPane.bottomAnchor="10.0"
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"/>
</AnchorPane> </AnchorPane>
<Separator/> <Separator/>
<BorderPane VBox.vgrow="ALWAYS"> <BorderPane VBox.vgrow="ALWAYS">
<left> <left>
<Label id="pressure" fx:id="valueLabel" alignment="CENTER_RIGHT" minWidth="110.0" prefHeight="60.0" text="---" BorderPane.alignment="CENTER"> <Label id="pressure" fx:id="valueLabel" alignment="CENTER_RIGHT" minWidth="110.0" prefHeight="60.0"
text="---" BorderPane.alignment="CENTER">
<BorderPane.margin> <BorderPane.margin>
<Insets/> <Insets/>
</BorderPane.margin> </BorderPane.margin>
<padding> <padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
</padding></Label> </padding>
</Label>
</left> </left>
<right> <right>
<Label id="units" fx:id="unitLabel" prefHeight="60.0" prefWidth="75.0" text="mbar" BorderPane.alignment="CENTER"> <Label id="units" fx:id="unitLabel" prefHeight="60.0" prefWidth="75.0" text="mbar"
BorderPane.alignment="CENTER">
<padding> <padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
</padding></Label> </padding>
</Label>
</right> </right>
</BorderPane> </BorderPane>
<Separator/> <Separator/>
<AnchorPane styleClass="statusPane"> <AnchorPane styleClass="statusPane">
<children>
<Label fx:id="status" maxWidth="200.0" text="Initializing" wrapText="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
<VBox.margin> <VBox.margin>
<Insets/> <Insets/>
</VBox.margin> </VBox.margin>
<padding> <padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
</padding> </padding>
<Label fx:id="status" maxWidth="200.0" text="Initializing" wrapText="true"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="0.0"/>
</AnchorPane> </AnchorPane>
</children>
</VBox> </VBox>
</children> </center>
</AnchorPane> </BorderPane>

View File

@ -5,19 +5,20 @@
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<?import java.net.URL?> <?import java.net.URL?>
<AnchorPane id="root" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="inr.numass.readvac.fx.VacCollectorView"> <BorderPane fx:id="root" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.111"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="inr.numass.readvac.fx.VacCollectorView">
<stylesheets> <stylesheets>
<URL value="@/styles/vacstyles.css"/> <URL value="@/styles/vacstyles.css"/>
</stylesheets> </stylesheets>
<children> <center>
<HBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <HBox>
<children>
<VBox alignment="TOP_CENTER" HBox.hgrow="ALWAYS"> <VBox alignment="TOP_CENTER" HBox.hgrow="ALWAYS">
<children>
<ToolBar> <ToolBar>
<items> <ToggleButton fx:id="startStopButton" mnemonicParsing="false"
<ToggleButton fx:id="startStopButton" mnemonicParsing="false" onAction="#onStartStopToggle" text="Measure" /> onAction="#onStartStopToggle" text="Measure"/>
<ToggleButton fx:id="storeButton" mnemonicParsing="false" onAction="#onStoreToggle" text="Store" /> <ToggleButton fx:id="storeButton" mnemonicParsing="false" onAction="#onStoreToggle"
text="Store"/>
<Separator orientation="VERTICAL"/> <Separator orientation="VERTICAL"/>
<Label text="Interval: "/> <Label text="Interval: "/>
<ChoiceBox fx:id="intervalSelector" prefWidth="150.0"/> <ChoiceBox fx:id="intervalSelector" prefWidth="150.0"/>
@ -25,11 +26,9 @@
<Pane HBox.hgrow="ALWAYS"/> <Pane HBox.hgrow="ALWAYS"/>
<Separator orientation="VERTICAL"/> <Separator orientation="VERTICAL"/>
<ToggleButton fx:id="logButton" mnemonicParsing="false" text="Console"/> <ToggleButton fx:id="logButton" mnemonicParsing="false" text="Console"/>
</items>
</ToolBar> </ToolBar>
<AnchorPane fx:id="plotHolder" VBox.vgrow="ALWAYS"/> <AnchorPane fx:id="plotHolder" VBox.vgrow="ALWAYS"/>
<HBox styleClass="beveled"> <HBox styleClass="beveled">
<children>
<Label alignment="CENTER_RIGHT" text="Last update: "> <Label alignment="CENTER_RIGHT" text="Last update: ">
<font> <font>
<Font size="24.0"/> <Font size="24.0"/>
@ -40,16 +39,14 @@
<Font size="24.0"/> <Font size="24.0"/>
</font> </font>
</Label> </Label>
</children>
</HBox> </HBox>
</children>
</VBox> </VBox>
<Separator orientation="VERTICAL"/> <Separator orientation="VERTICAL"/>
<VBox fx:id="vacBoxHolder" minWidth="200.0" spacing="2.0"> <VBox fx:id="vacBoxHolder" minWidth="200.0" spacing="2.0">
<HBox.margin> <HBox.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0"/> <Insets bottom="2.0" left="2.0" right="2.0" top="2.0"/>
</HBox.margin></VBox> </HBox.margin>
</children> </VBox>
</HBox> </HBox>
</children> </center>
</AnchorPane> </BorderPane>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<config>
<storage path="/home/numass-storage/"/>
<serialconfig P1="/dev/ttyUSB0" P2="/dev/ttyS5" P3="/dev/ttyS4" Px="/dev/ttyUSB1"/>
<run>12_2015.test</run>
</config>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<numass-vac>
<p1 name="P1" color="red" port="com::/dev/ttyUSB0"/>
<p2 name="P2" color="blue" port="tcp::192.168.111.32:4002"/>
<p3 name="P3" color="green" port="tcp::192.168.111.32:4003"/>
<px name="Px" color="black" port="com::/dev/ttyUSB1"/>
<baratron name="Baratron" color="cyan" port="tcp::192.168.111.33:4004"/>
</numass-vac>

View File

@ -10,6 +10,7 @@ import hep.dataforge.io.ColumnedDataWriter
import hep.dataforge.storage.commons.StorageUtils import hep.dataforge.storage.commons.StorageUtils
import hep.dataforge.tables.Table import hep.dataforge.tables.Table
import inr.numass.data.NMPoint import inr.numass.data.NMPoint
import inr.numass.data.NumassData
import inr.numass.data.NumassDataUtils import inr.numass.data.NumassDataUtils
import inr.numass.storage.NumassStorage import inr.numass.storage.NumassStorage
import inr.numass.utils.UnderflowCorrection import inr.numass.utils.UnderflowCorrection
@ -26,7 +27,7 @@ Collection<NMPoint> data = NumassDataUtils.joinSpectra(
.map { .map {
println "loading ${it.key}" println "loading ${it.key}"
it.value it.value
} }.map { (NumassData) it }
) )
data = NumassDataUtils.substractReferencePoint(data, 18600d); data = NumassDataUtils.substractReferencePoint(data, 18600d);

View File

@ -84,7 +84,7 @@ public class NumassFitScanTask extends AbstractTask<FitResult> {
if (model.meta().hasMeta("filter")) { if (model.meta().hasMeta("filter")) {
model.dependsOn("filter", metaBuilder.build(), "prepare"); model.dependsOn("filter", metaBuilder.build(), "prepare");
} else if (model.meta().hasMeta("empty")) { } else if (model.meta().hasMeta("empty")) {
model.dependsOn("substractEmpty", metaBuilder.build(), "prepare"); model.dependsOn("subtractEmpty", metaBuilder.build(), "prepare");
} else { } else {
model.dependsOn("prepare", metaBuilder.build(), "prepare"); model.dependsOn("prepare", metaBuilder.build(), "prepare");
} }

View File

@ -72,7 +72,7 @@ public class NumassFitTask extends SingleActionTask<Table, FitResult> {
if (model.meta().hasMeta("filter")) { if (model.meta().hasMeta("filter")) {
model.dependsOn("filter", metaBuilder.build(), "prepare"); model.dependsOn("filter", metaBuilder.build(), "prepare");
} else if (model.meta().hasMeta("empty")) { } else if (model.meta().hasMeta("empty")) {
model.dependsOn("substractEmpty", metaBuilder.build(), "prepare"); model.dependsOn("subtractEmpty", metaBuilder.build(), "prepare");
} else { } else {
model.dependsOn("prepare", metaBuilder.build(), "prepare"); model.dependsOn("prepare", metaBuilder.build(), "prepare");
} }

View File

@ -41,7 +41,7 @@ import java.util.function.BiFunction;
public class NumassSubstractEmptySourceTask extends AbstractTask<Table> { public class NumassSubstractEmptySourceTask extends AbstractTask<Table> {
@Override @Override
public String getName() { public String getName() {
return "substractEmpty"; return "subtractEmpty";
} }
@Override @Override
@ -50,7 +50,7 @@ public class NumassSubstractEmptySourceTask extends AbstractTask<Table> {
DataNode<Table> rootNode = data.getCheckedNode("prepare", Table.class); DataNode<Table> rootNode = data.getCheckedNode("prepare", Table.class);
Data<? extends Table> emptySource = data.getCheckedNode("empty", Table.class).getData(); Data<? extends Table> emptySource = data.getCheckedNode("empty", Table.class).getData();
rootNode.forEachDataWithType(Table.class, input -> { rootNode.forEachDataWithType(Table.class, input -> {
Data<? extends Table> res = subtractBackground(input, emptySource); Data<? extends Table> res = subtract(input, emptySource);
res.getGoal().onComplete((r, err) -> { res.getGoal().onComplete((r, err) -> {
if (r != null) { if (r != null) {
OutputStream out = model.getContext().io().out("merge", input.getName() + ".subtract"); OutputStream out = model.getContext().io().out("merge", input.getName() + ".subtract");
@ -77,11 +77,11 @@ public class NumassSubstractEmptySourceTask extends AbstractTask<Table> {
} }
private Data<? extends Table> subtractBackground(Data<? extends Table> mergeData, Data<? extends Table> emptyData) { private Data<? extends Table> subtract(Data<? extends Table> mergeData, Data<? extends Table> emptyData) {
return DataUtils.combine(mergeData, emptyData, Table.class, mergeData.meta(), (BiFunction<Table, Table, Table>) this::subtractBackground); return DataUtils.combine(mergeData, emptyData, Table.class, mergeData.meta(), (BiFunction<Table, Table, Table>) this::subtract);
} }
private Table subtractBackground(Table merge, Table empty) { private Table subtract(Table merge, Table empty) {
ListTable.Builder builder = new ListTable.Builder(merge.getFormat()); ListTable.Builder builder = new ListTable.Builder(merge.getFormat());
merge.stream().forEach(point -> { merge.stream().forEach(point -> {
MapPoint.Builder pointBuilder = new MapPoint.Builder(point); MapPoint.Builder pointBuilder = new MapPoint.Builder(point);