org.bidib.wizard.gateway.service.BidibDistributedGatewayService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bidibwizard-gateway Show documentation
Show all versions of bidibwizard-gateway Show documentation
jBiDiB BiDiB Wizard Gateway POM
package org.bidib.wizard.gateway.service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.apache.commons.collections4.CollectionUtils;
import org.bidib.api.json.types.NodeAddress;
import org.bidib.api.json.types.SerialPortInfo;
import org.bidib.api.json.types.UsbPortInfo.UsbPortAction;
import org.bidib.jbidibc.messages.AddressData;
import org.bidib.jbidibc.messages.BidibLibrary;
import org.bidib.jbidibc.messages.BidibMessageEvaluator;
import org.bidib.jbidibc.messages.HostAdapter;
import org.bidib.jbidibc.messages.Node;
import org.bidib.jbidibc.messages.SequenceNumberProvider;
import org.bidib.jbidibc.messages.enums.CommandStationState;
import org.bidib.jbidibc.messages.enums.TargetModeEnum;
import org.bidib.jbidibc.messages.exception.ProtocolException;
import org.bidib.jbidibc.messages.helpers.Context;
import org.bidib.jbidibc.messages.helpers.DefaultContext;
import org.bidib.jbidibc.messages.message.BidibMessage;
import org.bidib.jbidibc.messages.message.BidibMessageInterface;
import org.bidib.jbidibc.messages.message.BidibRequestFactory;
import org.bidib.jbidibc.messages.message.BidibResponseFactory;
import org.bidib.jbidibc.messages.message.CommandStationDriveMessage;
import org.bidib.jbidibc.messages.message.CommandStationSetStateMessage;
import org.bidib.jbidibc.messages.message.GuestRequestSendMessage;
import org.bidib.jbidibc.messages.message.GuestResponseNotifyMessage;
import org.bidib.jbidibc.messages.message.LocalBidibDownMessage;
import org.bidib.jbidibc.messages.message.LocalBidibUpResponse;
import org.bidib.jbidibc.messages.message.LocalLogoffMessage;
import org.bidib.jbidibc.messages.message.LocalLogonMessage;
import org.bidib.jbidibc.messages.message.StringResponse;
import org.bidib.jbidibc.messages.message.SysGetMagicMessage;
import org.bidib.jbidibc.messages.message.SysPVersionResponse;
import org.bidib.jbidibc.messages.message.SysUniqueIdResponse;
import org.bidib.jbidibc.messages.message.netbidib.NetBidibLinkData;
import org.bidib.jbidibc.messages.message.netbidib.NetBidibLinkData.LogonStatus;
import org.bidib.jbidibc.messages.utils.ByteUtils;
import org.bidib.jbidibc.messages.utils.ConversionUtils;
import org.bidib.jbidibc.netbidib.server.NetBidibServer;
import org.bidib.wizard.api.model.NodeInterface;
import org.bidib.wizard.api.model.connection.AbstractMessageEvent;
import org.bidib.wizard.api.service.node.CommandStationService;
import org.bidib.wizard.api.utils.JsonNodeUtils;
import org.bidib.wizard.common.exception.ConnectionException;
import org.bidib.wizard.common.model.settings.ConnectionConfiguration;
import org.bidib.wizard.common.model.settings.GlobalSettingsInterface;
import org.bidib.wizard.common.service.SettingsService;
import org.bidib.wizard.core.model.connection.ConnectionRegistry;
import org.bidib.wizard.core.model.connection.MessageEventHandler;
import org.bidib.wizard.core.service.ConnectionService;
import org.bidib.wizard.core.service.SystemInfoService;
import org.bidib.wizard.gateway.config.GatewayServiceSettings;
import org.bidib.wizard.gateway.model.GatewayRequest;
import org.bidib.wizard.gateway.model.LocoData;
import org.bidib.wizard.gateway.model.LocoList;
import org.bidib.wizard.gateway.model.connection.BidibProxyConnectionFactory;
import org.bidib.wizard.gateway.model.connection.ProxyBidibConnection;
import org.bidib.wizard.model.status.CommandStationStatus;
import org.bidib.wizard.model.status.DirectionStatus;
import org.bidib.wizard.model.status.SpeedSteps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.event.EventListener;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jgoodies.common.base.Objects;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
/**
* The {@code BidibDistributedGatewayService} is used for direct handling of distributed messages with or without
* netbidib depending on the configured {@code ProxyConnectionAdapter}.
* Use the spring profile {@code bidib-distributed} to start with {@code ProxyDistributedConnectionAdapter} enabled.
*/
public class BidibDistributedGatewayService
implements MessageEventHandler, BidibMessageEvaluator, ConnectionSupport {
private static final Logger LOGGER = LoggerFactory.getLogger(BidibDistributedGatewayService.class);
@Autowired
private ConnectionService connectionService;
@Autowired
private CommandStationService commandStationService;
@Autowired
@Lazy
private NetBidibServer netBidibServer;
@Autowired
private SystemInfoService systemInfoService;
@Autowired
private SettingsService settingsService;
@Autowired
private GatewayServiceSettings gatewayServiceConfiguration;
@Autowired
private BidibProxyConnectionFactory bidibProxyConnectionFactory;
@Autowired
@Lazy
private HostAdapter messageHostAdapter;
private final ProxyConnectionAdapter proxyConnectionAdapter;
@Value("${wizard-app-type:standalone}")
private String wizardAppType;
private ProxyBidibConnection bidibProxyConnection;
private final BidibRequestFactory requestFactory;
private final BidibResponseFactory responseFactory;
private final CompositeDisposable dispBidibMessages = new CompositeDisposable();
private NetBidibLinkData pairedPartner;
/**
* The {@code registeredNodeMap} contains the registered guest nodes.
*/
private Map registeredNodeMap = new HashMap<>();
public BidibDistributedGatewayService(final BidibRequestFactory requestFactory,
final BidibResponseFactory responseFactory, final NetBidibLinkData pairedPartner,
ProxyConnectionAdapter proxyConnectionAdapter) {
this.requestFactory = requestFactory;
this.responseFactory = responseFactory;
this.pairedPartner = pairedPartner;
this.proxyConnectionAdapter = proxyConnectionAdapter;
}
@PostConstruct
public void initialize() {
LOGGER.info("Initialize the request and response factories.");
this.requestFactory.initialize();
this.responseFactory.initialize();
}
@PreDestroy
public void shutdown() {
LOGGER.info("Dispose the subscription on bidib messages.");
dispBidibMessages.dispose();
}
/**
* Get the next free node address.
*
* @param uniqueId
* the uniqueId
* @return the node address
*/
private int getNextFreeNodeAddress(Long uniqueId) {
LOGGER.warn("Get the next free node address for uniqueid: {}", ByteUtils.formatHexUniqueId(uniqueId));
// check the map
int lastAddress = 31;
synchronized (registeredNodeMap) {
if (registeredNodeMap.containsKey(uniqueId)) {
// get the registered node address
lastAddress = registeredNodeMap.get(uniqueId);
LOGGER
.warn("The node map already contains an entry for uniqueId: {}, nodeAddress: {}",
ByteUtils.formatHexUniqueId(uniqueId), lastAddress);
}
else {
// search a free address value
try {
int maxValue =
registeredNodeMap
.values().stream().mapToInt(v -> v).max().orElseThrow(NoSuchElementException::new);
lastAddress = maxValue + 1;
}
catch (NoSuchElementException ex) {
LOGGER.info("No elements in map. Use address 32.");
lastAddress = 32;
}
LOGGER
.info("Register the node with uniqueId: {}, assigned nodeAddress: {}",
ByteUtils.formatHexUniqueId(uniqueId), lastAddress);
// register the node
registeredNodeMap.put(uniqueId, lastAddress);
}
}
return lastAddress;
}
@Override
public void connectionClosed(Long uniqueId) {
handleLocalLogoff(uniqueId);
}
private void handleLocalLogon(final LocalLogonMessage localLogonMessage, final SequenceNumberProvider proxyNode) {
// generate a local node address
BidibMessage localLogonAckResponse;
try {
Long uniqueId = Long.valueOf(ByteUtils.convertUniqueIdToLong(localLogonMessage.getUniqueId()));
Integer localNodeAddr = null;
// check if registered already
synchronized (registeredNodeMap) {
Integer registeredAddress = registeredNodeMap.get(uniqueId);
if (registeredAddress != null) {
LOGGER
.warn(
"Handle the localLogon message. The uniqueId is already registered in registeredNodeMap, uniqueId: {}, registeredAddress: {}",
ByteUtils.formatHexUniqueId(uniqueId), registeredAddress);
localNodeAddr = registeredAddress;
return;
}
}
// if we accept the LOGON we must set the pairedPartner to LOGGED_ON
LOGGER
.info("Handle the localLogon. Set the uniqueId in the pairedPartner: {}",
ByteUtils.formatHexUniqueId(uniqueId));
if (localNodeAddr == null) {
localNodeAddr = getNextFreeNodeAddress(uniqueId);
}
this.pairedPartner.setUniqueId(uniqueId);
this.pairedPartner.setLogonStatus(LogonStatus.LOGGED_ON);
localLogonAckResponse = responseFactory.createLocalLogonAckResponse(0 /*nodeAddr*/, uniqueId);
LOGGER.info("Prepared localLogonAckResponse: {}", localLogonAckResponse);
messageHostAdapter.forwardMessageToGuest(proxyNode, localLogonAckResponse);
}
catch (ProtocolException ex) {
LOGGER.warn("Publish the localLogonAckResponse failed.", ex);
}
}
private void handleLocalLogoff(Long uniqueId) {
if (uniqueId == null) {
LOGGER.info("No uniqueId available to logoff.");
return;
}
synchronized (registeredNodeMap) {
Integer registeredAddress = registeredNodeMap.remove(uniqueId);
LOGGER
.info("Removed registered address from registeredNodeMap, uniqueId: {}, registeredAddress: {}",
ByteUtils.formatHexUniqueId(uniqueId), registeredAddress);
}
}
/**
* Handle the bidib message event that was received from the message subject of the connection.
*
* @param event
* the message event
*/
@Override
public void handleMessageEvent(final AbstractMessageEvent event) {
LOGGER.info("Handle the message event: {}", event);
if (bidibProxyConnection != null) {
proxyConnectionAdapter.handleMessageEventFromBus(bidibProxyConnection, messageHostAdapter, event);
}
else {
LOGGER.warn("The bidibProxyConnection is not available to handle the message event: {}", event);
}
}
@EventListener
public void handleContextStart(ApplicationStartedEvent ase) {
LOGGER.info("The application context is started. Open the socket receiver to accept connections from guests.");
netBidibServer.startServer();
LOGGER.info("Subscribe for USB port changes in system.");
systemInfoService.subscribeUsbPortEvents(usbInfo -> {
LOGGER.info("Changed USB port in system detected: {}", usbInfo);
try {
String portIdentifier = usbInfo.getSerialPort().getPortName();
if (usbInfo.getAction() == UsbPortAction.INSERTED) {
signalPortAvailable(portIdentifier);
}
else {
signalPortUnavailable(portIdentifier);
}
}
catch (Exception ex) {
LOGGER.warn("Auto-connect to backend failed.", ex);
}
}, ex -> {
LOGGER.warn("The USB port info subject has published an error.", ex);
});
List serialPorts = systemInfoService.getRegisteredSerialPorts();
if (CollectionUtils.isNotEmpty(serialPorts)) {
LOGGER.info("Found registered serial ports in the system: {}", serialPorts);
try {
String portIdentifier = serialPorts.get(0).getPortName();
signalPortAvailable(portIdentifier);
}
catch (Exception ex) {
LOGGER.warn("Auto-connect to backend failed.", ex);
}
}
else {
LOGGER.info("No configured serial port available in the system.");
// check if 'main' connection is configured as simulation and open it if isAutoConnectBackend is
// enabled
if (gatewayServiceConfiguration.isAutoConnectBackend()) {
LOGGER.info("Check if the 'main' connection is configured as simulation.");
Optional globalSettings =
Optional.ofNullable(settingsService.getGlobalSettings());
List configs =
globalSettings
.map(settings -> settings.getConnectionConfigurations()).orElse(Collections.emptyList());
Optional simConfig =
configs
.stream().filter(config -> ConnectionRegistry.CONNECTION_ID_MAIN.equals(config.getName()))
.filter(config -> "SerialSimulation".contentEquals(config.getConnectionProvider())).findFirst();
simConfig.ifPresent(config -> {
try {
String connectionId = config.getId();
LOGGER.info("Try to connect simulation with connectionId: {}", connectionId);
final Context context = new DefaultContext();
context.register(Context.CONNECTION_ID, connectionId);
connectBackend(context);
}
catch (ConnectionException ex) {
LOGGER.warn("Auto-connect to simulation failed.", ex);
}
});
}
}
}
/**
* Signal that the port is available.
*
* @param portIdentifier
* the port identifier
*/
private void signalPortAvailable(String portIdentifier) {
if (gatewayServiceConfiguration.isAutoConnectBackend() && !"standalone".equals(wizardAppType)) {
LOGGER.info("Auto-connect backend is enabled. Connect to backend, portIdentifier: {}", portIdentifier);
try {
String connectionId = connectionService.findConnectionIdByPort(portIdentifier);
LOGGER.info("Try to connect to backend with connectionId: {}", connectionId);
final Context context = new DefaultContext();
context.register(Context.CONNECTION_ID, connectionId);
connectBackend(context);
}
catch (ConnectionException ex) {
LOGGER.warn("Auto-connect to backend failed.", ex);
}
}
else {
LOGGER
.warn("Auto-connect to backend is disabled or wizard runs in standalone mode, portIdentifier: {}",
portIdentifier);
}
}
/**
* Signal that the port is unavailable.
*
* @param portIdentifier
* the port identifier
*/
private void signalPortUnavailable(String portIdentifier) {
LOGGER.info("The port is signalled as unavailable: {}", portIdentifier);
if (bidibProxyConnection != null) {
try {
String connectionId = connectionService.findConnectionIdByPort(portIdentifier);
if (Objects.equals(connectionId, bidibProxyConnection.getConnectionId())) {
LOGGER.info("Disconnect to backend with connectionId: {}", connectionId);
bidibProxyConnection.disconnect();
}
}
catch (ConnectionException ex) {
LOGGER
.info("Find connection to disconnect the backend is skipped because not connection available.",
ex.getMessage());
}
}
}
@Override
public void disconnectBackend(final Context context) {
LOGGER.info("Disconnect from backend: {}", context);
if (bidibProxyConnection != null) {
try {
bidibProxyConnection.disconnect();
LOGGER.info("Disconnect connection passed.");
}
catch (ConnectionException ex) {
LOGGER.warn("Disconnect connection failed.", ex);
}
// free the instance
bidibProxyConnection = null;
}
}
@Override
public void connectBackend(final Context context) {
String connectionId = context.get(Context.CONNECTION_ID, String.class, ConnectionRegistry.CONNECTION_ID_MAIN);
LOGGER.info("Connect the backend. Get the connection with id: {}", connectionId);
if (bidibProxyConnection == null) {
// create the proxy connection
bidibProxyConnection = bidibProxyConnectionFactory.createBidibConnection(connectionId, this);
LOGGER.info("Created new bidibConnection: {}", bidibProxyConnection);
}
if (!bidibProxyConnection.isConnected()) {
LOGGER.info("The proxied backend connection is not connected. Connect to the backend: {}", context);
bidibProxyConnection.connect(context);
LOGGER.info("Connect to the backend has finished, context: {}", context);
}
else {
LOGGER.warn("Connection to backend is established already: {}", bidibProxyConnection);
}
}
/**
* Process the bidibMessage from the guest to the backend. For node registration messages the handling is done in
* the gateway service.
*
* @param bidibMessage
* the bidib message
*/
@Override
public void processBidibMessageFromGuest(
final SequenceNumberProvider proxyNode, final BidibMessageInterface bidibMessage) {
LOGGER.info("Process the bidibMessage: {}", bidibMessage);
switch (ByteUtils.getInt(bidibMessage.getType())) {
case BidibLibrary.MSG_GUEST_REQ_SEND:
// process the GUEST REQ SEND messages
GuestRequestSendMessage guestRequestSendMessage = (GuestRequestSendMessage) bidibMessage;
processGuestReqSend(proxyNode, guestRequestSendMessage);
break;
case BidibLibrary.MSG_LOCAL_LOGON:
final LocalLogonMessage localLogonMessage = (LocalLogonMessage) bidibMessage;
handleLocalLogon(localLogonMessage, proxyNode);
break;
case BidibLibrary.MSG_LOCAL_LOGOFF:
LocalLogoffMessage localLogoffMessage = (LocalLogoffMessage) bidibMessage;
Long uniqueId = localLogoffMessage.getSenderUniqueId();
handleLocalLogoff(uniqueId);
break;
case BidibLibrary.MSG_LOCAL_BIDIB_DOWN:
LocalBidibDownMessage localBidibDownMessage = (LocalBidibDownMessage) bidibMessage;
processLocalBidibDownMessage(proxyNode, localBidibDownMessage);
break;
default:
// TODO here we are node '0' and we are the gateway
try {
if (bidibProxyConnection != null) {
// process the messages from the guest
proxyConnectionAdapter
.processBidibMessageFromGuest(bidibProxyConnection, messageHostAdapter, bidibMessage);
}
else {
LOGGER
.warn(
"The bidibProxyConnection is not available to process the messages from the guest: {}",
bidibMessage);
}
}
catch (ProtocolException ex) {
LOGGER.info("Process command in proxy connection adapter failed.", ex);
}
break;
}
}
/**
* Process the {@code LocalBidibDownMessage} that was received from the connected partner. These messages are used
* to get additional information from the interface and provided proprietary data.
*
* @param proxyNode
* the proxy node
* @param localBidibDownMessage
* the message
*/
private void processLocalBidibDownMessage(
final SequenceNumberProvider proxyNode, LocalBidibDownMessage localBidibDownMessage) {
LOGGER.info("Process the localBidibDownMessage: {}", localBidibDownMessage);
byte[] wrappedMessage = localBidibDownMessage.getWrappedMessage();
// check if this is a wrapped bidib message
LocalBidibUpResponse concreteBidibMessage = null;
try {
switch (wrappedMessage[0]) {
case BidibLibrary.MSG_STRING_GET:
LOGGER.info("Get the STRING will return a fake message.");
byte namespace = wrappedMessage[1];
byte index = wrappedMessage[2];
StringResponse resp = null;
if (index == 0) {
resp = new StringResponse(Node.ROOTNODE_ADDR, 0, namespace, index, "IF2");
}
else {
resp = new StringResponse(Node.ROOTNODE_ADDR, 0, namespace, index, "My cool IF2");
}
concreteBidibMessage =
new LocalBidibUpResponse(localBidibDownMessage.getAddr(), 0/* sendMsgNum */,
resp.getMessageContent());
break;
case BidibLibrary.MSG_SYS_GET_UNIQUE_ID:
LOGGER.info("Get the UNIQUE_ID will return a fake message.");
SysUniqueIdResponse sysUniqueIdResponse =
new SysUniqueIdResponse(Node.ROOTNODE_ADDR, 0, 0x90000D84002100L);
concreteBidibMessage =
new LocalBidibUpResponse(localBidibDownMessage.getAddr(), 0/* sendMsgNum */,
sysUniqueIdResponse.getMessageContent());
break;
case BidibLibrary.MSG_SYS_GET_P_VERSION:
LOGGER.info("Get the P_VERSION will return a fake message.");
SysPVersionResponse sysPVersionResponse = new SysPVersionResponse(Node.ROOTNODE_ADDR, 0, 0, 7);
concreteBidibMessage =
new LocalBidibUpResponse(localBidibDownMessage.getAddr(), 0/* sendMsgNum */,
sysPVersionResponse.getMessageContent());
break;
default:
break;
}
}
catch (Exception ex) {
LOGGER.warn("Handle local bidib down message failed: {}", ByteUtils.bytesToHex(wrappedMessage), ex);
}
if (concreteBidibMessage != null) {
LOGGER.info("Publish the LocalBidibUpResponse: {}", concreteBidibMessage);
messageHostAdapter.forwardMessageToGuest(proxyNode, concreteBidibMessage);
LOGGER.info("Skip further processing of message: {}", concreteBidibMessage);
return;
}
// handle the proprietary messages
GatewayRequest gatewayRequest = null;
final ObjectMapper objectMapper = new ObjectMapper();
try {
gatewayRequest = objectMapper.readValue(wrappedMessage, GatewayRequest.class);
}
catch (IOException ex) {
LOGGER.warn("Read request from guest failed.", ex);
}
LOGGER.info("Current request: {}", gatewayRequest);
if (gatewayRequest != null && gatewayRequest.getRequest() != null) {
switch (gatewayRequest.getRequest()) {
case "locolist":
// TODO this is a hack to get the loco list transferred to the guest
LOGGER.info("Publish the locolist.");
try {
concreteBidibMessage =
new LocalBidibUpResponse(localBidibDownMessage.getAddr(), 0/* sendMsgNum */,
prepareLocoList());
messageHostAdapter.forwardMessageToGuest(proxyNode, concreteBidibMessage);
}
catch (JsonProcessingException | ProtocolException ex) {
LOGGER.warn("Send the LocalBidibUpResponse failed.", ex);
}
break;
default:
break;
}
}
else {
}
}
protected byte[] prepareLocoList() throws JsonProcessingException {
// create ObjectMapper instance
final ObjectMapper objectMapper = new ObjectMapper();
// TODO
List locoDataList = new ArrayList<>();
LocoData locoItem = new LocoData(3, "Capitole");
locoDataList.add(locoItem);
locoItem = new LocoData(6, "Re 485");
locoDataList.add(locoItem);
// configure objectMapper for pretty input
// objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
LocoList locoList = new LocoList(locoDataList);
return objectMapper.writeValueAsBytes(locoList);
}
protected void processGuestReqSend(
final SequenceNumberProvider proxyNode, final GuestRequestSendMessage guestRequestSendMessage) {
final byte[] gatewayAddress = guestRequestSendMessage.getAddr();
final TargetModeEnum targetMode = guestRequestSendMessage.getTargetMode();
try {
byte[] wrappedContent = guestRequestSendMessage.getWrappedContent();
wrappedContent = ByteUtils.append(wrappedContent, ByteUtils.getLowByte(BidibLibrary.BIDIB_PKT_MAGIC));
LOGGER.info("Current wrappedContent: {}", ByteUtils.bytesToHex(wrappedContent));
this.requestFactory.create(wrappedContent).forEach(command -> {
LOGGER.info("Current command: {}", command);
// TODO we must get the data from the gatewayNodeProvider and not ask the backend
NodeInterface gatewayNode = bidibProxyConnection.getNodeProvider().findNodeByAddress(command.getAddr());
LOGGER.info("Current proxyNode: {}, resolved gatewayNode: {}", proxyNode, gatewayNode);
switch (ByteUtils.getInt(command.getType())) {
case BidibLibrary.MSG_SYS_GET_MAGIC:
final SysGetMagicMessage sysMagic = (SysGetMagicMessage) command;
// return the magic of the gateway node
Integer magic = gatewayNode.getNode().getMagic();
// TODO use correct sequence number
int num = 0;
try {
BidibMessage bidibResponse =
responseFactory.createSysMagicResponse(sysMagic.getAddr(), num, magic);
LOGGER
.info(">>> MSG_SYS_GET_MAGIC: Current messageContent: {}",
ByteUtils.bytesToHex(bidibResponse.getMessageContent()));
// prepare the GuestResponseFyiResponse that is published by the
// DistributedBidibMessageReceiver
byte[] nodeAddress = command.getAddr();
GuestResponseNotifyMessage guestResponseNotifyResponse =
new GuestResponseNotifyMessage(gatewayAddress, 0, targetMode, nodeAddress,
bidibResponse.getNum(), bidibResponse.getMessageContent());
messageHostAdapter.forwardMessageToGuest(proxyNode, guestResponseNotifyResponse);
}
catch (ProtocolException ex) {
LOGGER.info("Process command from wrapped message failed.", ex);
}
break;
case BidibLibrary.MSG_CS_SET_STATE:
final CommandStationSetStateMessage csSetStateMessage = (CommandStationSetStateMessage) command;
final CommandStationState commandStationState = csSetStateMessage.getState();
LOGGER
.info("Set the requested CS state: {}, gatewayNode: {}", commandStationState, gatewayNode);
// use the command station service to send the message
if (bidibProxyConnection != null) {
NodeAddress nodeAddress = JsonNodeUtils.prepareNodeAddress(gatewayNode);
commandStationService
.setCommandStationState(bidibProxyConnection.getConnectionId(), nodeAddress,
CommandStationStatus.valueOf(commandStationState));
}
else {
LOGGER.warn("No bidibConnection available.");
}
break;
case BidibLibrary.MSG_CS_DRIVE:
final CommandStationDriveMessage csDriveMessage = (CommandStationDriveMessage) command;
// use the command station service to send the message
if (bidibProxyConnection != null) {
NodeAddress nodeAddress = JsonNodeUtils.prepareNodeAddress(gatewayNode);
AddressData addressData = csDriveMessage.getDecoderAddress();
int locoAddress = addressData.getAddress();
SpeedSteps speedSteps = SpeedSteps.valueOf(csDriveMessage.getSpeedSteps());
Integer speed = csDriveMessage.getSpeed();
DirectionStatus direction = DirectionStatus.valueOf(addressData.getType());
// TODO fix
int outputActiveBits = csDriveMessage.getOutputActiveBits();
LOGGER.info("Send speed, outputActiveBits: {}", outputActiveBits);
BitSet activeFunctions = new BitSet(1);
for (int index = 0; index < 6; index++) {
activeFunctions.set(index, ByteUtils.getBit(outputActiveBits, index) == 1);
}
BitSet functions = ConversionUtils.convertFunctions(csDriveMessage.getFunctionBits());
// TODO provide the context
final Context context = null;
commandStationService
.setSpeed(bidibProxyConnection.getConnectionId(), nodeAddress, locoAddress, speedSteps,
speed, direction, activeFunctions, functions, context);
}
else {
LOGGER.warn("No bidibConnection available.");
}
break;
default:
LOGGER.warn("The command is not processed: {}", command);
break;
}
});
}
catch (ProtocolException ex) {
LOGGER.info("Process command from wrapped message failed.", ex);
}
catch (Exception ex) {
LOGGER.info("Process command from wrapped message failed.", ex);
}
}
}