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

org.bidib.wizard.server.controllers.MessageActions Maven / Gradle / Ivy

There is a newer version: 2.0.29
Show newest version
package org.bidib.wizard.server.controllers;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.collections4.CollectionUtils;
import org.bidib.api.json.types.NodeAddress;
import org.bidib.api.json.types.booster.BoostDiagnostic;
import org.bidib.api.json.types.booster.BoosterState;
import org.bidib.api.json.types.booster.BoosterState.BoosterStateType;
import org.bidib.api.json.types.booster.BoosterState.CommandStationStateType;
import org.bidib.api.json.types.occupancy.AbstractPort;
import org.bidib.api.json.types.occupancy.AddressData.EnrailmentDirection;
import org.bidib.api.json.types.occupancy.OccupancyStatusResponse;
import org.bidib.api.json.types.occupancy.PortIdentifier;
import org.bidib.api.json.types.switching.AbstractConfigPort;
import org.bidib.api.json.types.switching.PortConfigResponse;
import org.bidib.api.json.types.switching.PortStatusResponse;
import org.bidib.jbidibc.messages.FeedbackAddressData;
import org.bidib.jbidibc.messages.enums.LcOutputType;
import org.bidib.wizard.api.model.BoosterNodeInterface;
import org.bidib.wizard.api.model.CommandStationNodeInterface;
import org.bidib.wizard.api.model.NodeInterface;
import org.bidib.wizard.api.model.connection.AbstractQueueEvent;
import org.bidib.wizard.api.model.connection.event.AccessoryStateMessageEvent;
import org.bidib.wizard.api.model.connection.event.OccupancyCvMessageEvent;
import org.bidib.wizard.api.model.event.NodeStatusEvent.StatusIdentifier;
import org.bidib.wizard.api.utils.JsonNodeUtils;
import org.bidib.wizard.api.utils.PortListUtils;
import org.bidib.wizard.model.ports.AnalogPort;
import org.bidib.wizard.model.ports.BacklightPort;
import org.bidib.wizard.model.ports.FeedbackPort;
import org.bidib.wizard.model.ports.GenericPort;
import org.bidib.wizard.model.ports.InputPort;
import org.bidib.wizard.model.ports.LightPort;
import org.bidib.wizard.model.ports.MotorPort;
import org.bidib.wizard.model.ports.Port;
import org.bidib.wizard.model.ports.PortTypeAware;
import org.bidib.wizard.model.ports.ServoPort;
import org.bidib.wizard.model.ports.SoundPort;
import org.bidib.wizard.model.ports.SwitchPairPort;
import org.bidib.wizard.model.ports.SwitchPort;
import org.bidib.wizard.model.status.BoosterStatus;
import org.bidib.wizard.model.status.FeedbackPortStatus;
import org.bidib.wizard.server.controllers.actions.BoosterDiagAction;
import org.bidib.wizard.server.controllers.actions.BoosterStatusAction;
import org.bidib.wizard.server.controllers.actions.CommandStationStatusAction;
import org.bidib.wizard.server.controllers.actions.FeedbackPortAction;
import org.bidib.wizard.server.controllers.actions.NodeStatusAction;
import org.bidib.wizard.server.controllers.actions.NodeStringAction;
import org.bidib.wizard.server.controllers.actions.PortConfigAction;
import org.bidib.wizard.server.controllers.actions.PortStatusAction;
import org.bidib.wizard.server.jsontuils.JsonPortMapping;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

enum MessageActions implements MessageConsumer {

    BoosterDiagAction {
        @Override
        public void accept(AbstractQueueEvent messageEvent, NodeInterface node, MessageController controller) {
            BoosterDiagAction event = (BoosterDiagAction) messageEvent;
            LOGGER.info("Received new booster diag action: {}", event);

            NodeAddress nodeAddress = JsonNodeUtils.prepareNodeAddress(node);
            final BoosterNodeInterface boosterNode = node.getBoosterNode();
            if (boosterNode != null) {

                BoostDiagnostic boostDiagnostic =
                    new BoostDiagnostic(event.getConnectionId(), nodeAddress, boosterNode.getBoosterCurrent(),
                        boosterNode.getBoosterMaximumCurrent(), boosterNode.getBoosterVoltage(),
                        boosterNode.getBoosterTemperature());
                controller.publishBoostDiagnostic(boostDiagnostic);
            }
        }
    },

    BoosterStateAction {
        @Override
        public void accept(AbstractQueueEvent messageEvent, NodeInterface node, MessageController controller) {
            // BoosterStateMessageEvent event = (BoosterStateMessageEvent) messageEvent;
            BoosterStatusAction event = (BoosterStatusAction) messageEvent;
            LOGGER.info("Received new booster state event: {}", event);
            NodeAddress nodeAddress = JsonNodeUtils.prepareNodeAddress(node);

            final BoosterNodeInterface boosterNode = node.getBoosterNode();
            if (boosterNode != null) {

                // prepare the json booster state
                BoosterState boosterState =
                    new BoosterState()
                        .withBooster(BoosterStateType
                            .fromValue(boosterNode.getBoosterStatus() != null ? boosterNode.getBoosterStatus().name()
                                : BoosterStatus.OFF.name()))
                        .withConnectionId(event.getConnectionId()).withNode(nodeAddress);

                // check if the node is a command station, and get the status of the command station
                CommandStationNodeInterface commandStationNode = node.getCommandStationNode();
                if (commandStationNode != null) {
                    if (commandStationNode.getCommandStationStatus() != null) {
                        boosterState
                            .withDcc(
                                CommandStationStateType.valueOf(commandStationNode.getCommandStationStatus().name()));
                    }
                    else {
                        boosterState.withDcc(CommandStationStateType.OFF);
                    }
                }

                LOGGER.info("Prepare new booster state: {}", boosterState);
                controller.publishBoosterState(boosterState);
            }
            else {
                LOGGER.warn("The signalled node is not a booster node: {}", node);
            }
        }
    },

    CommandStationStateAction {
        @Override
        public void accept(AbstractQueueEvent messageEvent, NodeInterface node, MessageController controller) {
            CommandStationStatusAction event = (CommandStationStatusAction) messageEvent;
            LOGGER.info("Received new command station state event: {}", event);
            CommandStationNodeInterface commandStationNode = node.getCommandStationNode();
            if (commandStationNode != null) {

                NodeAddress nodeAddress = JsonNodeUtils.prepareNodeAddress(node);

                BoosterState boosterState =
                    new BoosterState().withConnectionId(event.getConnectionId()).withNode(nodeAddress);
                if (commandStationNode.getCommandStationStatus() != null) {
                    boosterState
                        .withDcc(CommandStationStateType.fromValue(commandStationNode.getCommandStationStatus().name()));
                }

                // check if the node is a booster
                final BoosterNodeInterface boosterNode = node.getBoosterNode();
                if (boosterNode != null) {
                    if (boosterNode.getBoosterStatus() != null) {
                        boosterState.withBooster(BoosterStateType.valueOf(boosterNode.getBoosterStatus().name()));
                    }
                    else {
                        boosterState.withBooster(BoosterStateType.OFF);
                    }
                }
                LOGGER.info("Prepare new booster state: {}", boosterState);
                controller.publishBoosterState(boosterState);
            }
            else {
                LOGGER.warn("The signalled node is not a commandstation node: {}", node);
            }

        }
    },

    PortConfigAction {
        @Override
        public void accept(AbstractQueueEvent messageEvent, NodeInterface node, MessageController controller) {
            PortConfigAction event = (PortConfigAction) messageEvent;
            LOGGER
                .info("Received new PortConfigAction: {}, isInitialLoadFinished: {}", event,
                    node.getNodeLoadStatusIdentifier());

            if (StatusIdentifier.InitialLoadFinished != node.getNodeLoadStatusIdentifier()) {
                LOGGER.info("The initial load has not finished yet. Do not publish the port config.");
                return;
            }

            // publish the change to the client
            NodeAddress nodeAddress = JsonNodeUtils.prepareNodeAddress(node);
            final PortConfigResponse portConfigResponse =
                new PortConfigResponse().withConnectionId(event.getConnectionId()).withNode(nodeAddress);

            Port port = null;
            Integer portNumber = event.getPort().getPortNumber();
            if (node.getNode().isPortFlatModelAvailable()) {

                PortTypeAware genericPort = event.getPort();
                LcOutputType currentPortType = genericPort.getPortType();
                LOGGER
                    .info(
                        "The current node supports the flat port model, get the generic port with portNumber: {}, portType: {}",
                        portNumber, currentPortType);

                // get the port with the current port type
                port = PortListUtils.getPort(node, currentPortType, portNumber);
            }
            else {
                // get the port with the current port type
                port = (Port) event.getPort();
            }

            LOGGER.info("Convert port to jsonPort: {}", port);
            AbstractPort jsonPort = JsonPortMapping.toJsonPort(port);

            // publish the notification
            portConfigResponse.withPort(new PortIdentifier(portNumber, jsonPort.getPortType()));

            if (jsonPort instanceof AbstractConfigPort) {
                portConfigResponse.withPcfg(((AbstractConfigPort) jsonPort).getPcfg());
            }
            else {
                LOGGER.warn("No config available from jsonPort: {}", jsonPort);
            }

            try {
                controller.publishPortConfig(portConfigResponse);
            }
            catch (Exception ex) {
                LOGGER.warn("Publish the port config failed.", ex);
            }

        }
    },

    PortStatusAction {
        @Override
        public void accept(AbstractQueueEvent messageEvent, NodeInterface node, MessageController controller) {
            PortStatusAction event = (PortStatusAction) messageEvent;
            LOGGER.info("Received new PortStatusAction: {}", event);

            if (StatusIdentifier.InitialLoadFinished != node.getNodeLoadStatusIdentifier()) {
                LOGGER.info("The initial load has not finished yet. Do not publish the port status.");
                return;
            }

            // publish the change to the client
            NodeAddress nodeAddress = JsonNodeUtils.prepareNodeAddress(node);

            Port port = null;
            Integer portNumber = event.getPort().getPortNumber();
            if (node.getNode().isPortFlatModelAvailable()) {
                LOGGER.info("The current node supports the flat port model, update the generic port.");

                PortTypeAware genericPort = event.getPort();
                LcOutputType currentPortType = genericPort.getPortType();

                // get the port with the current port type
                port = PortListUtils.getPort(node, currentPortType, portNumber);
            }
            else {
                // get the port with the current port type
                port = (Port) event.getPort();

                if (port == null) {
                    LOGGER.warn("No port delivered in event: {}", event);
                }
            }

            try {
                LcOutputType portType = port.getPortType();

                LOGGER.info("Current port type: {}", portType);
                final PortStatusResponse portStatusResponse =
                    JsonPortMapping.toJsonPortStatusResponse(event.getConnectionId(), nodeAddress, port);

                try {
                    controller.publishPortStatus(portStatusResponse);
                }
                catch (Exception ex) {
                    LOGGER.warn("Publish the port status failed.", ex);
                }
            }
            catch (Exception ex2) {
                LOGGER.warn("Get the port type failed, port: {}", port, ex2);
            }

        }
    },

    NodeStatusAction {
        @Override
        public void accept(AbstractQueueEvent messageEvent, NodeInterface node, MessageController controller) {
            NodeStatusAction event = (NodeStatusAction) messageEvent;
            LOGGER.info("Received node status action: {}", event);

            if (StatusIdentifier.InitialLoadFinished != node.getNodeLoadStatusIdentifier()) {
                LOGGER.info("The initial load has not finished yet. Do not publish the port status.");
                return;
            }

            LOGGER.info("Publish the port config and the port status for node: {}", node);
            NodeAddress nodeAddress = JsonNodeUtils.prepareNodeAddress(node);

            if (node.getNode().isPortFlatModelAvailable()) {
                LOGGER.info("The current node supports the flat port model, publish config of the generic port ports.");

                List ports = node.getGenericPorts();
                for (GenericPort genericPort : ports) {

                    LOGGER.info("Prepare config data of genericPort: {}", genericPort);

                    int portNumber = genericPort.getPortNumber();
                    // get the port with the current port type
                    Port port = PortListUtils.getPort(node, genericPort.getCurrentPortType(), portNumber);

                    if (port == null) {
                        LOGGER.info("No port available for portNumber: {}", portNumber);
                        continue;
                    }

                    publishPort(event.getConnectionId(), nodeAddress, port, controller);
                }
            }
            else {
                // TODO add support for typed-port model
                LOGGER.info("Deliver all ports for typed-port model: {}", node);

                if (node.hasAnalogPorts()) {
                    // publish analog ports
                    for (AnalogPort port : node.getAnalogPorts()) {
                        publishPort(event.getConnectionId(), nodeAddress, port, controller);
                    }
                }

                if (node.hasBacklightPorts()) {
                    // publish backlight ports
                    for (BacklightPort port : node.getBacklightPorts()) {
                        publishPort(event.getConnectionId(), nodeAddress, port, controller);
                    }
                }

                if (node.hasInputPorts()) {
                    // publish input ports
                    List inputPorts = node.getInputPorts();
                    LOGGER.info("Node has inputPorts: {}", inputPorts);
                    for (InputPort port : inputPorts) {
                        publishPort(event.getConnectionId(), nodeAddress, port, controller);
                    }
                }
                else {
                    LOGGER.info("Node has node inputPorts: {}", node);
                }

                if (node.hasLightPorts()) {
                    // publish light ports
                    List lightPorts = node.getLightPorts();
                    LOGGER.info("Node has lightPorts: {}", lightPorts);
                    for (LightPort port : lightPorts) {
                        publishPort(event.getConnectionId(), nodeAddress, port, controller);
                    }
                }
                else {
                    LOGGER.info("Node has node lightPorts: {}", node);
                }

                if (node.hasMotorPorts()) {
                    // publish motor ports
                    for (MotorPort port : node.getMotorPorts()) {
                        publishPort(event.getConnectionId(), nodeAddress, port, controller);
                    }
                }

                if (node.hasServoPorts()) {
                    // publish servo ports
                    for (ServoPort port : node.getServoPorts()) {
                        publishPort(event.getConnectionId(), nodeAddress, port, controller);
                    }
                }

                if (node.hasSoundPorts()) {
                    // publish sound ports
                    for (SoundPort port : node.getSoundPorts()) {
                        publishPort(event.getConnectionId(), nodeAddress, port, controller);
                    }
                }

                if (node.hasSwitchPairPorts()) {
                    // publish switchPair ports
                    for (SwitchPairPort port : node.getSwitchPairPorts()) {
                        publishPort(event.getConnectionId(), nodeAddress, port, controller);
                    }
                }

                if (node.hasSwitchPorts()) {
                    // publish switch ports
                    for (SwitchPort port : node.getSwitchPorts()) {
                        publishPort(event.getConnectionId(), nodeAddress, port, controller);
                    }
                }
            }

        }
    },

    StringAction {
        @Override
        public void accept(AbstractQueueEvent messageEvent, NodeInterface node, MessageController controller) {
            NodeStringAction event = (NodeStringAction) messageEvent;
            LOGGER.info("Received node string action: {}", event);

            // TODO

        }
    },

    AccessoryStateAction {
        @Override
        public void accept(AbstractQueueEvent messageEvent, NodeInterface node, MessageController controller) {
            AccessoryStateMessageEvent event = (AccessoryStateMessageEvent) messageEvent;
            LOGGER.info("Received new AccessoryState event: {}", event);

            // TODO publish the change to the client

        }
    },

    OccupancyCvAction {
        @Override
        public void accept(AbstractQueueEvent messageEvent, NodeInterface node, MessageController controller) {
            OccupancyCvMessageEvent event = (OccupancyCvMessageEvent) messageEvent;
            LOGGER.info("Received new occupancy CV event: {}", event);

        }
    },

    FeedbackPortAction {
        @Override
        public void accept(AbstractQueueEvent messageEvent, NodeInterface node, MessageController controller) {
            FeedbackPortAction event = (FeedbackPortAction) messageEvent;
            LOGGER.info("Received new feedback port action: {}", event);

            final FeedbackPort feedbackPort = event.getPort();

            if (feedbackPort != null) {
                // publish the change to the client
                NodeAddress nodeAddress = JsonNodeUtils.prepareNodeAddress(node);
                final OccupancyStatusResponse occupancyStatusResponse =
                    buildOccupancyStatusResponse(event.getConnectionId(), nodeAddress, feedbackPort);

                controller.publishOccupancyStatus(occupancyStatusResponse);
            }

        }

    };

    private static final Logger LOGGER = LoggerFactory.getLogger(MessageActions.class);

    private static OccupancyStatusResponse buildOccupancyStatusResponse(
        String connectionId, final NodeAddress nodeAddress, final FeedbackPort feedbackPort) {

        final OccupancyStatusResponse occupancyStatusResponse =
            new OccupancyStatusResponse().withConnectionId(connectionId).withNode(nodeAddress);

        final org.bidib.api.json.types.occupancy.FeedbackPort jsonFeedbackPort =
            new org.bidib.api.json.types.occupancy.FeedbackPort().withId(feedbackPort.getId());
        occupancyStatusResponse.setPortNum(jsonFeedbackPort.getId());

        occupancyStatusResponse
            .setPortStatus(
                feedbackPort.getStatus() == FeedbackPortStatus.FREE ? OccupancyStatusResponse.FeedbackPortStatus.FREE
                    : OccupancyStatusResponse.FeedbackPortStatus.OCCUPIED);

        if (CollectionUtils.isNotEmpty(feedbackPort.getAddresses())) {

            Set addresses = new HashSet<>();
            for (FeedbackAddressData addressData : feedbackPort.getAddresses()) {
                final org.bidib.api.json.types.occupancy.AddressData jsonAddressData =
                    new org.bidib.api.json.types.occupancy.AddressData()
                        .withAddress(addressData.getAddress())
                        .withEnrailmentDirection(EnrailmentDirection.fromValue(addressData.getType().name()))
                        .withSpeed(addressData.getSpeed());
                addresses.add(jsonAddressData);
            }
            occupancyStatusResponse.withAddresses(addresses);
        }

        return occupancyStatusResponse;
    }

    private static void publishPort(
        String connectionId, NodeAddress nodeAddress, Port port, MessageController controller) {
        LOGGER.info("Convert port to jsonPort: {}, status: {}", port, port.getStatus());
        AbstractPort jsonPort = JsonPortMapping.toJsonPort(port);

        final PortConfigResponse portConfigResponse =
            new PortConfigResponse().withConnectionId(connectionId).withNode(nodeAddress);

        // publish the notification
        portConfigResponse.withPort(new PortIdentifier(port.getPortNumber(), jsonPort.getPortType()));

        if (jsonPort instanceof AbstractConfigPort) {
            portConfigResponse.withPcfg(((AbstractConfigPort) jsonPort).getPcfg());
        }
        else {
            LOGGER.warn("No config available from jsonPort: {}", jsonPort);
        }

        try {
            controller.publishPortConfig(portConfigResponse);
        }
        catch (Exception ex) {
            LOGGER.warn("Publish the port config failed.", ex);
        }

        try {
            LcOutputType portType = port.getPortType();

            LOGGER.info("Current port type: {}", portType);
            final PortStatusResponse portStatusResponse =
                JsonPortMapping.toJsonPortStatusResponse(connectionId, nodeAddress, port);

            controller.publishPortStatus(portStatusResponse);
        }
        catch (Exception ex) {
            LOGGER.warn("Publish the port status failed, port: {}", port, ex);
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy