diff --git a/.classpath b/.classpath index 899de31..d88872f 100644 --- a/.classpath +++ b/.classpath @@ -6,18 +6,13 @@ + + - - - - - - - diff --git a/pom.xml b/pom.xml index b80a7fe..45a2556 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 de.srsoftware web4rail - 0.5.4 + 0.5.5 Web4Rail Java Model Railway Control https://github.com/StephanRichter/Web4Rail @@ -33,7 +33,7 @@ de.srsoftware tools - 1.1.8 + 1.1.9 compile diff --git a/resources/logback.xml b/resources/logback.xml new file mode 100644 index 0000000..c22c8ca --- /dev/null +++ b/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n + + + + + + + \ No newline at end of file diff --git a/src/main/java/de/srsoftware/web4rail/Application.java b/src/main/java/de/srsoftware/web4rail/Application.java index bbbb58c..f95fe36 100644 --- a/src/main/java/de/srsoftware/web4rail/Application.java +++ b/src/main/java/de/srsoftware/web4rail/Application.java @@ -10,6 +10,8 @@ import java.io.OutputStreamWriter; import java.lang.reflect.InvocationTargetException; import java.net.InetSocketAddress; import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; import java.net.URLDecoder; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -30,7 +32,7 @@ public class Application { private static final Logger LOG = LoggerFactory.getLogger(Application.class); private static final String PORT = "port"; private static final Charset UTF8 = StandardCharsets.UTF_8; - + public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { Configuration config = new Configuration(Configuration.dir("Web4Rail")+"/app.config"); LOG.debug("Config: {}",config); diff --git a/src/main/java/de/srsoftware/web4rail/ControlUnit.java b/src/main/java/de/srsoftware/web4rail/ControlUnit.java index b5c489d..1ef016c 100644 --- a/src/main/java/de/srsoftware/web4rail/ControlUnit.java +++ b/src/main/java/de/srsoftware/web4rail/ControlUnit.java @@ -45,7 +45,7 @@ public class ControlUnit extends Thread{ milis = Integer.parseInt(word.substring(word.length()-3)); code = scanner.nextInt(); message = scanner.nextLine().trim(); - LOG.debug("recv {}.{} {} {}.",secs,milis,code,message); + LOG.info("recv {}.{} {} {}.",secs,milis,code,message); } @Override @@ -211,7 +211,7 @@ public class ControlUnit extends Thread{ private void writeln(String data) throws IOException { data = data.replace("{}", ""+bus); socket.getOutputStream().write((data+"\n").getBytes(StandardCharsets.US_ASCII)); - LOG.debug("sent {}.",data); + LOG.info("sent {}.",data); } public void update(HashMap params) { diff --git a/src/main/java/de/srsoftware/web4rail/Device.java b/src/main/java/de/srsoftware/web4rail/Device.java new file mode 100644 index 0000000..884d756 --- /dev/null +++ b/src/main/java/de/srsoftware/web4rail/Device.java @@ -0,0 +1,7 @@ +package de.srsoftware.web4rail; + +public interface Device { + public static final String ADDRESS = "address"; + public static final String PORT = "port"; + public static final String PROTOCOL = "proto"; +} diff --git a/src/main/java/de/srsoftware/web4rail/Plan.java b/src/main/java/de/srsoftware/web4rail/Plan.java index fb4e60d..2d2b525 100644 --- a/src/main/java/de/srsoftware/web4rail/Plan.java +++ b/src/main/java/de/srsoftware/web4rail/Plan.java @@ -299,11 +299,15 @@ public class Plan { LOG.warn("Was not able to load routes!",e); } try { - plan.controlUnit.load(filename+".cu"); - plan.controlUnit.start(); + plan.controlUnit.load(filename+".cu"); } catch (Exception e) { LOG.warn("Was not able to load control unit settings!",e); } + try { + plan.controlUnit.start(); + } catch (Exception e) { + LOG.warn("Was not able to establish connection to control unit!"); + } return plan; } diff --git a/src/main/java/de/srsoftware/web4rail/Protocol.java b/src/main/java/de/srsoftware/web4rail/Protocol.java new file mode 100644 index 0000000..a7f934b --- /dev/null +++ b/src/main/java/de/srsoftware/web4rail/Protocol.java @@ -0,0 +1,12 @@ +package de.srsoftware.web4rail; + +public enum Protocol{ + DCC14, + DCC27, + DCC28, + DCC128, + MOTO, + FLEISCH, + SELECTRIX, + ZIMO; +} diff --git a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java index a3ced8c..e7d3668 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java @@ -6,7 +6,9 @@ import java.util.Vector; import org.json.JSONObject; import de.srsoftware.tools.Tag; +import de.srsoftware.web4rail.Device; import de.srsoftware.web4rail.Plan; +import de.srsoftware.web4rail.Protocol; import de.srsoftware.web4rail.Window; import de.srsoftware.web4rail.tags.Button; import de.srsoftware.web4rail.tags.Fieldset; @@ -15,16 +17,10 @@ import de.srsoftware.web4rail.tags.Input; import de.srsoftware.web4rail.tags.Label; import de.srsoftware.web4rail.tags.Radio; -public class Locomotive extends Car { - - public enum Protocol{ - DCC14,DCC27,DCC28,DCC128,MOTO,FLEISCH,SELECTRIX,ZIMO; - } +public class Locomotive extends Car implements Device{ private static final String REVERSE = "reverse"; public static final String LOCOMOTIVE = "locomotive"; - private static final String PROTOCOL = "protocol"; - private static final String ADDRESS = "address"; private boolean reverse = false; private Protocol proto = Protocol.DCC128; private int address = 3; diff --git a/src/main/java/de/srsoftware/web4rail/tags/Fieldset.java b/src/main/java/de/srsoftware/web4rail/tags/Fieldset.java index 53ae9f7..fcd5303 100644 --- a/src/main/java/de/srsoftware/web4rail/tags/Fieldset.java +++ b/src/main/java/de/srsoftware/web4rail/tags/Fieldset.java @@ -5,9 +5,10 @@ import de.srsoftware.tools.Tag; public class Fieldset extends Tag { private static final long serialVersionUID = -1643025934527173421L; + public static final String TYPE = "fieldset"; public Fieldset(String title) { - super("fieldset"); + super(TYPE); if (title != null) new Tag("legend").content(title).addTo(this); } } diff --git a/src/main/java/de/srsoftware/web4rail/tags/Input.java b/src/main/java/de/srsoftware/web4rail/tags/Input.java index 3bbd63d..ac9bd02 100644 --- a/src/main/java/de/srsoftware/web4rail/tags/Input.java +++ b/src/main/java/de/srsoftware/web4rail/tags/Input.java @@ -18,5 +18,10 @@ public class Input extends Tag{ public Tag hideIn(Tag form) { return this.attr("type", "hidden").addTo(form); - } + } + + public Input numeric() { + attr("type","numeric"); + return this; + } } diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java index cececa8..7546063 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java @@ -78,6 +78,7 @@ public abstract class Tile { } public Object click() throws IOException { + LOG.debug("Tile.click()"); return propMenu(); } diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java b/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java index 7fc0b81..72d3f2a 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java @@ -1,27 +1,126 @@ package de.srsoftware.web4rail.tiles; import java.io.IOException; +import java.util.HashMap; import java.util.Map; +import org.json.JSONObject; + import de.srsoftware.tools.Tag; +import de.srsoftware.web4rail.Device; +import de.srsoftware.web4rail.Protocol; +import de.srsoftware.web4rail.tags.Fieldset; +import de.srsoftware.web4rail.tags.Input; +import de.srsoftware.web4rail.tags.Label; +import de.srsoftware.web4rail.tags.Radio; -public abstract class Turnout extends Tile { +public abstract class Turnout extends Tile implements Device{ public static final String STATE = "state"; + private static final String PORT_A = "port_a"; + private static final String PORT_B = "port_b"; + protected static final String STRAIGHT = "straight"; + + private Protocol protocol = Protocol.DCC128; + protected int address = 0; + protected int portA = 0, portB = 0; + protected int delay = 400; + protected boolean initialized; + public enum State{ LEFT,STRAIGHT,RIGHT,UNDEF; } + protected State state = State.STRAIGHT; - public State state() { - return state; + @Override + public Object click() throws IOException { + LOG.debug("Turnout.click()"); + Object o = super.click(); + if (address != 0 && !initialized) { + String p = null; + switch (protocol) { + case DCC14: + case DCC27: + case DCC28: + case DCC128: + p = "N"; + break; + case MOTO: + p = "M"; + break; + case SELECTRIX: + p = "S"; + break; + default: + p = "P"; + } + plan.queue("INIT {} GA "+address+" "+p); + initialized = true; + } + return o; + } + + protected void init() { + if (!initialized) { + plan.queue("INIT {} GA "+address+" "+proto()); + initialized = true; + } + } + + @Override + public JSONObject json() { + JSONObject json = super.json(); + if (portA != 0) json.put(PORT_A, portA); + if (portB != 0) json.put(PORT_B, portB); + if (address != 0) json.put(ADDRESS, address); + json.put(PROTOCOL, protocol); + return json; + } + + @Override + protected Tile load(JSONObject json) throws IOException { + if (json.has(ADDRESS)) address = json.getInt(ADDRESS); + if (json.has(PORT_A)) portA = json.getInt(PORT_A); + if (json.has(PORT_B)) portB = json.getInt(PORT_B); + if (json.has(PROTOCOL)) protocol = Protocol.valueOf(json.getString(PROTOCOL)); + return super.load(json); } - public void state(State newState) throws IOException { - state = newState; - LOG.debug("Setting {} to {}",this,state); - plan.stream("place "+tag(null)); + @Override + public Tag propForm() { + Tag form = super.propForm(); + Fieldset fieldset = new Fieldset(t("Decoder settings")); + Label protocol = new Label(t("Protocol:")); + for (Protocol proto : Protocol.values()) { + new Radio(PROTOCOL, proto.toString(), t(proto.toString()), proto == this.protocol).addTo(protocol); + } + protocol.addTo(fieldset).addTo(form); + new Input(ADDRESS, address).numeric().addTo(new Label(t("Address"))).addTo(fieldset); + return form; } + private char proto() { + switch (protocol) { + case DCC14: + case DCC27: + case DCC28: + case DCC128: + return 'N'; + case MOTO: + return 'M'; + case SELECTRIX: + return 'S'; + default: + return 'P'; + } + } + + public State state() { + return state; + } + + public abstract void state(State newState) throws IOException; + @Override public Tag tag(Map replacements) throws IOException { Tag tag = super.tag(replacements); @@ -32,4 +131,13 @@ public abstract class Turnout extends Tile { public void toggle() { state = State.STRAIGHT; } + + @Override + public Tile update(HashMap params) throws IOException { + if (params.containsKey(PROTOCOL)) protocol = Protocol.valueOf(params.get(PROTOCOL)); + if (params.containsKey(ADDRESS)) address = Integer.parseInt(params.get(ADDRESS)); + if (params.containsKey(PORT_A)) portA = Integer.parseInt(params.get(PORT_A)); + if (params.containsKey(PORT_B)) portB = Integer.parseInt(params.get(PORT_B)); + return super.update(params); + } } diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Turnout3E.java b/src/main/java/de/srsoftware/web4rail/tiles/Turnout3E.java index 0dfaa48..e64971d 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Turnout3E.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Turnout3E.java @@ -1,5 +1,6 @@ package de.srsoftware.web4rail.tiles; +import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -26,4 +27,10 @@ public class Turnout3E extends Turnout{ return new HashMap<>(); } } + + @Override + public void state(State newState) throws IOException { + // TODO Auto-generated method stub + LOG.warn("Turnout3E.state({}) not implemented, yet!",newState); + } } diff --git a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java index c59d8c7..c522425 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java @@ -1,16 +1,65 @@ package de.srsoftware.web4rail.tiles; import java.io.IOException; +import java.util.HashMap; + +import de.srsoftware.tools.Tag; +import de.srsoftware.web4rail.tags.Fieldset; +import de.srsoftware.web4rail.tags.Input; +import de.srsoftware.web4rail.tags.Label; public class TurnoutL extends Turnout { + + private static final String LEFT = "left"; + @Override public Object click() throws IOException { + LOG.debug("TurnoutL.click()"); + Object o = super.click(); if (route != null) { plan.stream(t("{} is locked by {}!",this,route)); - } else { - state = (state == State.STRAIGHT) ? State.LEFT : State.STRAIGHT; - plan.stream("place "+tag(null)); + } else state(state == State.STRAIGHT ? State.LEFT : State.STRAIGHT); + return o; + } + + @Override + public Tag propForm() { + Tag form = super.propForm(); + Tag fieldset = null; + for (Tag child : form.children()) { + if (child.is(Fieldset.TYPE)) { + fieldset = child; + break; + } + } + new Input(STRAIGHT, portA).numeric().addTo(new Label(t("Straight port"))).addTo(fieldset); + new Input(LEFT, portB).numeric().addTo(new Label(t("Left port"))).addTo(fieldset); + return form; + } + + @Override + public Tile update(HashMap params) throws IOException { + if (params.containsKey(STRAIGHT)) portA = Integer.parseInt(params.get(STRAIGHT)); + if (params.containsKey(LEFT)) portB = Integer.parseInt(params.get(LEFT)); + return super.update(params); + } + + @Override + public void state(State newState) throws IOException { + init(); + LOG.debug("Setting {} to {}",this,newState); + int p = 0; + switch (newState) { + case LEFT: + p = portB; + break; + case STRAIGHT: + p = portA; + break; + default: } - return propMenu(); + if (p != 0) plan.queue("SET {} GA "+address+" "+p+" 1 "+delay); + state = newState; + plan.stream("place "+tag(null)); } } diff --git a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java index 46b08dc..bd488b3 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java @@ -1,16 +1,65 @@ package de.srsoftware.web4rail.tiles; import java.io.IOException; +import java.util.HashMap; + +import de.srsoftware.tools.Tag; +import de.srsoftware.web4rail.tags.Fieldset; +import de.srsoftware.web4rail.tags.Input; +import de.srsoftware.web4rail.tags.Label; public class TurnoutR extends Turnout { + + private static final String RIGHT = "right"; + @Override public Object click() throws IOException { + LOG.debug("Turnoutr.click()"); + Object o = super.click(); if (route != null) { plan.stream(t("{} is locked by {}!",this,route)); - } else { - state = (state == State.STRAIGHT) ? State.RIGHT : State.STRAIGHT; - plan.stream("place "+tag(null)); + } else state(state == State.STRAIGHT ? State.RIGHT : State.STRAIGHT); + return o; + } + + @Override + public Tag propForm() { + Tag form = super.propForm(); + Tag fieldset = null; + for (Tag child : form.children()) { + if (child.is(Fieldset.TYPE)) { + fieldset = child; + break; + } + } + new Input(STRAIGHT, portA).addTo(new Label(t("Straight port"))).addTo(fieldset); + new Input(RIGHT, portB).addTo(new Label(t("Right port"))).addTo(fieldset); + return form; + } + + @Override + public Tile update(HashMap params) throws IOException { + if (params.containsKey(STRAIGHT)) portA = Integer.parseInt(params.get(STRAIGHT)); + if (params.containsKey(RIGHT)) portB = Integer.parseInt(params.get(RIGHT)); + return super.update(params); + } + + @Override + public void state(State newState) throws IOException { + init(); + LOG.debug("Setting {} to {}",this,newState); + int p = 0; + switch (newState) { + case RIGHT: + p = portB; + break; + case STRAIGHT: + p = portA; + break; + default: } - return propMenu(); + if (p != 0) plan.queue("SET {} GA "+address+" "+p+" 1 "+delay); + state = newState; + plan.stream("place "+tag(null)); } }