Restoring cryotemp

This commit is contained in:
darksnake 2016-09-28 17:04:18 +03:00
parent 2aecfdbced
commit e10b2393b6
17 changed files with 1094 additions and 2261 deletions

View File

@ -0,0 +1,16 @@
apply plugin: 'application'
if (!hasProperty('mainClass')) {
ext.mainClass = 'inr.numass.cryotemp.PKT8App'
}
mainClassName = mainClass
//mainClassName = "inr.numass.readvac.Main"
dependencies {
compile 'commons-cli:commons-cli:1.3'
compile 'de.jensd:shichimifx:1.0.5'
compile project(':dataforge-control')
compile project(':dataforge-storage')
compile project(':dataforge-plots')
}

View File

@ -0,0 +1,114 @@
package inr.numass.cryotemp;
import hep.dataforge.control.devices.PortSensor;
import hep.dataforge.control.measurements.AbstractMeasurement;
import hep.dataforge.control.measurements.Measurement;
import hep.dataforge.exceptions.ControlException;
import hep.dataforge.exceptions.MeasurementException;
import hep.dataforge.tables.DataPoint;
/**
* Created by darksnake on 28-Sep-16.
*/
public class PKT8 extends PortSensor<DataPoint> {
public static final String PGA = "pga";
public static final String SPS = "sps";
public static final String ABUF = "abuf";
@Override
protected Measurement<DataPoint> createMeasurement() throws MeasurementException {
return null;
}
@Override
protected Object computeState(String stateName) throws ControlException {
return super.computeState(stateName);
}
/**
* '0' : 2,5 SPS '1' : 5 SPS '2' : 10 SPS '3' : 25 SPS '4' : 50 SPS '5' :
* 100 SPS '6' : 500 SPS '7' : 1 kSPS '8' : 3,75 kSPS
*
* @param sps
* @return
*/
private String spsToStr(int sps) {
switch (sps) {
case 0:
return "2,5 SPS";
case 1:
return "5 SPS";
case 2:
return "10 SPS";
case 3:
return "25 SPS";
case 4:
return "50 SPS";
case 5:
return "100 SPS";
case 6:
return "500 SPS";
case 7:
return "1 kSPS";
case 8:
return "3.75 kSPS";
default:
return "unknown value";
}
}
/**
* '0' : ± 5 В '1' : ± 2,5 В '2' : ± 1,25 В '3' : ± 0,625 В '4' : ± 312.5 мВ
* '5' : ± 156,25 мВ '6' : ± 78,125 мВ
*
* @param sps
* @return
*/
private String pgaToStr(int sps) {
switch (sps) {
case 0:
return "± 5 V";
case 1:
return "± 2,5 V";
case 2:
return "± 1,25 V";
case 3:
return "± 0,625 V";
case 4:
return "± 312.5 mV";
case 5:
return "± 156,25 mV";
case 6:
return "± 78,125 mV";
default:
return "unknown value";
}
}
public String getSPS() {
return spsToStr(sps);
}
public String getPGA() {
return pgaToStr(pga);
}
public String getABUF() {
return Integer.toString(abuf);
}
private class PKT8Measurement extends AbstractMeasurement<DataPoint> {
@Override
public void start() {
}
@Override
public boolean stop(boolean force) throws MeasurementException {
return false;
}
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.cryotemp;
import ch.qos.logback.classic.Level;
import hep.dataforge.exceptions.ControlException;
import hep.dataforge.storage.commons.StorageManager;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Locale;
/**
* @author darksnake
*/
public class PKT8App extends Application {
PKT8MainViewController controller;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws IOException, ControlException {
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);
new StorageManager().startGlobal();
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/PKT8MainView.fxml"));
Parent parent = loader.load();
controller = loader.getController();
// Meta deviceMeta = XMLMetaConverter.fromStream(getClass().getResourceAsStream("/defaultConfig.xml"));
// controller.setupDevice(deviceMeta);
Scene scene = new Scene(parent, 600, 400);
primaryStage.setTitle("PKT8 cryogenic temperature viewer");
primaryStage.setScene(scene);
primaryStage.setMinHeight(400);
primaryStage.setMinWidth(600);
// primaryStage.setResizable(false);
primaryStage.show();
}
@Override
public void stop() throws Exception {
super.stop();
if (controller != null) {
controller.close();
controller = null;
}
// System.exit(0);
}
}

View File

@ -0,0 +1,427 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.cryotemp;
import hep.dataforge.context.Context;
import hep.dataforge.control.collectors.RegularPointCollector;
import hep.dataforge.control.devices.PortSensor;
import hep.dataforge.control.measurements.AbstractMeasurement;
import hep.dataforge.control.ports.PortHandler;
import hep.dataforge.control.ports.TcpPortHandler;
import hep.dataforge.exceptions.ControlException;
import hep.dataforge.exceptions.MeasurementException;
import hep.dataforge.exceptions.PortException;
import hep.dataforge.exceptions.StorageException;
import hep.dataforge.meta.Annotated;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.names.Named;
import hep.dataforge.storage.api.PointLoader;
import hep.dataforge.storage.api.Storage;
import hep.dataforge.storage.commons.LoaderFactory;
import hep.dataforge.tables.DataPoint;
import hep.dataforge.tables.TableTableFormatBuilder;
import hep.dataforge.values.Value;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.function.Function;
/**
* A device controller for Dubna PKT 8 cryogenic thermometry device
*
* @author Alexander Nozik
*/
public class PKT8Device extends PortSensor<DataPoint> implements PortHandler.PortController {
private static final String[] CHANNEL_DESIGNATIONS = {"a", "b", "c", "d", "e", "f", "g", "h"};
/**
* The key is the letter (a,b,c,d...) as in measurements
*/
private final Map<String, Channel> channels = new HashMap<>();
private PointLoader pointLoader;
private RegularPointCollector collector;
private boolean isStarted = false;
private PortHandler handler;
private int sps = -1;
private int pga = -1;
private int abuf = -1;
public PKT8Device(String name, Context context, Meta annotation) {
super(name, context, annotation);
}
/**
* Start measurement
*
* @throws ControlException
*/
@Override
public void doStart(Meta measurement) throws ControlException {
// Meta meta = new MetaChain("device", measurement.meta(),meta());
if (!isStarted) {
//setup storage
try {
Storage storage = getPrimaryStorage(measurement);
String suffix = Integer.toString((int) Instant.now().toEpochMilli());
// Building data format
TableTableFormatBuilder TableFormatBuilder = new TableTableFormatBuilder()
.addTime("timestamp");
List<String> names = new ArrayList<>();
for (Channel channel : this.channels.values()) {
TableFormatBuilder.addNumber(channel.getName());
names.add(channel.getName());
}
this.pointLoader = LoaderFactory.buildPointLoder(storage, "cryotemp_" + suffix, "", "timestamp", TableFormatBuilder.build());
Duration duration = Duration.parse(meta().getString("averagingDuration", "PT30S"));
collector = new RegularPointCollector((dp) -> {
if (pointLoader != null) {
try {
getLogger().debug("Point measurement complete. Pushing...");
pointLoader.push(dp);
} catch (StorageException ex) {
getLogger().error("Error while pushing point to loader", ex);
}
}
}, duration, names);
} catch (StorageException ex) {
getLogger().error("Can't setup storage", ex);
}
handler.send("s");
isStarted = true;
}
}
@Override
public void init() throws ControlException {
//read channel configuration
if (meta().hasNode("channel")) {
for (Meta node : meta().getNodes("channel")) {
String designation = node.getString("designation", "default");
this.channels.put(designation, new Channel(node));
}
} else {
//set default channel configuration
for (String designation : CHANNEL_DESIGNATIONS) {
channels.put(designation, new Channel(designation));
}
getLogger().warn("No channels defined in configuration");
}
//setup connection
if (meta().hasNode("debug")) {
handler = new PKT8VirtualPort("PKT8", meta().getNode("debug"));
} else {
String ip = this.meta().getString("connection.ip", "127.0.0.1");
int port = this.meta().getInt("connection.port", 4001);
handler = new TcpPortHandler(ip, port, getName());
}
handler.setDelimeter("\n");
handler.holdBy(this);
handler.open();
handler.send("p");
handler.sendAndWait("p", null, 1000);
//update parameters from meta
if (meta().hasValue("pga")) {
getLogger().info("Setting dynamic range to " + meta().getInt("pga"));
String response = handler.sendAndWait("g" + meta().getInt("pga"), null, 400).trim();
if (response.contains("=")) {
this.pga = Integer.parseInt(response.substring(4));
} else {
getLogger().error("Setting pga failsed with message: " + response);
}
}
setSPS(meta().getInt("sps", 0));
setBUF(meta().getInt("abuf", 100));
super.init();
}
@Override
public void shutdown() throws ControlException {
stop();
try {
this.handler.unholdBy(this);
this.handler.close();
} catch (Exception ex) {
throw new ControlException(ex);
}
super.shutdown();
}
public Collection<Channel> getChanels() {
return this.channels.values();
}
private void setBUF(int buf) throws PortException {
getLogger().info("Setting avaraging buffer size to " + buf);
String response = handler.sendAndWait("b" + buf, null, 400).trim();
if (response.contains("=")) {
this.abuf = Integer.parseInt(response.substring(14));
getLogger().info("successfully set buffer size to {}", this.abuf);
} else {
getLogger().error("Setting averaging buffer failsed with message: " + response);
}
}
@Override
public void doStop() throws ControlException {
handler.send("p");
isStarted = false;
if (collector != null) {
collector.cancel();
}
}
public void changeParameters(int sps, int abuf) {
this.executor.submit(() -> {
try {
stop();
//setting sps
setSPS(sps);
//setting buffer
setBUF(abuf);
start();
} catch (ControlException ex) {
getLogger().error("Control error", ex);
}
});
}
@Override
public void accept(String message) {
String trimmed = message.trim();
if (isStarted) {
if (trimmed.equals("stopped")) {
isStarted = false;
getLogger().info("Measurement paused");
} else {
String designation = trimmed.substring(0, 1);
double rawValue = Double.parseDouble(trimmed.substring(1)) / 100;
if (channels.containsKey(designation)) {
Channel channel = channels.get(designation);
notifyMeasurementComplete(channel.getName(), rawValue, channel.getTemperature(rawValue));
collector.put(channel.getName(), channel.getTemperature(rawValue));
} else {
notifyMeasurementComplete(designation, rawValue, -1);
}
}
}
}
private void notifyMeasurementComplete(String channel, double rawValue, double temperature) {
measurementResult(null, new Data(channel, rawValue, temperature));
}
@Override
public void error(String errorMessage, Throwable error) {
}
/**
* '0' : 2,5 SPS '1' : 5 SPS '2' : 10 SPS '3' : 25 SPS '4' : 50 SPS '5' :
* 100 SPS '6' : 500 SPS '7' : 1 kSPS '8' : 3,75 kSPS
*
* @param sps
* @return
*/
private String spsToStr(int sps) {
switch (sps) {
case 0:
return "2,5 SPS";
case 1:
return "5 SPS";
case 2:
return "10 SPS";
case 3:
return "25 SPS";
case 4:
return "50 SPS";
case 5:
return "100 SPS";
case 6:
return "500 SPS";
case 7:
return "1 kSPS";
case 8:
return "3.75 kSPS";
default:
return "unknown value";
}
}
/**
* '0' : ± 5 В '1' : ± 2,5 В '2' : ± 1,25 В '3' : ± 0,625 В '4' : ± 312.5 мВ
* '5' : ± 156,25 мВ '6' : ± 78,125 мВ
*
* @param sps
* @return
*/
private String pgaToStr(int sps) {
switch (sps) {
case 0:
return "± 5 V";
case 1:
return "± 2,5 V";
case 2:
return "± 1,25 V";
case 3:
return "± 0,625 V";
case 4:
return "± 312.5 mV";
case 5:
return "± 156,25 mV";
case 6:
return "± 78,125 mV";
default:
return "unknown value";
}
}
public String getSPS() {
return spsToStr(sps);
}
private void setSPS(int sps) throws PortException {
getLogger().info("Setting sampling rate to " + spsToStr(sps));
String response = handler.sendAndWait("v" + sps, null, 400).trim();
if (response.contains("=")) {
this.sps = Integer.parseInt(response.substring(4));
getLogger().info("successfully sampling rate to {}", spsToStr(this.sps));
} else {
getLogger().error("Setting sps failsed with message: " + response);
}
}
public String getPGA() {
return pgaToStr(pga);
}
public String getABUF() {
return Integer.toString(abuf);
}
public static class Data {
public String channel;
public double rawValue;
public double temperature;
public Data(String channel, double rawValue, double temperature) {
this.channel = channel;
this.rawValue = rawValue;
this.temperature = temperature;
}
}
public class Channel implements Named, Annotated {
private final Meta meta;
private final Function<Double, Double> transformation;
public Channel(String name) {
this.meta = new MetaBuilder("channel")
.putValue("name", name);
transformation = (d) -> d;
}
public Channel(Meta meta) {
this.meta = meta;
String transformationType = meta.getString("transformationType", "default");
if (meta.hasValue("coefs")) {
switch (transformationType) {
case "default":
case "hyperbolic":
List<Value> coefs = meta.getValue("coefs").listValue();
double r0 = meta.getDouble("r0", 1000);
transformation = (r) -> {
if (coefs == null) {
return -1d;
} else {
double res = 0;
for (int i = 0; i < coefs.size(); i++) {
res += coefs.get(i).doubleValue() * Math.pow(r0 / r, i);
}
return res;
}
};
break;
default:
throw new RuntimeException("Unknown transformation type");
}
} else {
//identity transformation
transformation = (d) -> d;
}
}
@Override
public String getName() {
return meta().getString("name");
}
@Override
public Meta meta() {
return meta;
}
public String description() {
return meta().getString("description", "");
}
/**
* @param r negative if temperature transformation not defined
* @return
*/
public double getTemperature(double r) {
return transformation.apply(r);
}
}
public class PKT8Measurement extends AbstractMeasurement<DataPoint> {
@Override
public void start() {
}
@Override
public boolean stop(boolean force) throws MeasurementException {
return false;
}
}
}

View File

@ -0,0 +1,277 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.cryotemp;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.AppenderBase;
import de.jensd.shichimifx.utils.SplitPaneDividerSlider;
import hep.dataforge.context.GlobalContext;
import hep.dataforge.control.devices.Device;
import hep.dataforge.control.devices.DeviceListener;
import hep.dataforge.control.measurements.MeasurementDevice;
import hep.dataforge.control.measurements.MeasurementListener;
import hep.dataforge.exceptions.ControlException;
import hep.dataforge.io.MetaFileReader;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.meta.MetaUtils;
import hep.dataforge.plots.XYPlotFrame;
import hep.dataforge.plots.data.DynamicPlottable;
import hep.dataforge.plots.data.DynamicPlottableSet;
import hep.dataforge.plots.jfreechart.JFreeChartFrame;
import hep.dataforge.values.Value;
import inr.numass.cryotemp.PKT8Device.Data;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.AnchorPane;
import javafx.stage.FileChooser;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.ParseException;
import java.time.Instant;
import java.util.Collection;
import java.util.ResourceBundle;
/**
* FXML Controller class
*
* @author darksnake
*/
public class PKT8MainViewController implements Initializable, DeviceListener, MeasurementListener<Data>, AutoCloseable {
public static final String DEFAULT_CONFIG_LOCATION = "devices.xml";
private PKT8Device device;
private XYPlotFrame plotFrame;
private DynamicPlottableSet plottables;
private Meta currentPlotConfig;
@FXML
private Button loadConfigButton;
@FXML
private SplitPane consoleSplitPane;
@FXML
private TextArea logArea;
@FXML
private ToggleButton startStopButton;
@FXML
private AnchorPane plotArea;
@FXML
private ToggleButton consoleButton;
@Override
public void close() throws Exception {
if (device != null) {
device.stop();
device.shutdown();
}
}
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
setupPlotFrame(null);
SplitPaneDividerSlider slider = new SplitPaneDividerSlider(consoleSplitPane, 0, SplitPaneDividerSlider.Direction.DOWN);
consoleButton.selectedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
slider.setAimContentVisible(newValue);
});
slider.setAimContentVisible(false);
}
@FXML
private void onLoadConfigClick(ActionEvent event) throws IOException, ParseException, ControlException {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open configuration file");
fileChooser.setInitialFileName(DEFAULT_CONFIG_LOCATION);
fileChooser.setInitialDirectory(GlobalContext.instance().io().getRootDirectory());
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("xml", "*.xml", "*.XML"));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("json", "*.json", "*.JSON"));
// fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("all", "*.*"));
File cfgFile = fileChooser.showOpenDialog(loadConfigButton.getScene().getWindow());
if (cfgFile != null) {
setConfig(MetaFileReader.read(cfgFile));
}
}
private void loadTestConfig() throws ControlException {
try {
Meta testConfig = MetaFileReader
.read(new File(getClass().getResource("/config/defaultConfig.xml").toURI()));
setConfig(testConfig);
} catch (URISyntaxException | IOException | ParseException ex) {
throw new Error(ex);
}
}
public String getDeviceName() {
return "PKT8";
}
public void setConfig(Meta config) throws ControlException {
if (config.hasNode("plotConfig")) {
Meta plotConfig = MetaUtils.findNodeByValue(config, "plotConfig", "device", getDeviceName());
if (plotConfig == null) {
plotConfig = config.getNode("plotConfig");
}
setupPlotFrame(plotConfig.getNode("plotFrame", null));
currentPlotConfig = plotConfig;
}
if (config.hasNode("device")) {
Meta deviceMeta = MetaUtils.findNodeByValue(config, "device", "name", Value.of(getDeviceName()));
setupDevice(deviceMeta);
} else {
setupDevice(config);
}
}
/**
* Set o reset plot area
*/
private void setupPlotFrame(Meta plotFrameMeta) {
plottables = new DynamicPlottableSet();
plotArea.getChildren().clear();
Meta plotConfig;
if (plotFrameMeta != null) {
plotConfig = new MetaBuilder(plotFrameMeta)
.setValue("xAxis.timeAxis", true);
} else {
plotConfig = new MetaBuilder("plotFrame")
.setValue("xAxis.timeAxis", true);
}
plotFrame = new JFreeChartFrame("plot", plotConfig).display(plotArea);
}
public void setupDevice(Meta deviceMeta) throws ControlException {
if (device != null) {
device.stop();
device.shutdown();
}
this.device = new PKT8Device("PKT8", GlobalContext.instance(), deviceMeta);
device.addDeviceListener(this);
device.addMeasurementListener(this);
logArea.appendText("Starting log...\n");
Appender<ILoggingEvent> appender = new AppenderBase<ILoggingEvent>() {
// private final DateTimeFormatter formatter = DateTimeFormatter.ISO_TIME;
@Override
protected void append(ILoggingEvent e) {
logArea.appendText(String.format("%s > (%s) [%s] %s%n",
e.getLoggerName(),
Instant.now().toString(),
e.getLevel(),
e.getFormattedMessage()));
}
};
appender.start();
device.getLogger().addAppender(appender);
device.init();
}
@Override
public void notifyDeviceInitialized(Device device) {
Collection<PKT8Device.Channel> channels = this.device.getChanels();
for (PKT8Device.Channel channel : channels) {
if (!plottables.hasPlottable(channel.getName())) {
//plot config from device configuration
Meta deviceLineMeta = channel.meta().getNode("plot", channel.meta());
//Do not use view config here, it is applyed separately
DynamicPlottable plottable = new DynamicPlottable(channel.getName(), deviceLineMeta);
plottables.addPlottable(plottable);
plotFrame.add(plottable);
}
}
startStopButton.setDisable(false);
if (currentPlotConfig != null) {
applyViewConfig(currentPlotConfig);
}
}
public void applyViewConfig(Meta viewConfig) {
plottables.applyConfig(viewConfig);
}
@Override
public void notifyDeviceShutdown(Device device) {
startStopButton.setDisable(true);
}
@Override
public void notifyDeviceStateChanged(Device device, String name, Value oldState, Value newState) {
}
// @Override
// public void sendMessage(Device device, int priority, Meta message) {
// String tag = message.getString("tag", "");
// logArea.appendText(String.format("%s > (%s) [%s] %s%n", device.getName(), Instant.now().toString(), tag, message));
// }
@Override
public void notifyMeasurementStarted(MeasurementDevice device, Meta measurement) {
}
@Override
public void notifyMeasurementStopped(MeasurementDevice device) {
}
@Override
public void notifyMeasurementResult(MeasurementDevice device, Meta measurement, Data measurementResult) {
plottables.put(measurementResult.channel, measurementResult.temperature);
}
@FXML
private void onStartStopClick(ActionEvent event) {
if (device != null) {
try {
if (startStopButton.isSelected()) {
device.start();
} else {
//in case device started
device.stop();
}
} catch (ControlException ex) {
}
}
}
}

View File

@ -0,0 +1,87 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.cryotemp;
import hep.dataforge.control.ports.VirtualPort;
import hep.dataforge.exceptions.PortException;
import hep.dataforge.meta.Annotated;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaUtils;
import hep.dataforge.values.Value;
import java.time.Duration;
import java.util.Random;
/**
* @author Alexander Nozik
*/
public class PKT8VirtualPort extends VirtualPort implements Annotated {
private final Meta meta;
private final Random generator = new Random();
public PKT8VirtualPort(String portName, Meta meta) {
super(portName);
this.meta = meta;
}
@Override
public Meta meta() {
return meta;
}
@Override
protected void evaluateRequest(String request) {
switch (request) {
case "s":
String[] letters = {"a", "b", "c", "d", "e", "f", "g", "h"};
for (String letter : letters) {
Meta channelMeta = MetaUtils.findNodeByValue(meta(), "channel", "letter", Value.of(letter));
double average;
double sigma;
if (channelMeta != null) {
average = channelMeta.getDouble("av", 1200);
sigma = channelMeta.getDouble("sigma", 50);
} else {
average = 1200d;
sigma = 50d;
}
this.planRegularResponse(
() -> {
double res = average + generator.nextGaussian() * sigma;
//TODO convert double value to formatted string
return letter + "000120000\n";
},
Duration.ZERO, Duration.ofSeconds(5), letter, "measurement"
);
}
return;
case "p":
cancelByTag("measurement");
this.recievePhrase("stopped\n\r");
return;
}
}
@Override
public void open() throws PortException {
}
@Override
public boolean isOpen() {
return true;
}
@Override
public void close() throws Exception {
cancelByTag("measurement");
}
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<device>
<storage path="D:\\temp\\cryo"/>
<connection ip="192.168.111.137" port="4001"/>
<abuf>120</abuf>
<channel designation="a" name="a-channel" r0="1000" transformationType="hyperbolic" coefs="[1.0,1.0]"
color="black"/>
<channel designation="b" name="b-channel" r0="1000" transformationType="hyperbolic" coefs="[1.1,1.1]"/>
<channel designation="c" name="c-channel" r0="1000" transformationType="hyperbolic" coefs="[1.2,1.0]"
thickness="2"/>
<channel designation="d" name="d-channel" r0="1000" transformationType="hyperbolic" coefs="[1.3,1.0]"/>
<plotConfig>
<eachPlot thickness="4"/>
<plot name="c-channel" color="magenta"/>
</plotConfig>
</device>

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2015 Alexander Nozik.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" id="AnchorPane" prefHeight="400.0" prefWidth="600.0"
xmlns="http://javafx.com/javafx/8" fx:controller="inr.numass.cryotemp.PKT8MainViewController">
<children>
<SplitPane fx:id="consoleSplitPane" dividerPositions="0.8" layoutX="184.0" layoutY="62.0" orientation="VERTICAL"
prefHeight="200.0" prefWidth="160.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="40.0">
<items>
<AnchorPane fx:id="plotArea" minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0"/>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="94.0" prefWidth="598.0">
<children>
<TextArea fx:id="logArea" editable="false" layoutX="38.0" layoutY="-75.0" prefHeight="200.0"
prefWidth="200.0" wrapText="true" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"/>
</children>
</AnchorPane>
</items>
</SplitPane>
<ToolBar prefHeight="40.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<ToggleButton fx:id="startStopButton" disable="true" mnemonicParsing="false"
onAction="#onStartStopClick" prefWidth="50.0" text="Start"/>
<Separator orientation="VERTICAL"/>
<Button fx:id="loadConfigButton" mnemonicParsing="false" onAction="#onLoadConfigClick"
text="Load config"/>
<ToggleButton fx:id="consoleButton" contentDisplay="CENTER" mnemonicParsing="false" text="Console"/>
</items>
</ToolBar>
</children>
</AnchorPane>

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system">
<system systemId="http://javafx.com/javafx/8.0.65" uri="www.oracle.com/technetwork/java/javase/overview/index.html"/>
</catalog>

File diff suppressed because one or more lines are too long

View File

@ -36,13 +36,9 @@ import hep.dataforge.tables.MapPoint;
import hep.dataforge.tables.TableFormat; import hep.dataforge.tables.TableFormat;
import hep.dataforge.tables.TableFormatBuilder; import hep.dataforge.tables.TableFormatBuilder;
import hep.dataforge.values.Value; import hep.dataforge.values.Value;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.ConcurrentSkipListMap;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -55,18 +51,14 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
// private static final String PEAK_SET_PATH = "peakJump.peak"; // private static final String PEAK_SET_PATH = "peakJump.peak";
private static final int TIMEOUT = 200; private static final int TIMEOUT = 200;
private TcpPortHandler handler;
//listener
private MspListener mspListener;
private Consumer<MspResponse> responseDelegate;
private Consumer<Throwable> errorDelegate;
boolean connected = false; boolean connected = false;
boolean selected = false; boolean selected = false;
boolean controlled = false; boolean controlled = false;
private TcpPortHandler handler;
//listener
private MspListener mspListener;
private Consumer<MspResponse> responseDelegate;
private Consumer<Throwable> errorDelegate;
// public MspDevice(String name, Context context, Meta config) { // public MspDevice(String name, Context context, Meta config) {
// super(name, context, config); // super(name, context, config);
@ -114,7 +106,7 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
} }
@Override @Override
protected Object calculateState(String stateName) throws ControlException { protected Object computeState(String stateName) throws ControlException {
switch (stateName) { switch (stateName) {
case "filamentOn": case "filamentOn":
return false;//Always return false on first request return false;//Always return false on first request
@ -387,10 +379,10 @@ 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 Map<Integer, String> peakMap;
private final Map<StorageConnection, PointLoader> loaderMap = new HashMap<>(); private final Map<StorageConnection, PointLoader> loaderMap = new HashMap<>();
// private List<PointLoader> loaders = new ArrayList<>(); // private List<PointLoader> loaders = new ArrayList<>();
private final Meta meta; private final Meta meta;
private Map<Integer, String> peakMap;
private double zero = 0; private double zero = 0;
public PeakJumpMeasurement(Meta meta) { public PeakJumpMeasurement(Meta meta) {

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system">
<system systemId="http://javafx.com/javafx/8.0.65" uri="www.oracle.com/technetwork/java/javase/overview/index.html"/>
</catalog>

File diff suppressed because one or more lines are too long

View File

@ -55,7 +55,7 @@ public class CM32Device extends PortSensor<Double> {
// return meta().getInt("timeout", 1000); // return meta().getInt("timeout", 1000);
// } // }
@Override @Override
protected Object calculateState(String stateName) throws ControlException { protected Object computeState(String stateName) throws ControlException {
if (getHandler() == null) { if (getHandler() == null) {
notifyError("No port connection", null); notifyError("No port connection", null);
return null; return null;

View File

@ -12,11 +12,12 @@ import hep.dataforge.control.ports.PortHandler;
import hep.dataforge.description.ValueDef; import hep.dataforge.description.ValueDef;
import hep.dataforge.exceptions.ControlException; import hep.dataforge.exceptions.ControlException;
import hep.dataforge.values.Value; import hep.dataforge.values.Value;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.adapter.JavaBeanBooleanPropertyBuilder; import javafx.beans.property.adapter.JavaBeanBooleanPropertyBuilder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* *
* @author Alexander Nozik * @author Alexander Nozik
@ -60,7 +61,7 @@ public class MKSVacDevice extends PortSensor<Double> {
} }
@Override @Override
protected Object calculateState(String stateName) throws ControlException { protected Object computeState(String stateName) throws ControlException {
if (getHandler() == null) { if (getHandler() == null) {
notifyError("No port connection", null); notifyError("No port connection", null);
return null; return null;

View File

@ -10,6 +10,7 @@ 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.exceptions.ControlException; import hep.dataforge.exceptions.ControlException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -43,7 +44,7 @@ public class VITVacDevice extends PortSensor<Double> {
} }
@Override @Override
protected Object calculateState(String stateName) throws ControlException { protected Object computeState(String stateName) throws ControlException {
if (getHandler() == null) { if (getHandler() == null) {
notifyError("No port connection", null); notifyError("No port connection", null);
return null; return null;

View File

@ -18,6 +18,7 @@ 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.values.Value; import hep.dataforge.values.Value;
import java.time.Instant; import java.time.Instant;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -44,13 +45,6 @@ public class VacCollectorDevice extends Sensor<DataPoint> {
} }
} }
public void setSensors(Iterable<Sensor> sensors) {
sensorMap = new LinkedHashMap<>();
for (Sensor sensor : sensors) {
sensorMap.put(sensor.getName(), sensor);
}
}
@Override @Override
public void init() throws ControlException { public void init() throws ControlException {
super.init(); super.init();
@ -60,7 +54,7 @@ public class VacCollectorDevice extends Sensor<DataPoint> {
} }
@Override @Override
protected Object calculateState(String stateName) throws ControlException { protected Object computeState(String stateName) throws ControlException {
//TODO add dot path notation for states //TODO add dot path notation for states
return Value.NULL; return Value.NULL;
} }
@ -96,6 +90,13 @@ public class VacCollectorDevice extends Sensor<DataPoint> {
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());