diff --git a/pom.xml b/pom.xml
index 7034606..08863d5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
de.srsoftware
web4rail
- 1.4.2
+ 1.4.3
Web4Rail
jar
Java Model Railway Control
diff --git a/src/main/java/de/srsoftware/web4rail/Plan.java b/src/main/java/de/srsoftware/web4rail/Plan.java
index 5bfe737..0580994 100644
--- a/src/main/java/de/srsoftware/web4rail/Plan.java
+++ b/src/main/java/de/srsoftware/web4rail/Plan.java
@@ -886,31 +886,38 @@ public class Plan extends BaseClass{
* @param data
*/
public synchronized void stream(String data) {
- data = data.replaceAll("\n", "").replaceAll("\r", "");
- //if (!data.startsWith("heartbeat")) LOG.debug("streaming: {}",data);
- Vector badClients = null;
- for (Entry entry : clients.entrySet()) {
- OutputStreamWriter client = entry.getKey();
- try {
- client.write("data: "+data+"\n\n");
- client.flush();
- clients.put(client,0);
- } catch (IOException e) {
- int errorCount = entry.getValue()+1;
- LOG.info("Error #{} on client: {}",errorCount,e.getMessage());
- if (errorCount > 4) {
- if (isNull(badClients)) badClients = new Vector();
+ String fixedData = data.replaceAll("\n", "").replaceAll("\r", "");
+ new Thread("Plan") {
+ @Override
+ public void run() {
+ //if (!data.startsWith("heartbeat")) LOG.debug("streaming: {}",data);
+ Vector badClients = null;
+ for (Entry entry : clients.entrySet()) {
+ OutputStreamWriter client = entry.getKey();
try {
- client.close();
- } catch (IOException e1) {}
- badClients.add(client);
- } else clients.put(client,errorCount);
+ client.write("data: "+fixedData+"\n\n");
+ client.flush();
+ clients.put(client,0);
+ } catch (IOException e) {
+ int errorCount = entry.getValue()+1;
+ LOG.info("Error #{} on client: {}",errorCount,e.getMessage());
+ if (errorCount > 4) {
+ if (isNull(badClients)) badClients = new Vector();
+ try {
+ client.close();
+ } catch (IOException e1) {}
+ badClients.add(client);
+ } else clients.put(client,errorCount);
+ }
+ }
+ if (badClients != null) for (OutputStreamWriter client: badClients) {
+ LOG.info("Disconnecting client.");
+ clients.remove(client);
+ }
+ // TODO Auto-generated method stub
}
- }
- if (badClients != null) for (OutputStreamWriter client: badClients) {
- LOG.info("Disconnecting client.");
- clients.remove(client);
- }
+ }.start();
+
}
/**
diff --git a/src/main/java/de/srsoftware/web4rail/Route.java b/src/main/java/de/srsoftware/web4rail/Route.java
index d6df5fc..e8c77e5 100644
--- a/src/main/java/de/srsoftware/web4rail/Route.java
+++ b/src/main/java/de/srsoftware/web4rail/Route.java
@@ -232,9 +232,7 @@ public class Route extends BaseClass {
}
public Integer brakeTime(String brakeId) {
- Integer result = brakeTimes.get(brakeId);
- Collection values = brakeTimes.values();
- return values.isEmpty() ? BrakeProcess.defaultTimeStep : values.stream().mapToInt(Integer::intValue).sum()/values.size();
+ return brakeTimes.get(brakeId);
}
public void brakeTime(String brakeId, Integer newTimeStep) {
@@ -392,6 +390,7 @@ public class Route extends BaseClass {
public void finish(Train train) {
LOG.debug("{}.finish()",this);
train.endRoute(endBlock,endDirection);
+ setSignals(Signal.RED);
freeIgnoring(null);
train = null;
}
diff --git a/src/main/java/de/srsoftware/web4rail/moving/Train.java b/src/main/java/de/srsoftware/web4rail/moving/Train.java
index f1a920d..a3522ef 100644
--- a/src/main/java/de/srsoftware/web4rail/moving/Train.java
+++ b/src/main/java/de/srsoftware/web4rail/moving/Train.java
@@ -362,7 +362,7 @@ public class Train extends BaseClass implements Comparable {
public String directedName(Direction dir) {
String result = name();
- String mark = ""; //isSet(autopilot) ? "ⓐ" : "";
+ String mark = autopilot ? "ⓐ" : "";
if (isNull(dir)) return result;
switch (dir) {
case NORTH:
@@ -418,6 +418,10 @@ public class Train extends BaseClass implements Comparable {
public void endRoute(Block endBlock, Direction endDirection) {
BrakeProcess brake = endBrake();
+ if (endBlock == destination) {
+ quitAutopilot();
+ destination = null;
+ }
if (isSet(brake)) brake.updateTime();
Integer waitTime = route.waitTime();
nextPreparedRoute = route.dropNextPreparedRoute();
@@ -721,11 +725,11 @@ public class Train extends BaseClass implements Comparable {
public String quitAutopilot() {
if (isSet(routePrepper)) routePrepper.stop();
- try {
- return autopilot ? t("Autopilot disabled") : t("Autopilot already was disabled!");
- } finally {
+ if (autopilot) {
autopilot = false;
- }
+ if (isSet(currentBlock)) plan.place(currentBlock);
+ }
+ return null;
}
@Override
@@ -826,7 +830,7 @@ public class Train extends BaseClass implements Comparable {
if (isNull(tile)) return properties(t("Tile {} not known!",dest));
if (tile instanceof Block) {
destination = (Block) tile;
- start(false);
+ start(true);
return t("{} now heading for {}",this,destination);
}
return properties(t("{} is not a block!",tile));
diff --git a/src/main/java/de/srsoftware/web4rail/threads/BrakeProcess.java b/src/main/java/de/srsoftware/web4rail/threads/BrakeProcess.java
index 16fd781..9b53539 100644
--- a/src/main/java/de/srsoftware/web4rail/threads/BrakeProcess.java
+++ b/src/main/java/de/srsoftware/web4rail/threads/BrakeProcess.java
@@ -5,11 +5,14 @@ import org.slf4j.LoggerFactory;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
+import de.srsoftware.web4rail.Route;
import de.srsoftware.web4rail.moving.Train;
public class BrakeProcess extends BaseClass implements Runnable{
private static final Logger LOG = LoggerFactory.getLogger(BrakeProcess.class);
+
+ private static final int SPEED_STEP = 10;
public static int defaultTimeStep = 500;
private Train train;
@@ -19,12 +22,31 @@ public class BrakeProcess extends BaseClass implements Runnable{
private int startSpeed;
private int lastSpeed;
private long lastTime;
+
+ private Integer timeStep;
+
+ private Route route;
+
+ private String brakeId;
public BrakeProcess(Train train) {
- this.train = train;
+ this.train = train;
+ this.brakeId = train.brakeId();
+ this.route = train.route();
new Thread(this, Application.threadName(this)).start();
}
+ private long calcDistance(Integer ts) {
+ long dist = 0;
+ int s = startSpeed;
+ while (s > Train.defaultEndSpeed) {
+ s -= SPEED_STEP;
+ dist += s*ts;
+ }
+ LOG.debug("Estimated distamce with {} ms timestep: {}",ts,dist);
+ return dist;
+ }
+
public BrakeProcess end() {
LOG.debug("{}.end()",this);
ended = true;
@@ -33,14 +55,15 @@ public class BrakeProcess extends BaseClass implements Runnable{
@Override
public void run() {
- Integer delay = train.route().brakeTime(train.brakeId());
+ timeStep = train.route().brakeTime(train.brakeId());
+ if (timeStep == null) timeStep = defaultTimeStep;
startSpeed = train.speed;
lastTime = timestamp();
while (!train.hasNextPreparedRoute()) {
- sleep(delay);
+ sleep(timeStep);
lastSpeed = train.speed;
updateDistance();
- if (lastSpeed > targetSpeed) lastSpeed -= 10;
+ if (lastSpeed > targetSpeed) lastSpeed -= SPEED_STEP;
if (ended) break;
if (lastSpeed <= targetSpeed && (ended = true)) lastSpeed = targetSpeed;
train.setSpeed(lastSpeed);
@@ -62,6 +85,23 @@ public class BrakeProcess extends BaseClass implements Runnable{
public void updateTime() {
updateDistance();
LOG.debug("updateTime(): start speed was {} {}.",startSpeed,BaseClass.speedUnit);
- // TODO
+ Integer newTimeStep = timeStep;
+ long calculated;
+ int step = 32*newTimeStep;
+ for (int i=0; i<20; i++) {
+ step = step/2;
+ if (step<1) step = 1;
+ calculated = calcDistance(newTimeStep);
+ LOG.debug("Calculated distance for step = {} ms: {}",newTimeStep,calculated);
+ LOG.debug("Update step: {}",step);
+ newTimeStep = newTimeStep + (calculated > distance ? -step : step);
+ }
+
+ if (!newTimeStep.equals(timeStep)) {
+ route.brakeTime(brakeId,newTimeStep);
+ calculated = calcDistance(newTimeStep);
+ LOG.debug("Corrected brake timestep for {} @ {} from {} to {} ms.",train,route,timeStep,newTimeStep);
+ LOG.debug("Differemce from estimated distance: {} ({}%)",distance-calculated,100*(distance-calculated)/(float)distance);
+ }
}
}
diff --git a/src/main/java/de/srsoftware/web4rail/threads/ControlUnit.java b/src/main/java/de/srsoftware/web4rail/threads/ControlUnit.java
index 2aae71c..d4e29f5 100644
--- a/src/main/java/de/srsoftware/web4rail/threads/ControlUnit.java
+++ b/src/main/java/de/srsoftware/web4rail/threads/ControlUnit.java
@@ -318,7 +318,7 @@ public class ControlUnit extends Thread implements Constants{
case FEEDBACK:
int addr = Integer.parseInt(parts[5]);
boolean active = !parts[6].equals("0");
- new Thread(Application.threadName("CU.FeedBack("+addr+")")) {
+ new Thread(Application.threadName("CU.Feedback("+addr+")")) {
@Override
public void run() {
plan.sensor(addr,active);
diff --git a/src/main/java/de/srsoftware/web4rail/threads/RoutePrepper.java b/src/main/java/de/srsoftware/web4rail/threads/RoutePrepper.java
index b6b1139..0807305 100644
--- a/src/main/java/de/srsoftware/web4rail/threads/RoutePrepper.java
+++ b/src/main/java/de/srsoftware/web4rail/threads/RoutePrepper.java
@@ -51,13 +51,13 @@ public class RoutePrepper extends BaseClass implements Runnable{
LOG.warn("{}→ {}.availableRoutes called without context.train!", inset, Train.class.getSimpleName());
if (error) return availableRoutes;
- Block destination = train.destination();
if (isSet(startDirection)) {
LOG.debug("{}- Looking for {}-bound routes from {}", inset, startDirection, block);
} else {
LOG.debug("{}- Looking for all routes from {}", inset, block);
}
-
+
+ Block destination = train.destination();
if (isSet(destination) && visitedRoutes.isEmpty()) LOG.debug("{}- Destination: {}", inset, destination);
for (Route routeCandidate : block.leavingRoutes()) {
@@ -68,9 +68,9 @@ public class RoutePrepper extends BaseClass implements Runnable{
}
HashSet stuckTrace = train.stuckTrace(); // if train has been stopped in between two blocks lastly:
- // only allow routes that do not conflict with current train
+ // only allow starting routes that do not conflict with current train
// position
- if (isSet(stuckTrace) && !routeCandidate.path().containsAll(stuckTrace)) {
+ if (isSet(stuckTrace) && visitedRoutes.isEmpty() && !routeCandidate.path().containsAll(stuckTrace)) {
LOG.debug("Stuck train occupies tiles ({}) outside of {} – not allowed.", stuckTrace, routeCandidate);
continue;
}
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Contact.java b/src/main/java/de/srsoftware/web4rail/tiles/Contact.java
index e36953f..cbf28c5 100644
--- a/src/main/java/de/srsoftware/web4rail/tiles/Contact.java
+++ b/src/main/java/de/srsoftware/web4rail/tiles/Contact.java
@@ -84,17 +84,16 @@ public class Contact extends Tile{
} else {
LOG.debug("{} activated.",this);
state = true;
+ stream();
if (isSet(timer)) timer.abort();
Train train = train();
Context context = isSet(train) ? train.contact(this) : new Context(this);
actions.fire(context,"Contact("+addr+")");
for (Listener listener : listeners) listener.fired("Contact("+addr+")");
-
- stream();
}
}
-
+
public int addr() {
return addr;
}
@@ -112,12 +111,7 @@ public class Contact extends Tile{
@Override
public Object click(boolean shift) throws IOException {
- if (!shift) new Thread(Application.threadName(this)) {
- @Override
- public void run() {
- trigger(200);
- }
- }.start();
+ if (!shift) trigger(200);
return super.click(shift);
}
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java
index 992243d..9157059 100644
--- a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java
+++ b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java
@@ -540,7 +540,11 @@ public abstract class Tile extends BaseClass implements Comparable {
oneWay = null;
}
}
- if ("on".equals(params.get(DISABLED))) status = Status.DISABLED;
+ if ("on".equals(params.get(DISABLED))) {
+ status = Status.DISABLED;
+ } else {
+ status = isSet(train) ? Status.OCCUPIED : Status.FREE;
+ }
String len = params.get(LENGTH);
if (isSet(len)) length(Integer.parseInt(len));
super.update(params);