All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bidib.wizard.gateway.service.BidibDistributedGatewayService Maven / Gradle / Ivy

There is a newer version: 2.0.29
Show newest version
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); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy