diff --git a/src/main/java/de/srsoftware/web4rail/Command.java b/src/main/java/de/srsoftware/web4rail/Command.java index 9cbc943..2558ff3 100644 --- a/src/main/java/de/srsoftware/web4rail/Command.java +++ b/src/main/java/de/srsoftware/web4rail/Command.java @@ -1,21 +1,103 @@ package de.srsoftware.web4rail; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; +import java.util.Date; +import java.util.Scanner; +import java.util.concurrent.TimeoutException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class Command extends CompletableFuture { +public class Command { private static final Logger LOG = LoggerFactory.getLogger(Command.class); private String command; + private Reply reply = null; + public static class Reply{ + private long secs; + private int milis; + private int code; + private String message; + + public Reply(Scanner scanner) { + String word = scanner.next(); + secs = Long.parseLong(word.substring(0, word.length()-4)); + milis = Integer.parseInt(word.substring(word.length()-3)); + code = scanner.nextInt(); + message = scanner.nextLine().trim(); + LOG.info("recv {}.{} {} {}.",secs,milis,code,message); + } + + public Reply(int code, String message) { + secs = new Date().getTime(); + milis = (int) (secs % 1000); + secs /= 1000; + this.code = code; + this.message = message; + } + + public boolean is(int code) { + return code == this.code; + } + + public boolean succeeded() { + return (code > 199 && code < 300); + } + + public String message() { + return message; + } + + @Override + public String toString() { + return "Reply("+secs+"."+milis+" / "+code+" / "+message+")"; + } + } + public Command(String command) { this.command = command; - this.orTimeout(500, TimeUnit.MILLISECONDS); LOG.debug("Created new Command({}).",command); } + + protected void onFailure(Reply reply) { + LOG.warn("onFailure({})",command); + } + + public void onResponse(Reply reply) { + this.reply = reply; + if (reply.succeeded()) { + onSuccess(); + } else onFailure(reply); + } + + public void onSuccess(){ + LOG.debug("onSuccess({})",command); + } + + public void readReplyFrom(Scanner scanner) { + onResponse(new Reply(scanner)); + } + + public Reply reply() throws TimeoutException { + return reply(100); + } + + public Reply reply(int timeout) throws TimeoutException { + int counter = 0; + while (reply == null) try { + if (counter++ > timeout) timeout(); + Thread.sleep(10); + } catch (InterruptedException e) { + LOG.warn("wait() interrupted!",e); + } + return reply; + } + + private void timeout() throws TimeoutException { + String msg = command; + command = null; + throw new TimeoutException("\""+msg+"\" timed out!"); + } @Override public String toString() { diff --git a/src/main/java/de/srsoftware/web4rail/ControlUnit.java b/src/main/java/de/srsoftware/web4rail/ControlUnit.java index 1f3a98f..486220b 100644 --- a/src/main/java/de/srsoftware/web4rail/ControlUnit.java +++ b/src/main/java/de/srsoftware/web4rail/ControlUnit.java @@ -10,6 +10,7 @@ import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.LinkedList; import java.util.Scanner; +import java.util.concurrent.TimeoutException; import org.json.JSONObject; import org.slf4j.Logger; @@ -26,44 +27,10 @@ public class ControlUnit extends Thread implements Constants{ private static final Logger LOG = LoggerFactory.getLogger(ControlUnit.class); private static final String DEFAULT_HOST = "localhost"; private static final int DEFAULT_PORT = 4303; - private static final int OK_PROTO = 201; - private static final int OK_MODE = 202; - private static final int OK = 200; private static final String HOST = "host"; private static final String PORT = "port"; private static final String BUS = "bus"; - public class Reply{ - private long secs; - private int milis; - private int code; - private String message; - - public Reply(Scanner scanner) { - String word = scanner.next(); - secs = Long.parseLong(word.substring(0, word.length()-4)); - milis = Integer.parseInt(word.substring(word.length()-3)); - code = scanner.nextInt(); - message = scanner.nextLine().trim(); - LOG.info("recv {}.{} {} {}.",secs,milis,code,message); - } - - public String message() { - return message; - } - - @Override - public String toString() { - return "Reply("+secs+"."+milis+" / "+code+" / "+message+")"; - } - - public boolean is(int code) { - return code == this.code; - } - } - - - private String host = DEFAULT_HOST; private int port = DEFAULT_PORT; private int bus = 0; @@ -72,6 +39,11 @@ public class ControlUnit extends Thread implements Constants{ private Socket socket; private Scanner scanner; private boolean power = false; + private Plan plan; + + public ControlUnit(Plan plan) { + this.plan = plan; + } /** * @return stops the loop at the next interval @@ -81,7 +53,7 @@ public class ControlUnit extends Thread implements Constants{ return this; } - private void handshake() throws IOException { + private void handshake() throws TimeoutException, IOException { String proto = null; if (scanner.hasNext()) { String line = scanner.nextLine(); @@ -92,18 +64,19 @@ public class ControlUnit extends Thread implements Constants{ } if (proto == null) throw new IOException("Handshake failed: "+line); if (!proto.startsWith("0.8.")) throw new IOException("Unsupported protocol: "+proto); - writeln("SET PROTOCOL SRCP "+proto); } else throw new IOException("Handshake expected."); + + Command command = new Command("SET PROTOCOL SRCP "+proto); + send(command); + if (!command.reply().succeeded()) throw new IOException("Handshake failed: "+command.reply()); - Reply reply = new Reply(scanner); - if (reply.code != OK_PROTO) throw new IOException("Handshake failed: "+reply); + command = new Command("SET CONNECTIONMODE SRCP COMMAND"); // preset following mode: COMMAND MODE + send(command); + if (!command.reply().succeeded()) throw new IOException("Handshake failed: "+command.reply()); - writeln("SET CONNECTIONMODE SRCP COMMAND"); // preset following mode: COMMAND MODE - reply = new Reply(scanner); - if (reply.code != OK_MODE) throw new IOException("Handshake failed: "+reply); - writeln("GO"); // switch mode - reply = new Reply(scanner); - if (reply.code != OK) throw new IOException("Handshake failed: "+reply); + command = new Command("GO"); // switch mode + send(command); + if (!command.reply().succeeded()) throw new IOException("Handshake failed: "+command.reply()); } private JSONObject json() { @@ -124,10 +97,21 @@ public class ControlUnit extends Thread implements Constants{ } public static void main(String[] args) throws InterruptedException { - ControlUnit cu = new ControlUnit().setEndpoint("Modellbahn", DEFAULT_PORT).setBus(1).restart(); + ControlUnit cu = new ControlUnit(null).setEndpoint("Modellbahn", DEFAULT_PORT).setBus(1).restart(); Thread.sleep(1000); - cu.queue("SET {} POWER ON"); - cu.queue("SET {} GL 1 0 10 128"); + cu.queue(new Command("SET {} POWER ON") { + + @Override + public void onSuccess() { + LOG.debug("Power on"); + } + + @Override + public void onFailure(Reply reply) { + LOG.debug("Was not able to turn power on: {}",reply.message()); + } + + }); Thread.sleep(1000); cu.end(); } @@ -166,10 +150,9 @@ public class ControlUnit extends Thread implements Constants{ return win; } - public Command queue(String command) { - Command promise = new Command(command); - queue.add(promise); - return promise; + public Command queue(Command command) { + queue.add(command); + return command; } /** @@ -190,7 +173,7 @@ public class ControlUnit extends Thread implements Constants{ Thread.sleep(10); } else { Command command = queue.pop(); - command.complete(send(command)); + send(command); } } catch (InterruptedException | IOException e) { e.printStackTrace(); @@ -215,10 +198,12 @@ public class ControlUnit extends Thread implements Constants{ * @return * @throws IOException */ - private Reply send(Command command) throws IOException { - if (command == null) return null; - writeln(command.toString()); - return new Reply(scanner); + private void send(Command command) throws IOException { + if (command == null || command.toString() == null) return; + String data = command.toString().replace("{}", ""+bus); + socket.getOutputStream().write((data+"\n").getBytes(StandardCharsets.US_ASCII)); + LOG.info("sent {}.",data); + command.readReplyFrom(scanner); } private ControlUnit setBus(int bus) { @@ -239,7 +224,7 @@ public class ControlUnit extends Thread implements Constants{ scanner = new Scanner(socket.getInputStream()); handshake(); stopped = false; - } catch (IOException e) { + } catch (IOException | TimeoutException e) { throw new IllegalStateException(e); } super.start(); @@ -249,11 +234,23 @@ public class ControlUnit extends Thread implements Constants{ return Translation.get(Application.class, text, fills); } - private Object togglePower() { + private Command togglePower() { power = !power; String PW = power?"ON":"OFF"; - queue("SET {} POWER "+PW); - return t("Turned power {}.",PW); + Command command = new Command("SET {} POWER "+PW) { + + @Override + public void onSuccess() { + plan.stream(t("Turned power {}.",PW)); + } + + @Override + public void onFailure(Reply reply) { + plan.stream(t("Was not able to turn power {}!",PW)); + } + + }; + return queue(command); } @@ -263,10 +260,4 @@ public class ControlUnit extends Thread implements Constants{ if (params.containsKey(BUS)) bus = Integer.parseInt(params.get(BUS)); return t("Updated control unit settings"); } - - private void writeln(String data) throws IOException { - data = data.replace("{}", ""+bus); - socket.getOutputStream().write((data+"\n").getBytes(StandardCharsets.US_ASCII)); - LOG.info("sent {}.",data); - } } diff --git a/src/main/java/de/srsoftware/web4rail/Plan.java b/src/main/java/de/srsoftware/web4rail/Plan.java index a433895..0466eb9 100644 --- a/src/main/java/de/srsoftware/web4rail/Plan.java +++ b/src/main/java/de/srsoftware/web4rail/Plan.java @@ -13,7 +13,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Stack; import java.util.Vector; -import java.util.concurrent.CompletableFuture; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -100,7 +99,7 @@ public class Plan implements Constants{ public HashMap tiles = new HashMap(); private HashSet blocks = new HashSet(); private HashMap routes = new HashMap(); - private ControlUnit controlUnit = new ControlUnit(); + private ControlUnit controlUnit = new ControlUnit(this); public Plan() { new Heartbeat().start(); @@ -520,7 +519,7 @@ public class Plan implements Constants{ stream(t("Warning: {}",t("Ghost train @ {}",contact))); } - public CompletableFuture queue(String command) { + public Command queue(Command command) { return controlUnit.queue(command); } } diff --git a/src/main/java/de/srsoftware/web4rail/Route.java b/src/main/java/de/srsoftware/web4rail/Route.java index 1ac8e54..00345c6 100644 --- a/src/main/java/de/srsoftware/web4rail/Route.java +++ b/src/main/java/de/srsoftware/web4rail/Route.java @@ -6,13 +6,13 @@ import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Vector; -import java.util.concurrent.CompletableFuture; import org.json.JSONArray; import org.json.JSONException; @@ -22,7 +22,6 @@ import org.slf4j.LoggerFactory; import de.keawe.tools.translations.Translation; import de.srsoftware.tools.Tag; -import de.srsoftware.web4rail.ControlUnit.Reply; import de.srsoftware.web4rail.Plan.Direction; import de.srsoftware.web4rail.actions.Action; import de.srsoftware.web4rail.actions.ActivateRoute; @@ -292,34 +291,20 @@ public class Route implements Constants{ file.close(); } - public CompletableFuture lock(Train train) throws IOException { - Vector locked = new Vector(); + public boolean lock() { + + ArrayList lockedTiles = new ArrayList(); try { - for (Tile tile : path) locked.add(tile.lock(this)); // try to lock all tiles along the path - } catch (Exception e) { // if something fails: unlock all tiles locked so far - for (Tile tile : locked) try { + for (Tile tile : path) lockedTiles.add(tile.lock(this)); + } catch (IOException e) { + for (Tile tile: lockedTiles) try { tile.unlock(); - } catch (IOException ex) { - LOG.warn("Problem while unlocking {}",ex); + } catch (IOException inner) { + LOG.warn("Was not able to unlock {}!",tile,inner); } - throw e; + return false; } - CompletableFuture promise = null; - for (Entry entry : turnouts.entrySet()) {// try to switch all turnouts of this route - CompletableFuture reply = entry.getKey().state(entry.getValue()); // switching a turnout is an asynchronous process, so it returns a CompletableFuture here - promise = promise == null ? reply : promise.thenCombine(reply, (a,b) -> a); - } - if (promise == null) promise = CompletableFuture.completedFuture(null); - promise.exceptionally(ex -> { - for (Tile tile : locked) try { - tile.unlock(); - } catch (IOException e) { - LOG.warn("Problem while unlocking {}",e); - } - throw new RuntimeException(ex); - }).thenRun(() -> this.train = train); - - return promise; + return true; } public List multiply(int size) { @@ -413,9 +398,27 @@ public class Route implements Constants{ if (lastTile instanceof Turnout) addTurnout((Turnout) lastTile,state); } - public Route setSignals(String state) throws IOException { - for (Signal signal : signals) signal.state(state == null ? "go" : state); - return this; + public boolean setSignals(String state) throws IOException { + for (Signal signal : signals) { + if (!signal.state(state == null ? Signal.GO : state)) return false; + } + return true; + } + + public boolean setTurnouts() { + Turnout turnout = null; + for (Entry entry : turnouts.entrySet()) try { + turnout = entry.getKey(); + State targetVal = entry.getValue(); + if (!turnout.state(targetVal).succeeded()) return false; + try { + Thread.sleep(500); + } catch (InterruptedException e) {} + } catch (IOException e) { + LOG.warn("Was not able to switch turnout {}!",turnout,e); + return false; + } + return true; } public Route start(Block block,Direction from) { @@ -443,6 +446,12 @@ public class Route implements Constants{ return getClass().getSimpleName()+"("+name()+")"; } + public boolean train(Train train) { + if (this.train != null && this.train != train) return false; + this.train = train; + return true; + } + public Route unlock() throws IOException { setSignals(Signal.STOP); for (Tile tile : path) tile.unlock(); diff --git a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java index 2ec04eb..0f7c716 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java @@ -7,6 +7,7 @@ import java.util.Vector; import org.json.JSONObject; import de.srsoftware.tools.Tag; +import de.srsoftware.web4rail.Command; import de.srsoftware.web4rail.Constants; import de.srsoftware.web4rail.Device; import de.srsoftware.web4rail.Plan; @@ -146,7 +147,20 @@ public class Locomotive extends Car implements Constants,Device{ case ZIMO: proto = "Z"; break; } - plan.queue("INIT {} GL "+address+" "+proto); + plan.queue(new Command("INIT {} GL "+address+" "+proto) { + + @Override + public void onSuccess() { + super.onSuccess(); + plan.stream(t("{} initialized.",this)); + } + + @Override + public void onFailure(Reply r) { + super.onFailure(r); + plan.stream(t("Was not able to initialize {}!",this)); + } + }); init = true; } @@ -226,7 +240,14 @@ public class Locomotive extends Car implements Constants,Device{ } private void queue() { - plan.queue("SET {} GL "+address+" "+(reverse?1:0)+" "+speed+" "+VMAX+" "+(f1?1:0)+" "+(f2?1:0)+" "+(f3?1:0)+" "+(f4?1:0)); + plan.queue(new Command("SET {} GL "+address+" "+(reverse?1:0)+" "+speed+" "+VMAX+" "+(f1?1:0)+" "+(f2?1:0)+" "+(f3?1:0)+" "+(f4?1:0)) { + + @Override + public void onFailure(Reply reply) { + super.onFailure(reply); + plan.stream(t("Failed to send command to {}: {}",this,reply.message())); + } + }); } public String setSpeed(int newSpeed) { diff --git a/src/main/java/de/srsoftware/web4rail/moving/Train.java b/src/main/java/de/srsoftware/web4rail/moving/Train.java index 6a745d7..9e64b93 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Train.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Train.java @@ -23,6 +23,7 @@ import de.srsoftware.web4rail.Application; import de.srsoftware.web4rail.Constants; import de.srsoftware.web4rail.Plan; import de.srsoftware.web4rail.Plan.Direction; +import de.srsoftware.web4rail.actions.SetSignalsToStop; import de.srsoftware.web4rail.Route; import de.srsoftware.web4rail.Window; import de.srsoftware.web4rail.tags.Button; @@ -366,22 +367,18 @@ public class Train implements Constants { if (availableRoutes.isEmpty()) return t("No free routes from {}",block); route = availableRoutes.get(rand.nextInt(availableRoutes.size())); - route.lock(this).thenApply(reply -> { - try { - route.setSignals(null); - if (direction != route.startDirection) turn(); - setSpeed(100); - return t("started {}",this); - } catch (Exception e) { - throw new RuntimeException(e); - } - }).thenAccept(message -> plan.stream(message)) - .exceptionally(ex -> { - plan.stream(ex.getMessage()); - throw new RuntimeException(ex); - }); - - return t("Trying to start {}",this); + if (!route.lock()) return t("Was not able to lock {}",route); + String error = null; + if (!route.setTurnouts()) error = t("Was not able to set all turnouts!"); + if (error == null && !route.setSignals(null)) error = t("Was not able to set all signals!"); + if (error == null && !route.train(this)) error = t("Was not able to assign {} to {}!",this,route); + if (error == null) { + setSpeed(128); + return t("Started {}",this); + } + route.unlock(); + this.block.train(this); // re-set train on previous block + return error; } private Object stop() { diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Signal.java b/src/main/java/de/srsoftware/web4rail/tiles/Signal.java index c4f7ea3..15b326e 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Signal.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Signal.java @@ -10,6 +10,7 @@ import de.srsoftware.web4rail.Plan.Direction; public abstract class Signal extends Tile{ public static final String STOP = "stop"; + public static final String GO = "go"; private String state = STOP; public Signal() { @@ -25,9 +26,10 @@ public abstract class Signal extends Tile{ public abstract boolean isAffectedFrom(Direction dir); - public void state(String state) throws IOException { + public boolean state(String state) throws IOException { this.state = state; plan.stream("place "+tag(null)); + return true; } @Override diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java b/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java index 968d90f..4b5f685 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java @@ -3,12 +3,13 @@ package de.srsoftware.web4rail.tiles; import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeoutException; import org.json.JSONObject; import de.srsoftware.tools.Tag; -import de.srsoftware.web4rail.ControlUnit.Reply; +import de.srsoftware.web4rail.Command; +import de.srsoftware.web4rail.Command.Reply; import de.srsoftware.web4rail.Device; import de.srsoftware.web4rail.Protocol; import de.srsoftware.web4rail.tags.Fieldset; @@ -41,6 +42,8 @@ public abstract class Turnout extends Tile implements Device{ init(); return super.click(); } + + protected abstract String commandFor(State newState); public void error(Reply reply) { this.error = true; @@ -52,11 +55,30 @@ public abstract class Turnout extends Tile implements Device{ throw new RuntimeException(reply.message()); } - protected void init() { + protected Reply init() { if (!initialized) { - plan.queue("INIT {} GA "+address+" "+proto()); - initialized = true; + Command command = new Command("INIT {} GA "+address+" "+proto()) { + + @Override + public void onSuccess() { + super.onSuccess(); + initialized = true; + } + + @Override + public void onFailure(Reply r) { + super.onSuccess(); + initialized = false; + } + + }; + try { + return plan.queue(command).reply(); + } catch (TimeoutException e) { + LOG.warn(e.getMessage()); + } } + return new Reply(200, "OK"); } @Override @@ -111,7 +133,37 @@ public abstract class Turnout extends Tile implements Device{ return state; } - public abstract CompletableFuture state(State newState) throws IOException; + public Reply state(State newState) throws IOException { + Reply reply = init(); + if (reply != null && !reply.succeeded()) return reply; + LOG.debug("Setting {} to {}",this,newState); + try { + String cmd = commandFor(newState); + return plan.queue(new Command(cmd) { + + @Override + public void onSuccess() { + super.onSuccess(); + try { + Turnout.this.state = newState; + plan.place(Turnout.this); + } catch (IOException e) {} + } + + @Override + protected void onFailure(Reply reply) { + super.onFailure(reply); + plan.stream(t("Unable to switch {}: {}",this,reply.message())); + } + + }).reply(); + } catch (TimeoutException e) { + LOG.warn(e.getMessage()); + } + return new Reply(417,t("Timeout while trying to switch {}.",this)); + + + } public void success() { this.error = false; diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Turnout3E.java b/src/main/java/de/srsoftware/web4rail/tiles/Turnout3E.java index e0a02fb..42769fa 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Turnout3E.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Turnout3E.java @@ -1,16 +1,19 @@ package de.srsoftware.web4rail.tiles; -import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.CompletableFuture; import de.srsoftware.web4rail.Connector; -import de.srsoftware.web4rail.ControlUnit.Reply; import de.srsoftware.web4rail.Plan.Direction; public class Turnout3E extends Turnout{ + @Override + public String commandFor(State newState) { + LOG.warn("Turnout3E.state({}) not implemented, yet!",newState); + throw new IllegalStateException(); + } + @Override public Map connections(Direction from) { switch (from) { @@ -29,11 +32,4 @@ public class Turnout3E extends Turnout{ return new HashMap<>(); } } - - @Override - public CompletableFuture state(State newState) throws IOException { - // TODO Auto-generated method stub - LOG.warn("Turnout3E.state({}) not implemented, yet!",newState); - return null; - } } diff --git a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java index 74f76f4..34b0e07 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java @@ -2,10 +2,8 @@ package de.srsoftware.web4rail.tiles; import java.io.IOException; import java.util.HashMap; -import java.util.concurrent.CompletableFuture; import de.srsoftware.tools.Tag; -import de.srsoftware.web4rail.ControlUnit.Reply; import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Input; import de.srsoftware.web4rail.tags.Label; @@ -19,16 +17,22 @@ public class TurnoutL extends Turnout { Object o = super.click(); if (route != null) { plan.stream(t("{} is locked by {}!",this,route)); - } else { - CompletableFuture promise = state(state == State.STRAIGHT ? State.LEFT : State.STRAIGHT); - promise.exceptionally(ex -> { - LOG.warn("Failed to toggle turnout: ",ex); - throw new RuntimeException(ex); - }).thenAccept(reply -> LOG.debug("Success: {}",reply)); - } + } else state(state == State.STRAIGHT ? State.LEFT : State.STRAIGHT); return o; } + @Override + protected String commandFor(State newState) { + switch (newState) { + case LEFT: + return "SET {} GA "+address+" "+portB+" 1 "+delay; + case STRAIGHT: + return "SET {} GA "+address+" "+portA+" 1 "+delay; + default: + throw new IllegalStateException(); + } + } + @Override public Tag propForm() { Tag form = super.propForm(); @@ -43,31 +47,7 @@ public class TurnoutL extends Turnout { new Input(LEFT, portB).numeric().addTo(new Label(t("Left port"))).addTo(fieldset); return form; } - - @Override - public CompletableFuture state(State newState) throws IOException { - init(); - LOG.debug("Requesting to set {} to {}",this,newState); - CompletableFuture result; - switch (newState) { - case LEFT: - result = plan.queue("SET {} GA "+address+" "+portB+" 1 "+delay); - break; - case STRAIGHT: - result = plan.queue("SET {} GA "+address+" "+portA+" 1 "+delay); - break; - default: - throw new IllegalStateException(); - } - return result.thenApply(reply -> { - LOG.debug("{} received {}",getClass().getSimpleName(),reply); - if (!reply.is(200)) error(reply); - state = newState; - success(); - return reply; - }); - } - + @Override public Tile update(HashMap params) throws IOException { if (params.containsKey(STRAIGHT)) portA = Integer.parseInt(params.get(STRAIGHT)); diff --git a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java index 599aaef..21489ff 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java @@ -2,10 +2,8 @@ package de.srsoftware.web4rail.tiles; import java.io.IOException; import java.util.HashMap; -import java.util.concurrent.CompletableFuture; import de.srsoftware.tools.Tag; -import de.srsoftware.web4rail.ControlUnit.Reply; import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Input; import de.srsoftware.web4rail.tags.Label; @@ -23,6 +21,19 @@ public class TurnoutR extends Turnout { return o; } + @Override + public String commandFor(State newState) { + + switch (newState) { + case RIGHT: + return "SET {} GA "+address+" "+portB+" 1 "+delay; + case STRAIGHT: + return "SET {} GA "+address+" "+portA+" 1 "+delay; + default: + throw new IllegalStateException(); + } + } + @Override public Tag propForm() { Tag form = super.propForm(); @@ -44,28 +55,4 @@ public class TurnoutR extends Turnout { if (params.containsKey(RIGHT)) portB = Integer.parseInt(params.get(RIGHT)); return super.update(params); } - - @Override - public CompletableFuture state(State newState) throws IOException { - init(); - LOG.debug("Setting {} to {}",this,newState); - CompletableFuture result; - switch (newState) { - case RIGHT: - result = plan.queue("SET {} GA "+address+" "+portB+" 1 "+delay); - break; - case STRAIGHT: - result = plan.queue("SET {} GA "+address+" "+portA+" 1 "+delay); - break; - default: - throw new IllegalStateException(); - } - return result.thenApply(reply -> { - LOG.debug("{} received {}",getClass().getSimpleName(),reply); - if (!reply.is(200)) error(reply); - state = newState; - success(); - return reply; - }); - } }