Restoring cryotemp
This commit is contained in:
parent
2aecfdbced
commit
e10b2393b6
16
numass-control/cryotemp/build.gradle
Normal file
16
numass-control/cryotemp/build.gradle
Normal 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')
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
@ -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>
|
@ -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>
|
@ -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
@ -36,13 +36,9 @@ import hep.dataforge.tables.MapPoint;
|
||||
import hep.dataforge.tables.TableFormat;
|
||||
import hep.dataforge.tables.TableFormatBuilder;
|
||||
import hep.dataforge.values.Value;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
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 int TIMEOUT = 200;
|
||||
|
||||
private TcpPortHandler handler;
|
||||
|
||||
//listener
|
||||
private MspListener mspListener;
|
||||
|
||||
private Consumer<MspResponse> responseDelegate;
|
||||
private Consumer<Throwable> errorDelegate;
|
||||
|
||||
boolean connected = false;
|
||||
boolean selected = 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) {
|
||||
// super(name, context, config);
|
||||
@ -114,7 +106,7 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object calculateState(String stateName) throws ControlException {
|
||||
protected Object computeState(String stateName) throws ControlException {
|
||||
switch (stateName) {
|
||||
case "filamentOn":
|
||||
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 final Map<Integer, Double> measurement = new ConcurrentSkipListMap<>();
|
||||
private Map<Integer, String> peakMap;
|
||||
private final Map<StorageConnection, PointLoader> loaderMap = new HashMap<>();
|
||||
// private List<PointLoader> loaders = new ArrayList<>();
|
||||
private final Meta meta;
|
||||
private Map<Integer, String> peakMap;
|
||||
private double zero = 0;
|
||||
|
||||
public PeakJumpMeasurement(Meta meta) {
|
||||
|
@ -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
@ -55,7 +55,7 @@ public class CM32Device extends PortSensor<Double> {
|
||||
// return meta().getInt("timeout", 1000);
|
||||
// }
|
||||
@Override
|
||||
protected Object calculateState(String stateName) throws ControlException {
|
||||
protected Object computeState(String stateName) throws ControlException {
|
||||
if (getHandler() == null) {
|
||||
notifyError("No port connection", null);
|
||||
return null;
|
||||
|
@ -12,11 +12,12 @@ import hep.dataforge.control.ports.PortHandler;
|
||||
import hep.dataforge.description.ValueDef;
|
||||
import hep.dataforge.exceptions.ControlException;
|
||||
import hep.dataforge.values.Value;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.adapter.JavaBeanBooleanPropertyBuilder;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
@ -60,7 +61,7 @@ public class MKSVacDevice extends PortSensor<Double> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object calculateState(String stateName) throws ControlException {
|
||||
protected Object computeState(String stateName) throws ControlException {
|
||||
if (getHandler() == null) {
|
||||
notifyError("No port connection", null);
|
||||
return null;
|
||||
|
@ -10,6 +10,7 @@ import hep.dataforge.control.measurements.Measurement;
|
||||
import hep.dataforge.control.measurements.SimpleMeasurement;
|
||||
import hep.dataforge.control.ports.PortHandler;
|
||||
import hep.dataforge.exceptions.ControlException;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.regex.Matcher;
|
||||
@ -43,7 +44,7 @@ public class VITVacDevice extends PortSensor<Double> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object calculateState(String stateName) throws ControlException {
|
||||
protected Object computeState(String stateName) throws ControlException {
|
||||
if (getHandler() == null) {
|
||||
notifyError("No port connection", null);
|
||||
return null;
|
||||
|
@ -18,6 +18,7 @@ import hep.dataforge.tables.DataPoint;
|
||||
import hep.dataforge.tables.MapPoint;
|
||||
import hep.dataforge.tables.PointListener;
|
||||
import hep.dataforge.values.Value;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
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
|
||||
public void init() throws ControlException {
|
||||
super.init();
|
||||
@ -60,7 +54,7 @@ public class VacCollectorDevice extends Sensor<DataPoint> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object calculateState(String stateName) throws ControlException {
|
||||
protected Object computeState(String stateName) throws ControlException {
|
||||
//TODO add dot path notation for states
|
||||
return Value.NULL;
|
||||
}
|
||||
@ -96,6 +90,13 @@ public class VacCollectorDevice extends Sensor<DataPoint> {
|
||||
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 final ValueCollector collector = new PointCollector(this::result, sensorMap.keySet());
|
||||
|
Loading…
Reference in New Issue
Block a user