org.bidib.wizard.mvc.loco.controller.LocoController Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bidibwizard-client Show documentation
Show all versions of bidibwizard-client Show documentation
jBiDiB BiDiB Wizard Client Application POM
package org.bidib.wizard.mvc.loco.controller;
import java.awt.Window;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.bidib.jbidibc.messages.AddressData;
import org.bidib.jbidibc.messages.enums.PositionLocationEnum;
import org.bidib.jbidibc.messages.exception.NoAnswerException;
import org.bidib.jbidibc.messages.helpers.Context;
import org.bidib.jbidibc.messages.helpers.DefaultContext;
import org.bidib.jbidibc.messages.utils.ProductUtils;
import org.bidib.jbidibc.messages.utils.ThreadFactoryBuilder;
import org.bidib.wizard.api.model.CommandStationNodeInterface;
import org.bidib.wizard.api.model.NodeInterface;
import org.bidib.wizard.api.model.NodeProvider;
import org.bidib.wizard.api.model.connection.AbstractMessageEvent;
import org.bidib.wizard.api.model.connection.BidibConnection;
import org.bidib.wizard.api.model.connection.event.OccupancyCvMessageEvent;
import org.bidib.wizard.api.model.connection.event.OccupancyDynStateMessageEvent;
import org.bidib.wizard.api.model.connection.event.OccupancyPositionMessageEvent;
import org.bidib.wizard.api.model.connection.event.OccupancySpeedMessageEvent;
import org.bidib.wizard.api.service.console.ConsoleColor;
import org.bidib.wizard.api.service.console.ConsoleService;
import org.bidib.wizard.api.service.core.LocoService;
import org.bidib.wizard.api.service.node.CommandStationService;
import org.bidib.wizard.client.common.uils.SwingUtils;
import org.bidib.wizard.client.common.view.WindowUtils;
import org.bidib.wizard.common.exception.ConnectionException;
import org.bidib.wizard.common.service.SettingsService;
import org.bidib.wizard.core.model.connection.ConnectionRegistry;
import org.bidib.wizard.core.model.connection.MessageEventConsumer;
import org.bidib.wizard.core.service.ConnectionService;
import org.bidib.wizard.model.loco.LocoModel;
import org.bidib.wizard.model.loco.listener.LocoModelListener;
import org.bidib.wizard.model.locolist.LocoListModel;
import org.bidib.wizard.model.status.CommandStationStatus;
import org.bidib.wizard.model.status.DirectionStatus;
import org.bidib.wizard.model.status.RfBasisMode;
import org.bidib.wizard.model.status.SpeedSteps;
import org.bidib.wizard.mvc.common.DialogRegistry;
import org.bidib.wizard.mvc.common.view.RegisteredDialog;
import org.bidib.wizard.mvc.common.view.ViewCloseListener;
import org.bidib.wizard.mvc.console.controller.ConsoleController;
import org.bidib.wizard.mvc.loco.model.LocoConfigModel;
import org.bidib.wizard.mvc.loco.view.LocoDialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
/**
* The {@code LocoController} is a prototype bean and will be created per loco dialog instance.
*/
public class LocoController {
private static final Logger LOGGER = LoggerFactory.getLogger(LocoController.class);
private final CommandStationNodeInterface node;
private final JFrame parent;
private final LocoConfigModel locoConfigModel = new LocoConfigModel();
// private LocoModel locoModel;
private LocoDialog locoDialog;
private LocoModelListener locoModelListener;
@Autowired
private ConnectionService connectionService;
@Autowired
private CommandStationService commandStationService;
@Autowired
private LocoService locoService;
@Autowired
private SettingsService settingsService;
@Autowired
private ConsoleService consoleService;
private CompositeDisposable compDispMessages;
private final NodeProvider nodeProvider;
/**
* worker to deactivate the dcc accessories
*/
private /* final */ ScheduledExecutorService commandStationStatusWorker;
private /* final */ ScheduledExecutorService commandStationSpeedWorker;
private final DialogRegistry dialogRegistry;
public LocoController(final CommandStationNodeInterface node, JFrame parent, final NodeProvider nodeProvider,
DialogRegistry dialogRegistry) {
this.node = node;
this.parent = parent;
this.nodeProvider = nodeProvider;
this.dialogRegistry = dialogRegistry;
this.compDispMessages = new CompositeDisposable();
}
/**
* Start the loco controller.
*/
public void start(
final AddressData initialAddress, final SpeedSteps speedSteps, final LocoListModel locoListModel) {
LOGGER.info("Current connectionService: {}", connectionService);
Integer searchLocoAddress = null;
if (locoListModel != null) {
searchLocoAddress = locoListModel.getAddress();
}
else if (initialAddress != null) {
searchLocoAddress = initialAddress.getAddress();
}
// check if a loco dialog with the same address exists
if (CollectionUtils.isNotEmpty(dialogRegistry.getDialogRegistry())) {
String searchKey = LocoDialog.prepareKey(searchLocoAddress);
RegisteredDialog existingDialog =
IterableUtils.find(dialogRegistry.getDialogRegistry(), new Predicate() {
@Override
public boolean evaluate(RegisteredDialog dialog) {
return searchKey.equals(dialog.getKey());
}
});
if (existingDialog != null) {
LOGGER.info("Found existing dialog: {}", existingDialog);
try {
if (SystemUtils.IS_OS_WINDOWS) {
WindowUtils.bringWindowToFront((Window) existingDialog);
}
else {
((Window) existingDialog).toFront();
}
}
catch (Exception ex) {
LOGGER.warn("Bring the existing dialog to front failed.");
}
return;
}
else {
LOGGER.info("No existing dialog found.");
}
}
// initialize the controller
if (ProductUtils.isRFBasisNode(node.getNode().getUniqueId())
|| ProductUtils.isSpeedometer(node.getNode().getUniqueId())) {
LOGGER.info("The default speed steps for the decoders on the RF Basis Node or Speedometer is 128.");
locoConfigModel
.setSpeedSteps(
speedSteps != null ? speedSteps : settingsService.getWizardSettings().getLastSelectedSpeedSteps());
locoConfigModel.setCarControlEnabled(true);
}
else {
locoConfigModel
.setSpeedSteps(
speedSteps != null ? speedSteps : settingsService.getWizardSettings().getLastSelectedSpeedSteps());
}
final LocoModel locoModel;
if (locoListModel != null) {
LOGGER.info("Create new locoModel with locoListModel: {}", locoListModel);
// copy the values from the locoListModel to the locoModel
locoModel = new LocoModel(locoListModel);
locoConfigModel.setSpeedSteps(locoModel.getSpeedSteps());
}
else if (initialAddress != null) {
LOGGER.info("Create new locoModel from the provided initial address: {}", initialAddress);
final LocoListModel llm =
this.locoService
.getOrCreateLoco(ConnectionRegistry.CONNECTION_ID_MAIN, this.node, initialAddress.getAddress());
locoModel = new LocoModel(llm);
locoConfigModel.setSpeedSteps(locoModel.getSpeedSteps());
}
else {
LOGGER.info("Create new empty locoModel with default speedSteps.");
locoModel = new LocoModel(null);
locoModel.setSpeedSteps(locoConfigModel.getSpeedSteps());
}
prepareMessageMap(locoModel);
try {
final CompositeDisposable disp = new CompositeDisposable();
Disposable dispConnStatus = connectionService.subscribeConnectionStatusChanges(connectionInfo -> {
if (connectionInfo.getConnectionId().equals(ConnectionRegistry.CONNECTION_ID_MAIN)) {
LOGGER.info("Current state: {}", connectionInfo.getConnectionState());
switch (connectionInfo.getConnectionState().getActualPhase()) {
case CONNECTED:
LOGGER.info("The connection was opened.");
registerForMessages();
break;
case DISCONNECTED:
LOGGER.info("The connection was closed.");
compDispMessages.dispose();
if (locoDialog != null) {
locoDialog.close(LocoController.this.settingsService);
locoDialog = null;
}
disp.dispose();
break;
default:
break;
}
}
}, error -> {
LOGGER.warn("The connection status change caused an error.", error);
});
disp.add(dispConnStatus);
}
catch (Exception ex) {
LOGGER.warn("Register controller as node listener failed.", ex);
}
try {
LOGGER.info("Check if the connection is connected already.");
boolean isConnected = connectionService.isConnected(ConnectionRegistry.CONNECTION_ID_MAIN);
if (isConnected) {
registerForMessages();
}
}
catch (Exception ex) {
LOGGER.warn("Register for messages failed.", ex);
}
LOGGER.info("Create new instance of LocoDialog.");
final LocoControlListener locoControlListener = new LocoControlListener() {
@Override
public void setSpeed(Integer speed, DirectionStatus direction) {
// LOGGER.info("Set speed: {}, direction: {}", speed, direction);
LocoController.this.setSpeed(locoModel, speed, direction);
}
@Override
public void setFunction(int index, boolean value) {
LOGGER.info("Set function is called, index: {}, value: {}", index, value);
// Prepare the function group index
int functionGroupIndex = 0;
if (index < 5) {
functionGroupIndex = 0;
}
else if (index < 9) {
functionGroupIndex = 1;
}
else if (index < 13) {
functionGroupIndex = 2;
}
else if (index < 21) {
functionGroupIndex = 3;
}
else if (index < 29) {
functionGroupIndex = 4;
}
else {
LOGGER.warn("Function > 28 uses binary state operation.");
setBinaryState(index, value);
return;
}
BitSet activeFunctions = new BitSet(functionGroupIndex + 1);
LOGGER.info("functions have changed, functionGroupIndex: {}", functionGroupIndex);
activeFunctions.set(functionGroupIndex, true);
if (locoModel.getAddress() == null) {
LOGGER.warn("No address available.");
return;
}
final Integer locoAddress = locoModel.getAddress();
final SpeedSteps speedSteps = locoModel.getSpeedSteps();
final DirectionStatus direction = locoModel.getDirection();
final BitSet functions = new BitSet();
functions.or(locoModel.getFunctions());
functions.set(index, value);
commandStationSpeedWorker.submit(() -> {
// create the context
final Context context = new DefaultContext();
registerActiveRfBasis(locoModel, context);
// count the CS_DRIVE messages that are sent
SwingUtils.executeInEDT(() -> locoModel.incCounterCsDrive());
commandStationService
.setSpeed(ConnectionRegistry.CONNECTION_ID_MAIN, node, locoAddress, speedSteps, null, direction,
activeFunctions, functions, context);
});
}
@Override
public void setBinaryState(int stateNumber, boolean value) {
LOGGER
.info("Send the binary state, dccAddress: {}, stateNumber: {}, value: {}", locoModel.getAddress(),
stateNumber, value);
if (locoModel.getAddress() == null) {
LOGGER.warn("No address available.");
return;
}
// we must send the binary state for the change of active RF base to all bases but the others
// only to the selected base
final Context context = new DefaultContext();
boolean baseChanged = false;
// special handling for cars
if (locoConfigModel.isCarControlEnabled()) {
if (stateNumber < 512 || stateNumber > 517) {
// normal binary function operations --> send to active base
registerActiveRfBasis(locoModel, context);
}
else if (locoModel.getActiveBase() != null) {
// we must send the current speed and functions to the new basis before we switch to the new
// basis
int functionGroupIndex = 4;
BitSet activeFunctions = new BitSet(functionGroupIndex + 1);
LOGGER.debug("functions have changed, functionGroupIndex: {}", functionGroupIndex);
activeFunctions.set(0, functionGroupIndex, true);
LOGGER
.info(
"The active RF basis is switched. Send the current speed data to the new RF basis before switch the decoder to the new basis: {}",
locoModel.getActiveBase());
Integer speed = locoModel.getSpeed();
if (speed != null) {
// no speed conversion for stop and emergency stop
if (speed > 1) {
// for 14/28 speedSteps we must calc the value based on 128 speed steps
switch (locoModel.getSpeedSteps()) {
case DCC28:
speed = (speed * 127) / 28;
break;
case DCC14:
speed = (speed * 127) / 14;
break;
default:
break;
}
}
}
// let execute this in a worker
final Integer speedValue = speed;
final Integer locoAddress = locoModel.getAddress();
final SpeedSteps speedSteps = locoModel.getSpeedSteps();
final DirectionStatus direction = locoModel.getDirection();
final BitSet functions = locoModel.getFunctions();
commandStationSpeedWorker.submit(() -> {
registerActiveRfBasis(locoModel, context);
// count the CS_DRIVE messages that are sent
SwingUtils.executeInEDT(() -> locoModel.incCounterCsDrive());
commandStationService
.setSpeed(ConnectionRegistry.CONNECTION_ID_MAIN, node, locoAddress, speedSteps,
speedValue, direction, activeFunctions, functions, context);
});
baseChanged = true;
}
}
if (baseChanged) {
LOGGER.info("Send the binary state to all bases because we change the active RF basis.");
final Integer locoAddress = locoModel.getAddress();
commandStationSpeedWorker.submit(() -> {
final Context localContext = new DefaultContext();
// count the CS_BIN_STATE messages that are sent
locoModel.incCounterCsBinState();
// set the binary state
commandStationService
.setBinaryState(ConnectionRegistry.CONNECTION_ID_MAIN, node, locoAddress, stateNumber,
value, localContext);
});
}
else {
final Integer locoAddress = locoModel.getAddress();
commandStationSpeedWorker.submit(() -> {
// count the CS_BIN_STATE messages that are sent
locoModel.incCounterCsBinState();
// set the binary state
commandStationService
.setBinaryState(ConnectionRegistry.CONNECTION_ID_MAIN, node, locoAddress, stateNumber,
value, context);
});
}
if (baseChanged && locoModel.getPrevActiveBase() != null
&& locoModel.getPrevActiveBase() != RfBasisMode.SINGLE) {
final Integer locoAddress = locoModel.getAddress();
final SpeedSteps speedSteps = locoModel.getSpeedSteps();
final DirectionStatus direction = locoModel.getDirection();
commandStationSpeedWorker.submit(() -> {
LOGGER.info("Clear decoder from prev active base: {}", locoModel.getPrevActiveBase());
final Context localContext = new DefaultContext();
registerPrevActiveRfBasis(locoModel, localContext);
// count the CS_DRIVE messages that are sent
SwingUtils.executeInEDT(() -> locoModel.incCounterCsDrive());
commandStationService
.setSpeed(ConnectionRegistry.CONNECTION_ID_MAIN, node, locoAddress, speedSteps, null,
direction, null, null, localContext);
locoModel.resetPrevActiveBase();
});
}
}
@Override
public void setSpeedSteps(SpeedSteps speedSteps) {
// LOGGER.info("Set the speedSteps: {}", speedSteps);
LocoController.this.setSpeedSteps(locoModel, speedSteps);
};
@Override
public void clearLoco() {
if (locoModel.getAddress() == null) {
LOGGER.warn("No address available.");
return;
}
final Integer locoAddress = locoModel.getAddress();
final SpeedSteps speedSteps = locoModel.getSpeedSteps();
commandStationSpeedWorker.submit(() -> {
// create the context
final Context context = new DefaultContext();
registerActiveRfBasis(locoModel, context);
// count the CS_DRIVE messages that are sent
SwingUtils.executeInEDT(() -> locoModel.incCounterCsDrive());
commandStationService
.clearLoco(ConnectionRegistry.CONNECTION_ID_MAIN, node, locoAddress, speedSteps, context);
});
};
};
locoDialog =
new LocoDialog(parent, locoModel, locoConfigModel, settingsService, locoControlListener,
lm -> registerLocoModelListener(lm), newLocoAddress -> changeLocoAddress(locoModel, newLocoAddress));
locoDialog.addViewCloseListener(new ViewCloseListener() {
@Override
public void close() {
LOGGER.info("The locoView is closed.");
// unregisterMessageListener(messageListener, communication);
RegisteredDialog registeredDialog = null;
// release locoView
if (locoDialog != null) {
registeredDialog = locoDialog;
locoDialog = null;
}
if (locoModelListener != null) {
LOGGER.info("Remove locoModelListener from model.");
locoModel.removeLocoModelListener(locoModelListener);
locoModelListener = null;
}
locoModel.cleanup();
unregisterView(registeredDialog);
}
});
// // Register the loco dialog
LOGGER.info("Register the LocoDialog in the dialog registry: {}", locoDialog);
dialogRegistry.getDialogRegistry().add(locoDialog);
// query the current state of the command station
try {
if (node.getCommandStationStatus() == null) {
LOGGER.info("Subscribe to command station status changes.");
final CompositeDisposable disp = new CompositeDisposable();
Disposable dispCsState = node.subscribeSubjectCommandStationState(csState -> {
LOGGER.info("Current command station state: {}", csState);
// this will start the command station if it was stopped
if (CommandStationStatus.isOffState(csState)) {
LOGGER.info("Set the command station to status GO.");
if (commandStationStatusWorker == null) {
commandStationStatusWorker =
Executors
.newScheduledThreadPool(1, new ThreadFactoryBuilder()
.setNameFormat("commandStationStatusWorkers-thread-%d").build());
}
// Must not set the command station status from receiveQueueWorker !
commandStationStatusWorker.submit(() -> {
commandStationService
.setCommandStationState(ConnectionRegistry.CONNECTION_ID_MAIN, node,
CommandStationStatus.GO);
});
}
disp.dispose();
}, error -> {
LOGGER.warn("Get the current command station state failed.");
disp.dispose();
}, () -> {
LOGGER.warn("Get the current command station state subscription has completed, node: {}", node);
});
disp.add(dispCsState);
commandStationService.queryCommandStationState(ConnectionRegistry.CONNECTION_ID_MAIN, node);
}
}
catch (Exception ex) {
LOGGER.warn("Get command station state failed.", ex);
}
}
public void registerLocoModelListener(final LocoModel locoModel) {
LOGGER.info("Register the locoModel listener for locoModel: {}", locoModel);
// TODO the locoModelListener must be assigned to the locoModel
if (commandStationSpeedWorker == null) {
commandStationSpeedWorker =
Executors
.newScheduledThreadPool(1,
new ThreadFactoryBuilder().setNameFormat("commandStationSpeedWorkers-thread-%d").build());
}
}
private void setSpeed(final LocoModel locoModel, Integer speed, DirectionStatus directionStatus) {
LOGGER.info("Set loco speed: {}, direction: {}", speed, directionStatus);
if (locoModel.getAddress() == null) {
LOGGER.warn("No address available.");
return;
}
// set the speed
if (speed != null) {
final Integer locoAddress = locoModel.getAddress();
final SpeedSteps speedSteps = locoModel.getSpeedSteps();
if (directionStatus != null) {
locoModel.setDirection(directionStatus);
}
final DirectionStatus direction = locoModel.getDirection();
// no speed conversion for stop and emergency stop
if (speed > 1) {
// for 14/28 speedSteps we must calc the value based on 128 speed steps
switch (speedSteps) {
case DCC28:
speed = (speed * 127) / 28;
break;
case DCC14:
speed = (speed * 127) / 14;
break;
default:
break;
}
}
LOGGER
.info(
"The speed has changed in the locoModel. Send the new speed value: {}, direction: {}, address: {}, speedSteps: {}",
speed, direction, locoAddress, speedSteps);
// let execute this in a worker
final Integer speedValue = speed;
commandStationSpeedWorker.submit(() -> {
try {
// create the context
final Context context = new DefaultContext();
registerActiveRfBasis(locoModel, context);
// count the CS_DRIVE messages that are sent
SwingUtils.executeInEDT(() -> locoModel.incCounterCsDrive());
commandStationService
.setSpeed(ConnectionRegistry.CONNECTION_ID_MAIN, node, locoAddress, speedSteps, speedValue,
direction, null, null, context);
}
catch (NoAnswerException ex) {
LOGGER.warn("Set speed failed.", ex);
SwingUtilities.invokeLater(() -> {
ConsoleController.ensureConsoleVisible();
if (StringUtils.isNotBlank(ex.getMessage())) {
consoleService.addConsoleLine(ConsoleColor.red, ex.getMessage());
}
else {
consoleService.addConsoleLine(ConsoleColor.red, "Set speed failed.");
}
});
}
catch (Exception ex) {
LOGGER.warn("Set speed failed.", ex);
}
});
}
else {
LOGGER.debug("No speed value in model.");
}
}
private void setSpeedSteps(final LocoModel locoModel, final SpeedSteps speedSteps) {
LOGGER.info("Set the speedSteps: {}, locoModel: {}", speedSteps, locoModel);
locoModel.setSpeedSteps(speedSteps);
}
private void changeLocoAddress(final LocoModel locoModel, final Integer locoAddress) {
LOGGER.info("Change the locoAddress: {}", locoAddress);
if (locoAddress != null) {
LocoListModel locoListModel =
locoService.getOrCreateLoco(ConnectionRegistry.CONNECTION_ID_MAIN, node, locoAddress);
locoModel.setLocoListModel(locoListModel);
}
else {
// reset the loco
locoModel.setLocoListModel(null);
}
// must reset the reported cell number
locoModel.setReportedCellNumber(null);
}
private void registerForMessages() {
LOGGER.info("Register for messages from the connection.");
// register for messages from the connection
try {
BidibConnection connection = connectionService.find(ConnectionRegistry.CONNECTION_ID_MAIN);
Disposable dispMessages = connection.getSubjectMessages().subscribe(msg -> {
handleBidibMessageEvent(msg);
});
compDispMessages.add(dispMessages);
}
catch (ConnectionException ex) {
LOGGER.warn("No connection found, register on messages is skipped.", ex);
}
}
private final Map, MessageEventConsumer> messageActionMap =
new HashMap<>();
private void prepareMessageMap(final LocoModel locoModel) {
LOGGER.info("Prepare the message map.");
// occupancy
messageActionMap.put(OccupancySpeedMessageEvent.class, (evt, node) -> {
OccupancySpeedMessageEvent event = (OccupancySpeedMessageEvent) evt;
// TODO this should be moved to DefaultLocoService
// final AddressData addressData = event.getAddressData();
// if (locoModel.getAddress() != null && addressData.getAddress() == locoModel.getAddress()) {
// int speed = event.getSpeed();
//
// LOGGER.info("Update the reported speed: {}", speed);
// SwingUtils.executeInEDT(() -> locoModel.setReportedSpeed(speed));
// }
});
messageActionMap.put(OccupancyDynStateMessageEvent.class, (evt, node) -> {
OccupancyDynStateMessageEvent event = (OccupancyDynStateMessageEvent) evt;
final AddressData decoderAddress = event.getDecoderAddress();
int dynNumber = event.getDynNumber();
final int dynValue = event.getDynValue();
LOGGER
.info("dynState, decoderAddress: {}, dynNumber: {}, dynValue: {}", decoderAddress, dynNumber, dynValue);
// TODO this should be moved to DefaultLocoService
// TODO must check the address and the address of the selected node
if (locoModel.getAddress() != null && decoderAddress.getAddress() == locoModel.getAddress()
&& dynNumber == 3) {
// LOGGER.info("The dynState is forwarded to model");
SwingUtils.executeInEDT(() -> locoModel.setDynStateEnergy(dynValue));
}
else {
LOGGER.debug("The dynState ist not forwarded to model");
}
});
messageActionMap.put(OccupancyCvMessageEvent.class, (evt, node) -> {
OccupancyCvMessageEvent event = (OccupancyCvMessageEvent) evt;
LOGGER.info("Received new occupancy CV event: {}", event);
LOGGER.warn("The occupancy CV event is not processed and discarded: {}", event);
});
// add message events for occupancy position
messageActionMap.put(OccupancyPositionMessageEvent.class, (evt, node) -> {
OccupancyPositionMessageEvent event = (OccupancyPositionMessageEvent) evt;
LOGGER.debug("Process the event: {}", event);
// TODO this should be moved to DefaultLocoService
if (event.getLocationType() == PositionLocationEnum.CELL_IDENTIFIER
&& (locoModel.getAddress() != null && event.getDecoderAddress() == locoModel.getAddress())) {
SwingUtilities.invokeLater(() -> {
LOGGER.info("Update the cellIdentifier: {}", event);
locoModel.setReportedCellNumber(event.getLocationAddress());
});
}
else {
LOGGER.debug("Do not show position feedback with type: {}", event.getLocationType());
}
});
}
private void handleBidibMessageEvent(AbstractMessageEvent event) {
LOGGER.debug("Handle the message event: {}", event);
// let the action update the cached value in the node
try {
MessageEventConsumer action = messageActionMap.get(event.getClass());
if (action != null) {
action.accept(event, node.getNode());
}
else {
LOGGER.debug("No message event action configured for event: {}", event);
}
}
catch (Exception ex) {
LOGGER.warn("Execute the message event action failed, node: {}, event: {}", node, event, ex);
}
}
private void unregisterView(RegisteredDialog view) {
if (view != null) {
try {
if (CollectionUtils.isNotEmpty(dialogRegistry.getDialogRegistry())) {
String searchKey = view.getKey();
RegisteredDialog existingDialog =
IterableUtils.find(dialogRegistry.getDialogRegistry(), new Predicate() {
@Override
public boolean evaluate(RegisteredDialog dialog) {
return searchKey.equals(dialog.getKey());
}
});
if (existingDialog != null) {
LOGGER.info("Found existing dialog to unregister: {}", existingDialog);
dialogRegistry.getDialogRegistry().remove(existingDialog);
LOGGER.info("Registry after remove: {}", dialogRegistry);
}
}
}
catch (Exception ex) {
LOGGER.warn("Unregister view failed: {}", view, ex);
}
}
else {
LOGGER.info("No view available to unregister.");
}
}
/**
* Register the active base in the context under the key {@code activeRfBasis}.
*
* @param context
* the context
*/
private void registerActiveRfBasis(final LocoModel locoModel, final Context context) {
if (locoConfigModel.isCarControlEnabled() && locoModel.getActiveBase() != null
&& locoModel.getActiveBase() != RfBasisMode.SINGLE) {
RfBasisMode activeRfBase = locoModel.getActiveBase();
registerRfBasisInContext(context, activeRfBase);
}
}
/**
* Register the previous active base in the context under the key {@code activeRfBasis}.
*
* @param context
* the context
*/
private void registerPrevActiveRfBasis(final LocoModel locoModel, final Context context) {
if (locoConfigModel.isCarControlEnabled() && locoModel.getPrevActiveBase() != null
&& locoModel.getPrevActiveBase() != RfBasisMode.SINGLE) {
RfBasisMode prevActiveRfBase = locoModel.getPrevActiveBase();
registerRfBasisInContext(context, prevActiveRfBase);
}
}
private void registerRfBasisInContext(final Context context, final RfBasisMode rfBase) {
context.unregister("activeRfBasis");
if (rfBase.getBaseNumber() != null) {
int activeBaseNumber = rfBase.getBaseNumber();
final NodeInterface rfBasisNode = nodeProvider.getNodes().stream().filter(bidibNode -> {
return (ProductUtils.isRFBasisNode(bidibNode.getUniqueId())
&& bidibNode.getBaseNumber() == activeBaseNumber);
}).findFirst().orElse(null);
if (rfBasisNode != null) {
LOGGER.info("Found the active rfBasisNode: {}", rfBasisNode);
context.register("activeRfBasis", rfBasisNode.getNode());
}
else {
LOGGER.warn("No active rfBasisNode found for activeBaseNumber: {}", activeBaseNumber);
}
}
else {
LOGGER.info("No base number for active rf base available.");
}
}
}