Skip to content

Commit

Permalink
Fix issue with Gosts, Virtual mode is now working with ECoS
Browse files Browse the repository at this point in the history
  • Loading branch information
fransjacobs committed Jan 7, 2025
1 parent 95a0a84 commit c5bec05
Show file tree
Hide file tree
Showing 13 changed files with 84 additions and 139 deletions.
2 changes: 1 addition & 1 deletion src/main/java/jcs/commandStation/GenericController.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import jcs.commandStation.entities.DeviceBean;
import jcs.commandStation.entities.InfoBean;

interface GenericController {
public interface GenericController {

CommandStationBean getCommandStationBean();

Expand Down
10 changes: 7 additions & 3 deletions src/main/java/jcs/commandStation/JCSCommandStationImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -308,13 +308,17 @@ public void disconnect() {

@Override
public void setVirtual(boolean flag) {
Logger.info("Switch Virtual Mode "+(flag?"On":"Off"));

Logger.info("Switch Virtual Mode " + (flag ? "On" : "Off"));
this.decoderController.setVirtual(flag);
}

@Override
public boolean isVirtual() {
return false;
if (this.decoderController != null) {
return this.decoderController.isVirtual();
} else {
return false;
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jcs.commandStation.virtual;
package jcs.commandStation;

import jcs.commandStation.events.SensorEvent;

/**
*
* @author Frans Jacobs
* Virtual Connection is used to 'mock' a 'vendor' connection implementation<br>
* to enable Virtual mode on a CommandStation.
*/
public interface VirtualConnection {

Expand Down
28 changes: 16 additions & 12 deletions src/main/java/jcs/commandStation/autopilot/AutoPilot.java
Original file line number Diff line number Diff line change
Expand Up @@ -388,29 +388,33 @@ public static boolean isGostDetected() {
}

private static void handleGhost(SensorEvent event) {
Logger.warn("Ghost Detected! @ Sensor " + event.getId());
//Switch power OFF!
JCS.getJcsCommandStation().switchPower(false);

//Show the Ghost block
String gostSensorId = event.getId();
//to which block does the sensor belong?
Logger.trace("Check for possible Ghost! @ Sensor " + event.getId());
List<BlockBean> blocks = PersistenceFactory.getService().getBlocks();
String sensorId = event.getId();
for (BlockBean block : blocks) {
if (block.getMinSensorId().equals(gostSensorId) || block.getPlusSensorId().equals(gostSensorId)) {
if ((block.getMinSensorId().equals(sensorId) || block.getPlusSensorId().equals(sensorId)) && block.getLocomotiveId() == null) {
if (event.getSensorBean().isActive()) {
block.setBlockState(BlockBean.BlockState.GHOST);
//Also persist
PersistenceFactory.getService().persist(block);

Logger.warn("Ghost Detected! @ Sensor " + sensorId + " in block " + block.getId());
//Switch power OFF!
JCS.getJcsCommandStation().switchPower(false);

TileEvent tileEvent = new TileEvent(block);
TileFactory.fireTileEventListener(tileEvent);
} else {
block.setBlockState(BlockBean.BlockState.FREE);
if (block.getLocomotiveId() != null) {
//keep state as is
} else {
block.setBlockState(BlockBean.BlockState.FREE);
}
}
TileEvent tileEvent = new TileEvent(block);
TileFactory.fireTileEventListener(tileEvent);

break;
}
}

}

static void handleSensorEvent(SensorEvent event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jcs.commandStation.virtual;
package jcs.commandStation.autopilot;

import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import jcs.JCS;
import jcs.commandStation.AccessoryController;
import jcs.commandStation.DecoderController;
import jcs.commandStation.FeedbackController;
import jcs.commandStation.autopilot.AutoPilot;
import jcs.commandStation.GenericController;
import jcs.commandStation.autopilot.state.Dispatcher;
import jcs.commandStation.events.SensorEvent;
import jcs.entities.LocomotiveBean;
Expand All @@ -38,15 +38,9 @@
public class DriveSimulator {

private final ScheduledExecutorService scheduledExecutor;
private DecoderController decoderController;
private AccessoryController accessoryController;
private FeedbackController feedbackController;

public DriveSimulator(DecoderController decoderController, AccessoryController accessoryController, FeedbackController feedbackController) {
public DriveSimulator() {
this.scheduledExecutor = new ScheduledThreadPoolExecutor(30);
this.decoderController = decoderController;
this.accessoryController = accessoryController;
this.feedbackController = feedbackController;
}

//Find the route the locomotive is doing....
Expand All @@ -63,46 +57,46 @@ public void simulateDriving(int locUid, int speed, LocomotiveBean.Direction dire
String occupationSensorId = dispatcher.getOccupationSensorId();
if (occupationSensorId != null) {
//Start a timer which execute a worker thread which fires the sensor
scheduledExecutor.schedule(() -> toggleSensor(occupationSensorId), 500, TimeUnit.MILLISECONDS);
scheduledExecutor.schedule(() -> setSensorValue(occupationSensorId, false), 500, TimeUnit.MILLISECONDS);
}

String exitSensorId = dispatcher.getExitSensorId();
if (exitSensorId != null) {
//Start a time which execute a worker thread which fires the sensor
scheduledExecutor.schedule(() -> toggleSensor(exitSensorId), 1500, TimeUnit.MILLISECONDS);
scheduledExecutor.schedule(() -> setSensorValue(exitSensorId, false), 1500, TimeUnit.MILLISECONDS);
}

String enterSensorId = dispatcher.getEnterSensorId();
String inSensorId = dispatcher.getInSensorId();

String sensorId = dispatcher.getWaitingForSensorId();

int time = 3000;
int time = 5000;
if (sensorId != null && sensorId.equals(enterSensorId)) {
time = 3000;
Logger.debug("Waiting " + time + "ms for Enter Sensor " + sensorId);
}

if (sensorId != null && sensorId.equals(inSensorId)) {
time = 1000;
Logger.debug("Waiting " + time + "ms for In Sensor " + sensorId);
}

if (sensorId != null) {
//Start a time which execute a worker thread which fires the sensor
scheduledExecutor.schedule(() -> toggleSensor(sensorId), time, TimeUnit.MILLISECONDS);
scheduledExecutor.schedule(() -> setSensorValue(sensorId, true), time, TimeUnit.MILLISECONDS);
}
}
}

private void toggleSensor(String sensorId) {
private void setSensorValue(String sensorId, boolean active) {
SensorBean sensor = PersistenceFactory.getService().getSensor(sensorId);

//TODO why toggle and then set active?
sensor.toggle();
sensor.setActive((sensor.getStatus() == 1));

sensor.setActive(active);
SensorEvent sensorEvent = new SensorEvent(sensor);
Logger.trace("Fire Sensor " + sensorId);
Logger.trace("Fire Sensor " + sensorId+" to "+active);

List<FeedbackController> acl = JCS.getJcsCommandStation().getFeedbackControllers();
for (FeedbackController fbc : acl) {
//fbc.fireSensorEventListeners(sensorEvent);

fbc.simulateSensor(sensorEvent);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/jcs/commandStation/esu/ecos/EcosManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ private void parse(EcosMessage msg) {
String prevStatus = this.status;
this.status = values.get(Ecos.STATUS).toString();

if (event && !status.equals(prevStatus)) {
if (!status.equals(prevStatus)) {
boolean power = Ecos.GO.equals(status);
Logger.trace("Power changed to: " + (power ? "On" : "Off"));
PowerEvent pe = new PowerEvent(power);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
import jcs.commandStation.events.LocomotiveSpeedEvent;
import jcs.commandStation.events.LocomotiveSpeedEventListener;
import jcs.commandStation.events.SensorEventListener;
import jcs.commandStation.virtual.DriveSimulator;
import jcs.commandStation.virtual.VirtualConnection;
import jcs.commandStation.autopilot.DriveSimulator;
import jcs.commandStation.VirtualConnection;
import static jcs.entities.AccessoryBean.AccessoryValue.GREEN;
import static jcs.entities.AccessoryBean.AccessoryValue.RED;
import jcs.entities.LocomotiveBean;
Expand Down Expand Up @@ -90,6 +90,16 @@ private void autoConnect(boolean autoConnect) {
}
}

@Override
public void setVirtual(boolean flag) {
this.virtual = flag;
Logger.info("Switching Virtual Mode " + (flag ? "On" : "Off"));
disconnect();
connect();
}



@Override
public boolean connect() {
if (!connected) {
Expand Down Expand Up @@ -157,7 +167,7 @@ public boolean connect() {
Logger.trace("There are " + this.feedbackManager.getSize() + " feedback modules");

if (isVirtual()) {
simulator = new DriveSimulator(this, this, this);
simulator = new DriveSimulator();
Logger.info("ECoS Virtual Mode Enabled!");

}
Expand Down Expand Up @@ -221,18 +231,10 @@ private void initFeedbackManager() {
for (int i = 0; i < feedbackManager.getSize(); i++) {
int moduleId = i + FeedbackManager.S88_OFFSET;
reply = connection.sendMessage(EcosMessageFactory.getFeedbackModuleInfo(moduleId));

//TODO: Start of day...
//feedbackManager.update(reply);

//TODO: we now know the begin state so refect that in the feedback modules....
// Map<String, Object> values = reply.getValueMap();
// if (values.containsKey(Ecos.STATE)) {
// String state = values.get(Ecos.STATE).toString();
// }
//
// if (values.containsKey(Ecos.PORTS)) {
// String ports = reply.getValueMap().get(Ecos.PORTS).toString();
// }
//Logger.trace("state: "+state+" ports: "+ports);
connection.sendMessage(EcosMessageFactory.subscribeFeedbackModule(moduleId));
//Logger.trace("r: "+reply.getResponse());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import jcs.commandStation.esu.ecos.EcosMessage;
import jcs.commandStation.esu.ecos.EcosMessageFactory;
import jcs.commandStation.events.SensorEvent;
import jcs.commandStation.virtual.VirtualConnection;
import jcs.commandStation.VirtualConnection;
import jcs.entities.AccessoryBean;
import jcs.entities.FeedbackModuleBean;
import jcs.entities.FunctionBean;
Expand Down Expand Up @@ -177,8 +177,8 @@ public synchronized EcosMessage sendMessage(EcosMessage message) {
}
default -> {
//Interpret the message
Logger.trace(msg);
Logger.trace(message.getId() + ": " + message.getCommand());
//Logger.trace(msg);
//Logger.trace(message.getId() + ": " + message.getCommand());
String cmd = message.getCommand();
String id = message.getId();
int objId = message.getObjectId();
Expand Down Expand Up @@ -338,9 +338,9 @@ public synchronized EcosMessage sendMessage(EcosMessage message) {
reply = replyBuilder.toString();
message.addResponse(reply);

//if (debug) {
Logger.trace("TX:" + message.getMessage() + " :->\n" + message.getResponse());
//}
if (debug) {
Logger.trace("TX:" + message.getMessage() + " :->\n" + message.getResponse());
}

return message;
}
Expand Down Expand Up @@ -424,15 +424,11 @@ FeedbackModuleBean getFeedbackModule(int moduleId) {
@Override
public void sendEvent(SensorEvent sensorEvent) {
Logger.trace("Device: " + sensorEvent.getDeviceId() + " contact: " + sensorEvent.getContactId() + " -> " + sensorEvent.isActive());

FeedbackModuleBean fbm = getFeedbackModule(100 + sensorEvent.getDeviceId());

Logger.trace(fbm.getId()+" nr: "+fbm.getModuleNumber() + " Current ports: " + fbm.portToString());

//Logger.trace(fbm.getId()+" nr: "+fbm.getModuleNumber() + " Current ports: " + fbm.portToString());
int port = sensorEvent.getContactId() - 1;

fbm.setPortValue(port, sensorEvent.isActive());
Logger.trace(100 + fbm.getModuleNumber() + " changed ports: " + fbm.portToString());
//Logger.trace(100 + fbm.getModuleNumber() + " changed ports: " + fbm.portToString());

StringBuilder sb = new StringBuilder();
int id = sensorEvent.getDeviceId() + 100;
Expand All @@ -447,17 +443,11 @@ public void sendEvent(SensorEvent sensorEvent) {

EcosMessage eventMessage = new EcosMessage(sb.toString());

Logger.trace("Sensor " + eventMessage);

//Logger.trace("Sensor " + eventMessage);
try {
this.eventQueue.put(eventMessage);
} catch (InterruptedException ex) {
Logger.error(ex);
}
}

public static String toHexString(int b) {
String h = Integer.toHexString((b));
return h;
}
}
2 changes: 1 addition & 1 deletion src/main/java/jcs/commandStation/hsis88/HSIImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import jcs.commandStation.entities.DeviceBean;
import jcs.entities.FeedbackModuleBean;
import jcs.commandStation.entities.InfoBean;
import jcs.commandStation.virtual.VirtualConnection;
import jcs.commandStation.VirtualConnection;
import jcs.entities.SensorBean;
import jcs.util.RunUtil;
import org.tinylog.Logger;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
import jcs.commandStation.marklin.cs2.LocomotiveSpeedEventParser;
import jcs.commandStation.marklin.cs2.PowerEventParser;
import jcs.commandStation.marklin.cs2.SensorMessageParser;
import jcs.commandStation.virtual.VirtualConnection;
import jcs.commandStation.VirtualConnection;
import jcs.entities.LocomotiveBean;
import jcs.entities.LocomotiveBean.DecoderType;
import static jcs.entities.LocomotiveBean.DecoderType.DCC;
Expand Down
Loading

0 comments on commit c5bec05

Please sign in to comment.