Revised port synchronous commands
This commit is contained in:
parent
203c02bf53
commit
9241177d40
@ -29,7 +29,6 @@ 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.exceptions.MeasurementException;
|
import hep.dataforge.exceptions.MeasurementException;
|
||||||
import hep.dataforge.exceptions.PortException;
|
|
||||||
import hep.dataforge.exceptions.StorageException;
|
import hep.dataforge.exceptions.StorageException;
|
||||||
import hep.dataforge.meta.Meta;
|
import hep.dataforge.meta.Meta;
|
||||||
import hep.dataforge.storage.api.PointLoader;
|
import hep.dataforge.storage.api.PointLoader;
|
||||||
@ -59,6 +58,7 @@ import java.util.stream.Collectors;
|
|||||||
@StateDef(@ValueDef(name = "storing"))
|
@StateDef(@ValueDef(name = "storing"))
|
||||||
public class PKT8Device extends PortSensor<PKT8Result> {
|
public class PKT8Device extends PortSensor<PKT8Result> {
|
||||||
public static final String PKT8_DEVICE_TYPE = "numass:pkt8";
|
public static final String PKT8_DEVICE_TYPE = "numass:pkt8";
|
||||||
|
private static final Duration TIMEOUT = Duration.ofMillis(400);
|
||||||
|
|
||||||
public static final String PGA = "pga";
|
public static final String PGA = "pga";
|
||||||
public static final String SPS = "sps";
|
public static final String SPS = "sps";
|
||||||
@ -119,7 +119,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"), 400).trim();
|
String response = sendAndWait("g" + meta().getInt("pga"), TIMEOUT).trim();
|
||||||
if (response.contains("=")) {
|
if (response.contains("=")) {
|
||||||
updateState(PGA, Integer.parseInt(response.substring(4)));
|
updateState(PGA, Integer.parseInt(response.substring(4)));
|
||||||
} else {
|
} else {
|
||||||
@ -177,7 +177,7 @@ public class PKT8Device extends PortSensor<PKT8Result> {
|
|||||||
} else {
|
} else {
|
||||||
handler = super.buildHandler(portName);
|
handler = super.buildHandler(portName);
|
||||||
}
|
}
|
||||||
handler.setDelimeter("\n");
|
handler.setDelimiter("\n");
|
||||||
|
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
@ -190,7 +190,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, 400).trim();
|
response = sendAndWait("b" + buf, Duration.ofMillis(400)).trim();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
response = ex.getMessage();
|
response = ex.getMessage();
|
||||||
}
|
}
|
||||||
@ -279,7 +279,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, 400).trim();
|
response = sendAndWait("v" + sps, TIMEOUT).trim();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
response = ex.getMessage();
|
response = ex.getMessage();
|
||||||
}
|
}
|
||||||
@ -324,8 +324,8 @@ public class PKT8Device extends PortSensor<PKT8Result> {
|
|||||||
public Measurement<PKT8Result> startMeasurement() throws MeasurementException {
|
public Measurement<PKT8Result> startMeasurement() throws MeasurementException {
|
||||||
//clearing PKT queue
|
//clearing PKT queue
|
||||||
try {
|
try {
|
||||||
getHandler().send("p");
|
send("p");
|
||||||
getHandler().sendAndWait("p", 400);
|
sendAndWait("p", TIMEOUT);
|
||||||
} catch (ControlException e) {
|
} catch (ControlException e) {
|
||||||
getLogger().error("Failed to clear PKT8 port");
|
getLogger().error("Failed to clear PKT8 port");
|
||||||
// throw new MeasurementException(e);
|
// throw new MeasurementException(e);
|
||||||
@ -357,10 +357,10 @@ public class PKT8Device extends PortSensor<PKT8Result> {
|
|||||||
try {
|
try {
|
||||||
getLogger().info("Starting measurement");
|
getLogger().info("Starting measurement");
|
||||||
handler.holdBy(this);
|
handler.holdBy(this);
|
||||||
handler.send("s");
|
send("s");
|
||||||
afterStart();
|
afterStart();
|
||||||
} catch (PortException ex) {
|
} catch (ControlException ex) {
|
||||||
error("Failed to start measurement", ex);
|
portError("Failed to start measurement", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -373,7 +373,7 @@ public class PKT8Device extends PortSensor<PKT8Result> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
getLogger().info("Stopping measurement");
|
getLogger().info("Stopping measurement");
|
||||||
String response = getHandler().sendAndWait("p", 400).trim();
|
String response = sendAndWait("p", TIMEOUT).trim();
|
||||||
// Должно быть именно с большой буквы!!!
|
// Должно быть именно с большой буквы!!!
|
||||||
return "Stopped".equals(response) || "stopped".equals(response);
|
return "Stopped".equals(response) || "stopped".equals(response);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
@ -389,7 +389,7 @@ public class PKT8Device extends PortSensor<PKT8Result> {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(String message) {
|
public void acceptPortPhrase(String message) {
|
||||||
String trimmed = message.trim();
|
String trimmed = message.trim();
|
||||||
|
|
||||||
if (isStarted()) {
|
if (isStarted()) {
|
||||||
@ -414,7 +414,7 @@ public class PKT8Device extends PortSensor<PKT8Result> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(String errorMessage, Throwable error) {
|
public void portError(String errorMessage, Throwable error) {
|
||||||
super.error(error);
|
super.error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,13 @@ package inr.numass.control.magnet;
|
|||||||
|
|
||||||
import hep.dataforge.control.ports.PortHandler;
|
import hep.dataforge.control.ports.PortHandler;
|
||||||
import hep.dataforge.control.ports.PortTimeoutException;
|
import hep.dataforge.control.ports.PortTimeoutException;
|
||||||
|
import hep.dataforge.control.ports.SyncPortController;
|
||||||
import hep.dataforge.exceptions.PortException;
|
import hep.dataforge.exceptions.PortException;
|
||||||
import hep.dataforge.utils.DateTimeUtils;
|
import hep.dataforge.utils.DateTimeUtils;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
@ -44,12 +46,15 @@ public class MagnetController implements PortHandler.PortController {
|
|||||||
public static double MIN_DOWN_STEP_SIZE = 0.05;
|
public static double MIN_DOWN_STEP_SIZE = 0.05;
|
||||||
public static double MAX_SPEED = 5d; // 5 A per minute
|
public static double MAX_SPEED = 5d; // 5 A per minute
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
private final PortHandler port;
|
private final PortHandler port;
|
||||||
|
private final SyncPortController controller = new SyncPortController(this);
|
||||||
|
|
||||||
private final int address;
|
private final int address;
|
||||||
private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
|
private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
|
||||||
protected MagnetStateListener listener;
|
protected MagnetStateListener listener;
|
||||||
private volatile double current = 0;
|
private volatile double current = 0;
|
||||||
private int timeout = 200;
|
private Duration timeout = Duration.ofMillis(200);
|
||||||
private Future monitorTask;
|
private Future monitorTask;
|
||||||
private Future updateTask;
|
private Future updateTask;
|
||||||
private Instant lastUpdate = null;
|
private Instant lastUpdate = null;
|
||||||
@ -69,9 +74,9 @@ public class MagnetController implements PortHandler.PortController {
|
|||||||
public MagnetController(String name, PortHandler port, int address, int timeout) {
|
public MagnetController(String name, PortHandler port, int address, int timeout) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.port.setDelimeter("\r");//PENDING меняем состояние внешнего объекта?
|
this.port.setDelimiter("\r");//PENDING меняем состояние внешнего объекта?
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.timeout = timeout;
|
this.timeout = Duration.ofMillis(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MagnetController(PortHandler port, int address, int timeout) {
|
public MagnetController(PortHandler port, int address, int timeout) {
|
||||||
@ -105,12 +110,12 @@ public class MagnetController implements PortHandler.PortController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(String message) {
|
public void acceptPortPhrase(String message) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(String errorMessage, Throwable error) {
|
public void portError(String errorMessage, Throwable error) {
|
||||||
if (this.listener != null) {
|
if (this.listener != null) {
|
||||||
listener.error(getName(), errorMessage, error);
|
listener.error(getName(), errorMessage, error);
|
||||||
} else {
|
} else {
|
||||||
@ -120,11 +125,13 @@ 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", timeout).trim();
|
port.send(controller,request + "\r");
|
||||||
|
return controller.waitFor(timeout).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", timeout).trim();
|
port.send(controller,request + "\r");
|
||||||
|
return controller.waitFor(timeout).trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +177,7 @@ public class MagnetController implements PortHandler.PortController {
|
|||||||
|
|
||||||
protected void setCurrent(double current) throws PortException {
|
protected void setCurrent(double current) throws PortException {
|
||||||
if (!setState("PC", current)) {
|
if (!setState("PC", current)) {
|
||||||
error("Can't set the current", null);
|
portError("Can't set the current", null);
|
||||||
} else {
|
} else {
|
||||||
lastUpdate = DateTimeUtils.now();
|
lastUpdate = DateTimeUtils.now();
|
||||||
}
|
}
|
||||||
@ -194,7 +201,7 @@ public class MagnetController implements PortHandler.PortController {
|
|||||||
*/
|
*/
|
||||||
private MagnetStatus getStatus() throws PortException {
|
private MagnetStatus getStatus() throws PortException {
|
||||||
try {
|
try {
|
||||||
port.holdBy(MagnetController.this);
|
port.holdBy(controller);
|
||||||
|
|
||||||
if (!setADR()) {
|
if (!setADR()) {
|
||||||
return MagnetStatus.off();
|
return MagnetStatus.off();
|
||||||
@ -217,7 +224,7 @@ public class MagnetController implements PortHandler.PortController {
|
|||||||
}
|
}
|
||||||
return monitor;
|
return monitor;
|
||||||
} finally {
|
} finally {
|
||||||
port.unholdBy(MagnetController.this);
|
port.unholdBy(controller);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +257,7 @@ public class MagnetController implements PortHandler.PortController {
|
|||||||
stopUpdateTask();
|
stopUpdateTask();
|
||||||
Runnable call = () -> {
|
Runnable call = () -> {
|
||||||
try {
|
try {
|
||||||
port.holdBy(MagnetController.this);
|
port.holdBy(controller);
|
||||||
double measuredI = getCurrent();
|
double measuredI = getCurrent();
|
||||||
this.current = measuredI;
|
this.current = measuredI;
|
||||||
|
|
||||||
@ -271,10 +278,10 @@ public class MagnetController implements PortHandler.PortController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (PortException ex) {
|
} catch (PortException ex) {
|
||||||
error("Error in update task", ex);
|
portError("Error in update task", ex);
|
||||||
stopUpdateTask();
|
stopUpdateTask();
|
||||||
} finally {
|
} finally {
|
||||||
port.unholdBy(MagnetController.this);
|
port.unholdBy(controller);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -286,7 +293,7 @@ public class MagnetController implements PortHandler.PortController {
|
|||||||
|
|
||||||
public void setOutputMode(boolean out) throws PortException {
|
public void setOutputMode(boolean out) throws PortException {
|
||||||
try {
|
try {
|
||||||
port.holdBy(MagnetController.this);
|
port.holdBy(controller);
|
||||||
if (!setADR()) {
|
if (!setADR()) {
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
@ -304,7 +311,7 @@ public class MagnetController implements PortHandler.PortController {
|
|||||||
listener.outputModeChanged(getName(), out);
|
listener.outputModeChanged(getName(), out);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
port.unholdBy(MagnetController.this);
|
port.unholdBy(controller);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,7 +385,7 @@ public class MagnetController implements PortHandler.PortController {
|
|||||||
try {
|
try {
|
||||||
getStatus();
|
getStatus();
|
||||||
} catch (PortException ex) {
|
} catch (PortException ex) {
|
||||||
error("Port connection exception during status measurement", ex);
|
portError("Port connection exception during status measurement", ex);
|
||||||
stopMonitorTask();
|
stopMonitorTask();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -393,17 +400,17 @@ public class MagnetController implements PortHandler.PortController {
|
|||||||
|
|
||||||
public String request(String message) {
|
public String request(String message) {
|
||||||
try {
|
try {
|
||||||
port.holdBy(this);
|
port.holdBy(controller);
|
||||||
try {
|
try {
|
||||||
if (!setADR()) {
|
if (!setADR()) {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
return talk(message);
|
return talk(message);
|
||||||
} finally {
|
} finally {
|
||||||
port.unholdBy(this);
|
port.unholdBy(controller);
|
||||||
}
|
}
|
||||||
} catch (PortException ex) {
|
} catch (PortException ex) {
|
||||||
error("Can not send message to the port", ex);
|
portError("Can not send message to the port", ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package inr.numass.control.magnet;
|
|||||||
import ch.qos.logback.classic.Level;
|
import ch.qos.logback.classic.Level;
|
||||||
import hep.dataforge.control.ports.PortFactory;
|
import hep.dataforge.control.ports.PortFactory;
|
||||||
import hep.dataforge.control.ports.PortHandler;
|
import hep.dataforge.control.ports.PortHandler;
|
||||||
|
import hep.dataforge.control.ports.SyncPortController;
|
||||||
import hep.dataforge.exceptions.PortException;
|
import hep.dataforge.exceptions.PortException;
|
||||||
import hep.dataforge.utils.DateTimeUtils;
|
import hep.dataforge.utils.DateTimeUtils;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -59,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", 1000);
|
String answer = SyncPortController.sendAndWait(handler, nextString + "\r", Duration.ofSeconds(1));
|
||||||
//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) {
|
||||||
|
4933
numass-control/msp/docs/ASCII Protocol User Manual SP1040016.100.pdf
Normal file
4933
numass-control/msp/docs/ASCII Protocol User Manual SP1040016.100.pdf
Normal file
File diff suppressed because one or more lines are too long
@ -27,6 +27,7 @@ import hep.dataforge.control.devices.Sensor;
|
|||||||
import hep.dataforge.control.devices.StateDef;
|
import hep.dataforge.control.devices.StateDef;
|
||||||
import hep.dataforge.control.measurements.AbstractMeasurement;
|
import hep.dataforge.control.measurements.AbstractMeasurement;
|
||||||
import hep.dataforge.control.ports.PortHandler;
|
import hep.dataforge.control.ports.PortHandler;
|
||||||
|
import hep.dataforge.control.ports.SyncPortController;
|
||||||
import hep.dataforge.control.ports.TcpPortHandler;
|
import hep.dataforge.control.ports.TcpPortHandler;
|
||||||
import hep.dataforge.description.ValueDef;
|
import hep.dataforge.description.ValueDef;
|
||||||
import hep.dataforge.events.EventBuilder;
|
import hep.dataforge.events.EventBuilder;
|
||||||
@ -55,22 +56,18 @@ import java.util.function.Consumer;
|
|||||||
*/
|
*/
|
||||||
@RoleDef(name = Roles.STORAGE_ROLE, objectType = StorageConnection.class)
|
@RoleDef(name = Roles.STORAGE_ROLE, objectType = StorageConnection.class)
|
||||||
@RoleDef(name = Roles.VIEW_ROLE)
|
@RoleDef(name = Roles.VIEW_ROLE)
|
||||||
@StateDef(
|
@StateDef(value = @ValueDef(name = PortSensor.CONNECTED_STATE, info = "Connection with the device itself"), writable = true)
|
||||||
value = @ValueDef(name = PortSensor.CONNECTED_STATE, info = "Connection with the device itself"),
|
@StateDef(value = @ValueDef(name = "storing", info = "Define if this device is currently writes to storage"), writable = true)
|
||||||
writable = true
|
@StateDef(value = @ValueDef(name = "filament", info = "The number of filament in use"), writable = true)
|
||||||
)
|
|
||||||
@StateDef(
|
|
||||||
value = @ValueDef(name = "storing", info = "Define if this device is currently writes to storage"),
|
|
||||||
writable = true
|
|
||||||
)
|
|
||||||
@StateDef(value = @ValueDef(name = "filamentOn", info = "Mass-spectrometer filament on"), writable = true)
|
@StateDef(value = @ValueDef(name = "filamentOn", info = "Mass-spectrometer filament on"), writable = true)
|
||||||
@StateDef(@ValueDef(name = "filamentStatus", info = "Filament status"))
|
@StateDef(@ValueDef(name = "filamentStatus", info = "Filament status"))
|
||||||
public class MspDevice extends Sensor<DataPoint> implements PortHandler.PortController {
|
public class MspDevice extends Sensor<DataPoint> implements PortHandler.PortController {
|
||||||
public static final String MSP_DEVICE_TYPE = "msp";
|
public static final String MSP_DEVICE_TYPE = "msp";
|
||||||
|
|
||||||
private static final int TIMEOUT = 200;
|
private static final Duration TIMEOUT = Duration.ofMillis(200);
|
||||||
|
|
||||||
private TcpPortHandler handler;
|
private TcpPortHandler handler;
|
||||||
|
private SyncPortController controller = new SyncPortController(this);
|
||||||
private Consumer<MspResponse> measurementDelegate;
|
private Consumer<MspResponse> measurementDelegate;
|
||||||
|
|
||||||
public MspDevice() {
|
public MspDevice() {
|
||||||
@ -91,7 +88,7 @@ public class MspDevice extends Sensor<DataPoint> implements PortHandler.PortCont
|
|||||||
int port = meta().getInt("connection.port", 10014);
|
int port = meta().getInt("connection.port", 10014);
|
||||||
getLogger().info("Connection to MKS mass-spectrometer on {}:{}...", ip, port);
|
getLogger().info("Connection to MKS mass-spectrometer on {}:{}...", ip, port);
|
||||||
handler = new TcpPortHandler(ip, port);
|
handler = new TcpPortHandler(ip, port);
|
||||||
handler.setDelimeter("\r\r");
|
handler.setDelimiter("\r\r");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -128,6 +125,8 @@ public class MspDevice extends Sensor<DataPoint> implements PortHandler.PortCont
|
|||||||
switch (stateName) {
|
switch (stateName) {
|
||||||
case "connected":
|
case "connected":
|
||||||
return false;
|
return false;
|
||||||
|
case "filament":
|
||||||
|
return 1;
|
||||||
case "filamentOn":
|
case "filamentOn":
|
||||||
return false;//Always return false on first request
|
return false;//Always return false on first request
|
||||||
case "filamentStatus":
|
case "filamentStatus":
|
||||||
@ -150,6 +149,9 @@ public class MspDevice extends Sensor<DataPoint> implements PortHandler.PortCont
|
|||||||
case PortSensor.CONNECTED_STATE:
|
case PortSensor.CONNECTED_STATE:
|
||||||
setConnected(value.booleanValue());
|
setConnected(value.booleanValue());
|
||||||
break;
|
break;
|
||||||
|
case "filament":
|
||||||
|
selectFilament(value.intValue());
|
||||||
|
break;
|
||||||
case "filamentOn":
|
case "filamentOn":
|
||||||
setFilamentOn(value.booleanValue());
|
setFilamentOn(value.booleanValue());
|
||||||
break;
|
break;
|
||||||
@ -169,12 +171,12 @@ public class MspDevice extends Sensor<DataPoint> implements PortHandler.PortCont
|
|||||||
String sensorName;
|
String sensorName;
|
||||||
if (isConnected() != connected) {
|
if (isConnected() != connected) {
|
||||||
if (connected) {
|
if (connected) {
|
||||||
handler.holdBy(this);
|
getHandler().holdBy(controller);
|
||||||
MspResponse response = sendAndWait("Sensors");
|
MspResponse response = sendAndWait("Sensors");
|
||||||
if (response.isOK()) {
|
if (response.isOK()) {
|
||||||
sensorName = response.get(2, 1);
|
sensorName = response.get(2, 1);
|
||||||
} else {
|
} else {
|
||||||
error(response.errorDescription(), null);
|
portError(response.errorDescription(), null);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//PENDING определеить в конфиге номер прибора
|
//PENDING определеить в конфиге номер прибора
|
||||||
@ -184,7 +186,7 @@ public class MspDevice extends Sensor<DataPoint> implements PortHandler.PortCont
|
|||||||
updateState("selected", true);
|
updateState("selected", true);
|
||||||
// selected = true;
|
// selected = true;
|
||||||
} else {
|
} else {
|
||||||
error(response.errorDescription(), null);
|
portError(response.errorDescription(), null);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,14 +196,14 @@ public class MspDevice extends Sensor<DataPoint> implements PortHandler.PortCont
|
|||||||
// invalidateState("controlled");
|
// invalidateState("controlled");
|
||||||
updateState("controlled", true);
|
updateState("controlled", true);
|
||||||
} else {
|
} else {
|
||||||
error(response.errorDescription(), null);
|
portError(response.errorDescription(), null);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// connected = true;
|
// connected = true;
|
||||||
updateState(PortSensor.CONNECTED_STATE, true);
|
updateState(PortSensor.CONNECTED_STATE, true);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
handler.unholdBy(this);
|
getHandler().unholdBy(controller);
|
||||||
return !sendAndWait("Release").isOK();
|
return !sendAndWait("Release").isOK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,11 +265,9 @@ public class MspDevice extends Sensor<DataPoint> implements PortHandler.PortCont
|
|||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
String response = getHandler().sendAndWait(
|
|
||||||
request,
|
getHandler().send(controller, request);
|
||||||
TIMEOUT,
|
String response = controller.waitFor(TIMEOUT, (String str) -> str.trim().startsWith(commandName));
|
||||||
(String str) -> str.trim().startsWith(commandName)
|
|
||||||
);
|
|
||||||
return new MspResponse(response);
|
return new MspResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,8 +287,13 @@ public class MspDevice extends Sensor<DataPoint> implements PortHandler.PortCont
|
|||||||
return getState("filamentOn").booleanValue();
|
return getState("filamentOn").booleanValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectFillament(int filament) throws PortException {
|
public void selectFilament(int filament) throws PortException {
|
||||||
sendAndWait("FilamentSelect", filament);
|
MspResponse response = sendAndWait("FilamentSelect", filament);
|
||||||
|
if (response.isOK()) {
|
||||||
|
updateState("filament", response.get(1, 1));
|
||||||
|
} else {
|
||||||
|
getLogger().error("Failed to set filament with error: {}", response.errorDescription());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -316,7 +321,7 @@ public class MspDevice extends Sensor<DataPoint> implements PortHandler.PortCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(String message) {
|
public void acceptPortPhrase(String message) {
|
||||||
dispatchEvent(
|
dispatchEvent(
|
||||||
EventBuilder
|
EventBuilder
|
||||||
.make("msp")
|
.make("msp")
|
||||||
@ -338,7 +343,7 @@ public class MspDevice extends Sensor<DataPoint> implements PortHandler.PortCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(String errorMessage, Throwable error) {
|
public void portError(String errorMessage, Throwable error) {
|
||||||
notifyError(errorMessage, error);
|
notifyError(errorMessage, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ import hep.dataforge.control.NamedValueListener
|
|||||||
import hep.dataforge.control.devices.DeviceListener
|
import hep.dataforge.control.devices.DeviceListener
|
||||||
import hep.dataforge.control.devices.PortSensor
|
import hep.dataforge.control.devices.PortSensor
|
||||||
import hep.dataforge.control.devices.Sensor
|
import hep.dataforge.control.devices.Sensor
|
||||||
import hep.dataforge.control.devices.Sensor.MEASURING_STATE
|
|
||||||
import hep.dataforge.fx.fragments.FragmentWindow
|
import hep.dataforge.fx.fragments.FragmentWindow
|
||||||
import hep.dataforge.fx.fragments.LogFragment
|
import hep.dataforge.fx.fragments.LogFragment
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
@ -33,6 +32,7 @@ import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
|||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
import inr.numass.control.DeviceViewConnection
|
import inr.numass.control.DeviceViewConnection
|
||||||
import inr.numass.control.deviceStateIndicator
|
import inr.numass.control.deviceStateIndicator
|
||||||
|
import inr.numass.control.deviceStateToggle
|
||||||
import javafx.beans.property.SimpleObjectProperty
|
import javafx.beans.property.SimpleObjectProperty
|
||||||
import javafx.collections.FXCollections
|
import javafx.collections.FXCollections
|
||||||
import javafx.collections.MapChangeListener
|
import javafx.collections.MapChangeListener
|
||||||
@ -121,10 +121,12 @@ class MspViewConnection : DeviceViewConnection<MspDevice>(), DeviceListener, Nam
|
|||||||
addLogHandler(device.logger)
|
addLogHandler(device.logger)
|
||||||
})
|
})
|
||||||
|
|
||||||
val filamentProperty = SimpleObjectProperty<Int>().apply {
|
val filamentProperty = SimpleObjectProperty<Int>(this, "filament", 1).apply {
|
||||||
addListener { _, oldValue, newValue ->
|
addListener { _, oldValue, newValue ->
|
||||||
if (newValue != oldValue) {
|
if (newValue != oldValue) {
|
||||||
device.selectFillament(newValue);
|
runAsync {
|
||||||
|
device.setState("filament", newValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,17 +136,13 @@ class MspViewConnection : DeviceViewConnection<MspDevice>(), DeviceListener, Nam
|
|||||||
minWidth = 600.0
|
minWidth = 600.0
|
||||||
top {
|
top {
|
||||||
toolbar {
|
toolbar {
|
||||||
togglebutton("Connect") {
|
deviceStateToggle(this@MspViewConnection,PortSensor.CONNECTED_STATE,"Connect")
|
||||||
isSelected = false
|
|
||||||
bindBooleanToState(PortSensor.CONNECTED_STATE, selectedProperty())
|
|
||||||
}
|
|
||||||
combobox(filamentProperty, listOf(1, 2)) {
|
combobox(filamentProperty, listOf(1, 2)) {
|
||||||
cellFormat {
|
cellFormat {
|
||||||
text = "Filament $it"
|
text = "Filament $it"
|
||||||
}
|
}
|
||||||
selectionModel.selectFirst()
|
|
||||||
disableProperty()
|
disableProperty()
|
||||||
.bind(getStateBinding(MEASURING_STATE).booleanBinding { it!!.booleanValue() })
|
.bind(getBooleanStateBinding(PortSensor.CONNECTED_STATE).not())
|
||||||
}
|
}
|
||||||
add(ToggleSwitch().apply {
|
add(ToggleSwitch().apply {
|
||||||
padding = Insets(5.0, 0.0, 0.0, 0.0)
|
padding = Insets(5.0, 0.0, 0.0, 0.0)
|
||||||
@ -152,7 +150,7 @@ class MspViewConnection : DeviceViewConnection<MspDevice>(), DeviceListener, Nam
|
|||||||
.bind(getStateBinding(PortSensor.CONNECTED_STATE).booleanBinding { !it!!.booleanValue() })
|
.bind(getStateBinding(PortSensor.CONNECTED_STATE).booleanBinding { !it!!.booleanValue() })
|
||||||
bindBooleanToState("filamentOn", selectedProperty())
|
bindBooleanToState("filamentOn", selectedProperty())
|
||||||
})
|
})
|
||||||
deviceStateIndicator(this@MspViewConnection, "filamentStatus") {
|
deviceStateIndicator(this@MspViewConnection, "filamentStatus", false) {
|
||||||
when (it.stringValue()) {
|
when (it.stringValue()) {
|
||||||
"ON" -> Paint.valueOf("red")
|
"ON" -> Paint.valueOf("red")
|
||||||
"OFF" -> Paint.valueOf("blue")
|
"OFF" -> Paint.valueOf("blue")
|
||||||
@ -161,7 +159,6 @@ class MspViewConnection : DeviceViewConnection<MspDevice>(), DeviceListener, Nam
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
separator(Orientation.VERTICAL)
|
|
||||||
|
|
||||||
togglebutton("Measure") {
|
togglebutton("Measure") {
|
||||||
isSelected = false
|
isSelected = false
|
||||||
@ -190,8 +187,9 @@ class MspViewConnection : DeviceViewConnection<MspDevice>(), DeviceListener, Nam
|
|||||||
}
|
}
|
||||||
PlotContainer.centerIn(this).plot = plotFrame
|
PlotContainer.centerIn(this).plot = plotFrame
|
||||||
}
|
}
|
||||||
init{
|
|
||||||
table.addListener {change: MapChangeListener.Change<out String, out Value> ->
|
init {
|
||||||
|
table.addListener { change: MapChangeListener.Change<out String, out Value> ->
|
||||||
if (change.wasAdded()) {
|
if (change.wasAdded()) {
|
||||||
val pl = plottables.get(change.key)
|
val pl = plottables.get(change.key)
|
||||||
val value = change.valueAdded
|
val value = change.valueAdded
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package inr.numass.control
|
package inr.numass.control
|
||||||
|
|
||||||
import hep.dataforge.control.connections.DeviceConnection
|
import hep.dataforge.control.Connection
|
||||||
import hep.dataforge.control.devices.Device
|
import hep.dataforge.control.devices.Device
|
||||||
import hep.dataforge.control.devices.DeviceListener
|
import hep.dataforge.control.devices.DeviceListener
|
||||||
import hep.dataforge.control.devices.PortSensor
|
import hep.dataforge.control.devices.PortSensor
|
||||||
@ -9,10 +9,10 @@ import hep.dataforge.fx.FXObject
|
|||||||
import hep.dataforge.fx.fragments.FXFragment
|
import hep.dataforge.fx.fragments.FXFragment
|
||||||
import hep.dataforge.fx.fragments.FragmentWindow
|
import hep.dataforge.fx.fragments.FragmentWindow
|
||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
import javafx.application.Platform
|
import javafx.beans.binding.BooleanBinding
|
||||||
import javafx.beans.binding.ObjectBinding
|
import javafx.beans.binding.ObjectBinding
|
||||||
import javafx.beans.property.BooleanProperty
|
import javafx.beans.property.BooleanProperty
|
||||||
import javafx.beans.value.ObservableValue
|
import javafx.beans.property.SimpleObjectProperty
|
||||||
import javafx.geometry.Pos
|
import javafx.geometry.Pos
|
||||||
import javafx.scene.Parent
|
import javafx.scene.Parent
|
||||||
import javafx.scene.layout.HBox
|
import javafx.scene.layout.HBox
|
||||||
@ -23,9 +23,24 @@ import java.util.*
|
|||||||
/**
|
/**
|
||||||
* Created by darksnake on 14-May-17.
|
* Created by darksnake on 14-May-17.
|
||||||
*/
|
*/
|
||||||
abstract class DeviceViewConnection<D : Device> : DeviceConnection<D>(), DeviceListener, FXObject {
|
abstract class DeviceViewConnection<D : Device> : Component(), Connection<D>, DeviceListener, FXObject {
|
||||||
private val bindings = HashMap<String, ObjectBinding<Value>>()
|
private val bindings = HashMap<String, ObjectBinding<Value>>()
|
||||||
|
|
||||||
|
val deviceProperty = SimpleObjectProperty<D>()
|
||||||
|
var device by deviceProperty
|
||||||
|
|
||||||
|
override fun isOpen(): Boolean {
|
||||||
|
return this.device != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun open(device: D) {
|
||||||
|
this.device = device
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
this.device = null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get binding for a given device state
|
* Get binding for a given device state
|
||||||
|
|
||||||
@ -47,7 +62,7 @@ abstract class DeviceViewConnection<D : Device> : DeviceConnection<D>(), DeviceL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBooleanStateBinding(state: String): ObservableValue<Boolean> {
|
fun getBooleanStateBinding(state: String): BooleanBinding {
|
||||||
return getStateBinding(state).booleanBinding { it!!.booleanValue() }
|
return getStateBinding(state).booleanBinding { it!!.booleanValue() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,8 +81,11 @@ abstract class DeviceViewConnection<D : Device> : DeviceConnection<D>(), DeviceL
|
|||||||
}
|
}
|
||||||
property.addListener { observable, oldValue, newValue ->
|
property.addListener { observable, oldValue, newValue ->
|
||||||
if (isOpen && oldValue != newValue) {
|
if (isOpen && oldValue != newValue) {
|
||||||
val result = device.setState(state, newValue).get().booleanValue();
|
runAsync {
|
||||||
Platform.runLater { property.set(result) }
|
device.setState(state, newValue).get().booleanValue();
|
||||||
|
} ui {
|
||||||
|
property.set(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import hep.dataforge.values.Value
|
|||||||
import javafx.beans.value.ObservableValue
|
import javafx.beans.value.ObservableValue
|
||||||
import javafx.event.EventTarget
|
import javafx.event.EventTarget
|
||||||
import javafx.geometry.Orientation
|
import javafx.geometry.Orientation
|
||||||
|
import javafx.scene.Node
|
||||||
import javafx.scene.paint.Color
|
import javafx.scene.paint.Color
|
||||||
import javafx.scene.paint.Paint
|
import javafx.scene.paint.Paint
|
||||||
import javafx.scene.shape.Circle
|
import javafx.scene.shape.Circle
|
||||||
@ -87,9 +88,11 @@ fun Indicator.bind(connection: DeviceViewConnection<*>, state: String, transform
|
|||||||
/**
|
/**
|
||||||
* State name + indicator
|
* State name + indicator
|
||||||
*/
|
*/
|
||||||
fun EventTarget.deviceStateIndicator(connection: DeviceViewConnection<*>, state: String, transform: ((Value) -> Paint)? = null) {
|
fun EventTarget.deviceStateIndicator(connection: DeviceViewConnection<*>, state: String, showName: Boolean = true, transform: ((Value) -> Paint)? = null) {
|
||||||
if (connection.device.hasState(state)) {
|
if (connection.device.hasState(state)) {
|
||||||
text("${state.toUpperCase()}: ")
|
if (showName) {
|
||||||
|
text("${state.toUpperCase()}: ")
|
||||||
|
}
|
||||||
indicator {
|
indicator {
|
||||||
bind(connection, state, transform);
|
bind(connection, state, transform);
|
||||||
}
|
}
|
||||||
@ -97,3 +100,22 @@ fun EventTarget.deviceStateIndicator(connection: DeviceViewConnection<*>, state:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A togglebutton + indicator for boolean state
|
||||||
|
*/
|
||||||
|
fun Node.deviceStateToggle(connection: DeviceViewConnection<*>, state: String, title: String = state) {
|
||||||
|
if (connection.device.hasState(state)) {
|
||||||
|
togglebutton(title) {
|
||||||
|
isSelected = false
|
||||||
|
selectedProperty().addListener { observable, oldValue, newValue ->
|
||||||
|
if(oldValue!= newValue){
|
||||||
|
connection.device.setState(state,newValue).thenAccept {
|
||||||
|
isSelected = it.booleanValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deviceStateIndicator(connection, state, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ public class CM32Device extends PortSensor<Double> {
|
|||||||
} else {
|
} else {
|
||||||
newHandler = PortFactory.getPort(portName);
|
newHandler = PortFactory.getPort(portName);
|
||||||
}
|
}
|
||||||
newHandler.setDelimeter("T--\r");
|
newHandler.setDelimiter("T--\r");
|
||||||
return newHandler;
|
return newHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ public class CM32Device extends PortSensor<Double> {
|
|||||||
@Override
|
@Override
|
||||||
protected synchronized Double doMeasure() throws Exception {
|
protected synchronized Double doMeasure() throws Exception {
|
||||||
|
|
||||||
String answer = getHandler().sendAndWait(CM32_QUERY, timeout());
|
String answer = sendAndWait(CM32_QUERY, timeout());
|
||||||
|
|
||||||
if (answer.isEmpty()) {
|
if (answer.isEmpty()) {
|
||||||
this.progressUpdate("No signal");
|
this.progressUpdate("No signal");
|
||||||
|
@ -43,7 +43,7 @@ public class MKSBaratronDevice extends PortSensor<Double> {
|
|||||||
@Override
|
@Override
|
||||||
protected PortHandler buildHandler(String portName) throws ControlException {
|
protected PortHandler buildHandler(String portName) throws ControlException {
|
||||||
PortHandler handler = super.buildHandler(portName);
|
PortHandler handler = super.buildHandler(portName);
|
||||||
handler.setDelimeter("\r");
|
handler.setDelimiter("\r");
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ public class MKSBaratronDevice extends PortSensor<Double> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected synchronized Double doMeasure() throws Exception {
|
protected synchronized Double doMeasure() throws Exception {
|
||||||
String answer = getHandler().sendAndWait("AV" + getChannel() + "\r", timeout());
|
String answer = sendAndWait("AV" + getChannel() + "\r", timeout());
|
||||||
if (answer == null || answer.isEmpty()) {
|
if (answer == null || answer.isEmpty()) {
|
||||||
// invalidateState("connection");
|
// invalidateState("connection");
|
||||||
updateState(CONNECTED_STATE, false);
|
updateState(CONNECTED_STATE, false);
|
||||||
|
@ -42,7 +42,7 @@ public class MKSVacDevice extends PortSensor<Double> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String talk(String requestContent) throws ControlException {
|
private String talk(String requestContent) throws ControlException {
|
||||||
String answer = getHandler().sendAndWait(String.format("@%s%s;FF", getDeviceAddress(), requestContent), timeout());
|
String answer = sendAndWait(String.format("@%s%s;FF", getDeviceAddress(), requestContent), timeout());
|
||||||
|
|
||||||
Matcher match = Pattern.compile("@" + getDeviceAddress() + "ACK(.*);FF").matcher(answer);
|
Matcher match = Pattern.compile("@" + getDeviceAddress() + "ACK(.*);FF").matcher(answer);
|
||||||
if (match.matches()) {
|
if (match.matches()) {
|
||||||
@ -55,7 +55,7 @@ public class MKSVacDevice extends PortSensor<Double> {
|
|||||||
@Override
|
@Override
|
||||||
protected PortHandler buildHandler(String portName) throws ControlException {
|
protected PortHandler buildHandler(String portName) throws ControlException {
|
||||||
PortHandler handler = super.buildHandler(portName);
|
PortHandler handler = super.buildHandler(portName);
|
||||||
handler.setDelimeter(";FF");
|
handler.setDelimiter(";FF");
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ public class MeradatVacDevice extends PortSensor<Double> {
|
|||||||
@Override
|
@Override
|
||||||
protected PortHandler buildHandler(String portName) throws ControlException {
|
protected PortHandler buildHandler(String portName) throws ControlException {
|
||||||
PortHandler newHandler = super.buildHandler(portName);
|
PortHandler newHandler = super.buildHandler(portName);
|
||||||
newHandler.setDelimeter("\r\n");
|
newHandler.setDelimiter("\r\n");
|
||||||
return newHandler;
|
return newHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ public class MeradatVacDevice extends PortSensor<Double> {
|
|||||||
checksum += aByte;
|
checksum += aByte;
|
||||||
}
|
}
|
||||||
String val = Integer.toHexString(-checksum);
|
String val = Integer.toHexString(-checksum);
|
||||||
val = val.substring(val.length()-2).toUpperCase();
|
val = val.substring(val.length() - 2).toUpperCase();
|
||||||
if (val.length() < 2) {
|
if (val.length() < 2) {
|
||||||
val = "0" + val;
|
val = "0" + val;
|
||||||
}
|
}
|
||||||
@ -90,7 +90,7 @@ public class MeradatVacDevice extends PortSensor<Double> {
|
|||||||
@Override
|
@Override
|
||||||
protected synchronized Double doMeasure() throws Exception {
|
protected synchronized Double doMeasure() throws Exception {
|
||||||
|
|
||||||
String answer = getHandler().sendAndWait(query, timeout(), phrase -> phrase.startsWith(base));
|
String answer = sendAndWait(query, timeout(), phrase -> phrase.startsWith(base));
|
||||||
|
|
||||||
if (answer.isEmpty()) {
|
if (answer.isEmpty()) {
|
||||||
this.progressUpdate("No signal");
|
this.progressUpdate("No signal");
|
||||||
|
@ -130,7 +130,7 @@ public class VacCollectorView extends DeviceViewConnection<VacCollectorDevice> i
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void open(VacCollectorDevice device) throws Exception {
|
public void open(VacCollectorDevice device) {
|
||||||
super.open(device);
|
super.open(device);
|
||||||
device.getSensors().stream().map((sensor) -> {
|
device.getSensors().stream().map((sensor) -> {
|
||||||
VacuumeterView view;
|
VacuumeterView view;
|
||||||
|
Loading…
Reference in New Issue
Block a user