Skip to content

Commit e40579a

Browse files
authored
Merge pull request #83 from fransjacobs/79-when-auto-mode-is-stopped-dispatchers-do-not-continue-until-destination-is-reached
79 when auto mode is stopped dispatchers do not continue until destination is reached
2 parents 0627e2c + 0626127 commit e40579a

33 files changed

+1243
-484
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ The aim of the program is to automate the running of trains on my layout.
3131
* [Marklin CS-2](https://www.marklin.nl/producten/details/article/60215)
3232
* [Marklin CS-3](https://www.marklin.nl/producten/details/article/60216)
3333
* [HSI-S88](https://www.ldt-infocenter.com/dokuwiki/doku.php?id=en:hsi-88-usb) or the [DIY version](https://mobatron.4lima.de/2020/05/s88-scanner-mit-arduino) for feedback
34+
35+
## NEW
36+
* Layout router, After the layout is created automatically all driveways are calculated.
37+
* Autopilot, automatically drive locomotives.
38+
* Virtual Command station.
39+
* Auto [Simulator](https://youtu.be/xP6eUdScMY0) in the Virtual Commandstation to test routes.
3440

3541
## Current status
3642
Currently the following modules are build:

src/main/java/jcs/commandStation/AbstractController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public void removeDisconnectionEventListener(DisconnectionEventListener listener
8989
this.disconnectionEventListeners.remove(listener);
9090
}
9191

92-
public boolean isPower() {
92+
public synchronized boolean isPower() {
9393
return this.power;
9494
}
9595

src/main/java/jcs/commandStation/JCSCommandStationImpl.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,9 @@ public void changeLocomotiveDirection(Direction newDirection, LocomotiveBean loc
431431
address = locomotive.getUid().intValue();
432432
}
433433
if (decoderController != null) {
434+
//Set the velocity to zero before changing the direction
435+
//Run this in a worker thread...
436+
434437
decoderController.changeVelocity(address, 0, locomotive.getDirection());
435438
decoderController.changeDirection(address, newDirection);
436439
}
@@ -781,7 +784,7 @@ private class LocomotiveDirectionChangeEventListener implements LocomotiveDirect
781784
public void onDirectionChange(LocomotiveDirectionEvent directionEvent) {
782785
LocomotiveBean lb = directionEvent.getLocomotiveBean();
783786
if (lb != null) {
784-
LocomotiveBean dblb;
787+
LocomotiveBean dblb = null;
785788
//For marklin use the ID
786789
if ("marklin.cs".equals(lb.getCommandStationId())) {
787790
dblb = PersistenceFactory.getService().getLocomotive(lb.getId());
@@ -792,7 +795,19 @@ public void onDirectionChange(LocomotiveDirectionEvent directionEvent) {
792795
} else {
793796
address = lb.getId().intValue();
794797
}
795-
dblb = PersistenceFactory.getService().getLocomotive(address, lb.getDecoderType(), lb.getCommandStationId());
798+
if (lb.getDecoderType() != null) {
799+
dblb = PersistenceFactory.getService().getLocomotive(address, lb.getDecoderType(), lb.getCommandStationId());
800+
} else {
801+
//Try to match one...
802+
Set<Protocol> protocols = PersistenceFactory.getService().getDefaultCommandStation().getSupportedProtocols();
803+
for (Protocol protocol : protocols) {
804+
DecoderType decoder = DecoderType.get(protocol.getProtocol());
805+
dblb = PersistenceFactory.getService().getLocomotive(address, decoder, lb.getCommandStationId());
806+
if (dblb != null) {
807+
break;
808+
}
809+
}
810+
}
796811
}
797812

798813
if (dblb != null) {

src/main/java/jcs/commandStation/autopilot/AutoPilot.java

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,31 @@ public synchronized void startAutoMode() {
8585
}
8686
}
8787

88+
public boolean isAutoModeActive() {
89+
if (this.autoPilotThread != null) {
90+
return this.autoPilotThread.isRunning();
91+
} else {
92+
return false;
93+
}
94+
}
95+
96+
boolean isAutoPilotThreadStopped() {
97+
if (this.autoPilotThread != null) {
98+
return this.autoPilotThread.isStopped();
99+
} else {
100+
return true;
101+
}
102+
}
103+
104+
public boolean isRunning(LocomotiveBean locomotive) {
105+
if (this.isAutoModeActive() && this.dispatchers.containsKey(locomotive.getName())) {
106+
Dispatcher dispatcher = this.dispatchers.get(locomotive.getName());
107+
return dispatcher.isRunning();
108+
} else {
109+
return false;
110+
}
111+
}
112+
88113
public synchronized void stopAutoMode() {
89114
this.autoPilotThread.stopAutoMode();
90115
notifyAll();
@@ -142,7 +167,7 @@ public synchronized void clearDispatchers() {
142167

143168
for (Dispatcher dispatcher : this.dispatchers.values()) {
144169
dispatcher.stopLocomotiveAutomode();
145-
dispatcher.forceStopRunning();
170+
//dispatcher.forceStopRunning();
146171
}
147172

148173
this.dispatchers.clear();
@@ -250,6 +275,7 @@ public void resetStates() {
250275
}
251276
default -> {
252277
if (BlockBean.BlockState.OCCUPIED == block.getBlockState()) {
278+
block.setArrivalSuffix(null);
253279
occupiedBlockCounter++;
254280
}
255281
}
@@ -386,23 +412,6 @@ public synchronized void removeAutoPilotStatusListener(AutoPilotStatusListener l
386412
Logger.trace("Status listeners: " + autoPilotStatusListeners.size());
387413
}
388414

389-
public boolean isAutoModeActive() {
390-
if (this.autoPilotThread != null) {
391-
return this.autoPilotThread.isRunning();
392-
} else {
393-
return false;
394-
}
395-
}
396-
397-
public boolean isRunning(LocomotiveBean locomotive) {
398-
if (this.isAutoModeActive() && this.dispatchers.containsKey(locomotive.getName())) {
399-
Dispatcher dispatcher = this.dispatchers.get(locomotive.getName());
400-
return dispatcher.isRunning();
401-
} else {
402-
return false;
403-
}
404-
}
405-
406415
public boolean tryAquireLock() {
407416
return semaphore.tryAcquire();
408417
}
@@ -421,6 +430,7 @@ private class AutoPilotThread extends Thread {
421430
private final List<SensorListener> sensorListeners = new ArrayList<>();
422431

423432
private boolean running = false;
433+
private boolean stopped = false;
424434

425435
AutoPilotThread(AutoPilot autoPilot) {
426436
this.autoPilot = autoPilot;
@@ -508,7 +518,7 @@ public void run() {
508518
if (dispatchersRunning) {
509519
for (Dispatcher ld : dispatchers.values()) {
510520
if (ld.isRunning()) {
511-
ld.forceStopRunning();
521+
//ld.forceStopRunning();
512522
Logger.trace("Forse Stop on " + ld.getName());
513523
}
514524
}
@@ -521,7 +531,12 @@ public void run() {
521531
asl.statusChanged(running);
522532
}
523533

524-
Logger.trace("Autopilot Finished. Notify " + autoPilotStatusListeners.size() + " Listeners...");
534+
Logger.trace("Autopilot Finished. Notified " + autoPilotStatusListeners.size() + " Listeners. Power is " + (JCS.getJcsCommandStation().isPowerOn() ? "on" : "off"));
535+
stopped = true;
536+
}
537+
538+
boolean isStopped() {
539+
return this.stopped;
525540
}
526541
}
527542

src/main/java/jcs/commandStation/autopilot/state/Dispatcher.java

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,14 @@ public class Dispatcher {
5353
private String destinationBlockId;
5454

5555
private String waitingForSensorId;
56+
//Enter Sensor of the destination
57+
private String enterSensorId;
58+
//In Sensor of the destination
5659
private String inSensorId;
60+
61+
//The Occupation sensor of the departure
62+
private String occupationSensorId;
63+
//The exit of the departure
5764
private String exitSensorId;
5865

5966
private final List<StateEventListener> stateEventListeners;
@@ -62,8 +69,9 @@ public class Dispatcher {
6269

6370
public Dispatcher(LocomotiveBean locomotiveBean, AutoPilot autoPilot) {
6471
this.locomotiveBean = locomotiveBean;
72+
//Prefill with the current locomotive direction
73+
this.locomotiveBean.setDispatcherDirection(locomotiveBean.getDirection());
6574
this.autoPilot = autoPilot;
66-
6775
this.stateEventListeners = new LinkedList<>();
6876
this.stateMachineThread = new StateMachineThread(this);
6977
}
@@ -107,15 +115,18 @@ public boolean isLocomotiveAutomodeOn() {
107115
return this.stateMachineThread.isEnableAutomode();
108116
}
109117

110-
public void startLocomotiveAutomode() {
111-
stateMachineThread.setEnableAutomode(true);
112-
//is the thread running?
113-
startRunning();
118+
public boolean startLocomotiveAutomode() {
119+
//Only when the Autopilot is ON!
120+
if (autoPilot.isAutoModeActive()) {
121+
stateMachineThread.setEnableAutomode(true);
122+
//is the thread running?
123+
startRunning();
124+
}
125+
return this.stateMachineThread.isEnableAutomode();
114126
}
115127

116128
public void stopLocomotiveAutomode() {
117129
stateMachineThread.setEnableAutomode(false);
118-
stopRunning();
119130
}
120131

121132
void startRunning() {
@@ -139,21 +150,17 @@ void stopRunning() {
139150
}
140151
}
141152

142-
public void forceStopRunning() {
143-
// if (stateMachineThread != null && stateMachineThread.isThreadRunning()) {
144-
// this.stateMachineThread.forceStop();
145-
// }
146-
}
147-
148153
void resetDispatcher() {
149154
this.routeBean = null;
150155
this.departureBlockId = null;
151156
this.destinationBlockId = null;
152157
this.waitingForSensorId = null;
158+
this.enterSensorId = null;
153159
this.inSensorId = null;
154160
this.exitSensorId = null;
155161
this.stateEventListeners.clear();
156-
this.stateMachineThread = new StateMachineThread(this);
162+
this.locomotiveBean.setDispatcherDirection(Direction.SWITCH);
163+
this.stateMachineThread = new StateMachineThread(null);
157164
}
158165

159166
public void reset() {
@@ -220,9 +227,9 @@ String getDestinationArrivalSuffix() {
220227
return destinationArrivalSuffix;
221228
}
222229

223-
public String getDispatcherStateString() {
230+
public String getStateName() {
224231
if (stateMachineThread != null) {
225-
return stateMachineThread.getState().getClass().getSimpleName();
232+
return stateMachineThread.getDispatcherStateName();
226233
} else {
227234
return "#Idle";
228235
}
@@ -237,6 +244,14 @@ public String getWaitingForSensorId() {
237244
return waitingForSensorId;
238245
}
239246

247+
public String getEnterSensorId() {
248+
return enterSensorId;
249+
}
250+
251+
void setEnterSensorId(String enterSensorId) {
252+
this.enterSensorId = enterSensorId;
253+
}
254+
240255
public String getInSensorId() {
241256
return inSensorId;
242257
}
@@ -245,6 +260,14 @@ void setInSensorId(String inSensorId) {
245260
this.inSensorId = inSensorId;
246261
}
247262

263+
public String getOccupationSensorId() {
264+
return occupationSensorId;
265+
}
266+
267+
void setOccupationSensorId(String occupationSensorId) {
268+
this.occupationSensorId = occupationSensorId;
269+
}
270+
248271
public String getExitSensorId() {
249272
return exitSensorId;
250273
}
@@ -265,7 +288,7 @@ void registerIgnoreEventHandler(String sensorId) {
265288

266289
synchronized void clearDepartureIgnoreEventHandlers() {
267290
if (departureBlockId != null) {
268-
BlockBean departureBlock = this.getDepartureBlock();
291+
BlockBean departureBlock = getDepartureBlock();
269292
String minSensorId = departureBlock.getMinSensorId();
270293
autoPilot.removeHandler(minSensorId);
271294
String plusSensorId = departureBlock.getPlusSensorId();
@@ -282,6 +305,12 @@ synchronized void onIgnoreEvent(SensorEvent event) {
282305
}
283306
}
284307

308+
if (this.enterSensorId != null && this.enterSensorId.equals(event.getId())) {
309+
if (!event.isActive()) {
310+
this.enterSensorId = null;
311+
}
312+
}
313+
285314
if (this.inSensorId != null && this.inSensorId.equals(event.getId())) {
286315
if (!event.isActive()) {
287316
this.inSensorId = null;

0 commit comments

Comments
 (0)