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

org.bidib.wizard.simulation.OneHubSimulator Maven / Gradle / Ivy

There is a newer version: 2.0.26
Show newest version
package org.bidib.wizard.simulation;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections4.MapUtils;
import org.bidib.jbidibc.messages.BidibLibrary;
import org.bidib.jbidibc.messages.BidibPort;
import org.bidib.jbidibc.messages.Feature;
import org.bidib.jbidibc.messages.enums.LcOutputType;
import org.bidib.jbidibc.messages.enums.PortModelEnum;
import org.bidib.jbidibc.messages.exception.ProtocolException;
import org.bidib.jbidibc.messages.message.BidibMessageInterface;
import org.bidib.jbidibc.messages.message.BidibRequestFactory;
import org.bidib.jbidibc.messages.message.LcConfigGetMessage;
import org.bidib.jbidibc.messages.message.LcConfigResponse;
import org.bidib.jbidibc.messages.message.LcConfigSetMessage;
import org.bidib.jbidibc.messages.message.LcKeyMessage;
import org.bidib.jbidibc.messages.message.LcKeyResponse;
import org.bidib.jbidibc.messages.message.LcNotAvailableResponse;
import org.bidib.jbidibc.messages.message.LcPortQueryAllMessage;
import org.bidib.jbidibc.messages.message.LcPortQueryMessage;
import org.bidib.jbidibc.messages.message.LcStatResponse;
import org.bidib.jbidibc.messages.port.PortConfigUtils;
import org.bidib.jbidibc.messages.utils.ByteUtils;
import org.bidib.jbidibc.messages.utils.NodeUtils;
import org.bidib.jbidibc.simulation.SimulationBidibMessageProcessor;
import org.bidib.jbidibc.simulation.SwitchingFunctionsNode;
import org.bidib.jbidibc.simulation.annotation.BidibNodeSimulator;
import org.bidib.jbidibc.simulation.annotation.BidibNodeSimulators;
import org.bidib.jbidibc.simulation.nodes.DefaultNodeSimulator;
import org.bidib.jbidibc.simulation.nodes.FlatPortType;
import org.bidib.jbidibc.simulation.nodes.InputPortType;
import org.bidib.jbidibc.simulation.nodes.PortType;
import org.bidib.wizard.model.ports.InputPort;
import org.bidib.wizard.model.ports.Port;
import org.bidib.wizard.model.status.InputPortStatus;
import org.bidib.wizard.simulation.events.InputPortStatusEvent;
import org.bushe.swing.event.EventBus;
import org.bushe.swing.event.annotation.AnnotationProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@BidibNodeSimulators({ @BidibNodeSimulator(vid = "13", pid = "114"), @BidibNodeSimulator(vid = "251", pid = "107") })
public class OneHubSimulator extends DefaultNodeSimulator implements /* InterfaceNode, */ SwitchingFunctionsNode {
    private static final Logger LOGGER = LoggerFactory.getLogger(OneHubSimulator.class);

    // TODO change
    private static final String SIMULATION_PANEL_CLASS =
        "org.bidib.wizard.simulation.client.view.panel.LightControlPanel";

    private final Map inputPorts = new HashMap();

    private int inputPortCount;

    public OneHubSimulator(byte[] nodeAddress, long uniqueId, boolean autoAddFeature,
        SimulationBidibMessageProcessor messageReceiver, final BidibRequestFactory bidibRequestFactory) {
        super(nodeAddress, uniqueId, autoAddFeature, messageReceiver, bidibRequestFactory);

        if (!NodeUtils.hasSubNodesFunctions(uniqueId)) {
            LOGGER.warn("The configured Hub has no subnode functions defined in the uniqueId!");
        }
    }

    @Override
    protected void prepareFeatures() {
        LOGGER.info("Prepare the features.");
        super.prepareFeatures();

        // features.add(new Feature(BidibLibrary.FEATURE_CTRL_INPUT_COUNT, inputPortCount));

        features.add(new Feature(BidibLibrary.FEATURE_CTRL_INPUT_NOTIFY, 1));
    }

    @Override
    public void postConstruct() {
        super.postConstruct();

        features.add(new Feature(BidibLibrary.FEATURE_CTRL_INPUT_COUNT, inputPortCount));
    }

    @Override
    protected void prepareCVs() {
        super.prepareCVs();
    }

    @Override
    public String getSimulationPanelClass() {
        return SIMULATION_PANEL_CLASS;
    }

    @Override
    public void start() {
        LOGGER.info("Start the simulator for address: {}", getAddress());

        AnnotationProcessor.process(this);

        // prepare the input ports
        setupInputPorts();

        super.start();
    }

    @Override
    public void stop() {
        AnnotationProcessor.unprocess(this);
        super.stop();
    }

    private void setupInputPorts() {
        for (int id = 0; id < inputPortCount; id++) {
            InputPort port = new InputPort();

            port.setId(id);
            port.setStatus(id % 2 == 0 ? InputPortStatus.ON : InputPortStatus.OFF);
            inputPorts.put(id, port);
        }
    }

    @Override
    protected byte[] prepareResponse(BidibMessageInterface bidibMessage) {

        byte[] response = null;
        switch (ByteUtils.getInt(bidibMessage.getType())) {
            case BidibLibrary.MSG_LC_CONFIG_GET:
                response = processLcConfigGetRequest(bidibMessage);
                break;
            case BidibLibrary.MSG_LC_CONFIG_SET:
                response = processLcConfigSetRequest(bidibMessage);
                break;
            case BidibLibrary.MSG_LC_KEY_QUERY:
                response = processLcKeyQueryRequest(bidibMessage);
                break;
            case BidibLibrary.MSG_LC_PORT_QUERY:
                response = processLcPortQueryRequest(bidibMessage);
                break;
            default:
                response = super.prepareResponse(bidibMessage);
                break;
        }
        return response;
    }

    protected byte[] processLcKeyQueryRequest(BidibMessageInterface bidibMessage) {

        LOGGER.info("Process the LcKeyQuery request: {}", bidibMessage);
        byte[] response = null;

        byte keyState = 0;
        Port port = null;
        try {
            LcKeyMessage lcKeyMessage = (LcKeyMessage) bidibMessage;
            int portNumber = lcKeyMessage.getBidibPort().getPortNumber(PortModelEnum.type);
            port = inputPorts.get(portNumber);
            keyState = port.getStatus().getType().getType();
            LcKeyResponse lcKeyResponse =
                new LcKeyResponse(bidibMessage.getAddr(), getNextSendNum(), ByteUtils.getLowByte(portNumber), keyState);
            response = lcKeyResponse.getContent();
        }
        catch (ProtocolException ex) {
            LOGGER.warn("Create LcKey response failed.", ex);
        }

        if (port != null) {
            publishInputPortChange(port);
        }

        return response;
    }

    protected byte[] processLcPortQueryRequest(BidibMessageInterface bidibMessage) {
        LOGGER.info("Process the LcOutputQuery request: {}", bidibMessage);
        byte[] response = null;

        byte portState = 0;

        try {
            final LcPortQueryMessage lcPortQueryMessage = (LcPortQueryMessage) bidibMessage;
            LcOutputType outputType = lcPortQueryMessage.getPortType(getPortModel());
            int portNumber = lcPortQueryMessage.getPortNumber(getPortModel());

            switch (outputType) {
                case INPUTPORT:
                    portState = inputPorts.get(portNumber).getStatus().getType().getType();
                    break;
                default:
                    LOGGER.warn("LcOutputQuery for unsupported port type detected: {}", outputType);
                    break;
            }
            BidibPort bidibPort = prepareBidibPort(getPortModel(), outputType, portNumber);

            LcStatResponse lcStatResponse =
                new LcStatResponse(bidibMessage.getAddr(), getNextSendNum(), bidibPort, portState);
            response = lcStatResponse.getContent();
        }
        catch (ProtocolException ex) {
            LOGGER.warn("Create LcStat response failed.", ex);
        }
        return response;
    }

    protected byte[] processLcPortQueryAllRequest(BidibMessageInterface bidibMessage) {
        LOGGER.info("Process the PortQueryAll request: {}", bidibMessage);
        byte[] response = null;
        try {
            LcPortQueryAllMessage portQueryAllMessage = (LcPortQueryAllMessage) bidibMessage;
            int portRangeFrom = portQueryAllMessage.getPortRangeFrom(getPortModel());
            int portRangeTo = portQueryAllMessage.getPortRangeTo(getPortModel());
            int portTypeMask = portQueryAllMessage.getPortTypeMask();

            LOGGER
                .info("Query all port states, portRangeFrom: {}, portRangeTo: {}, portModel: {}, portTypeMask: {}",
                    portRangeFrom, portRangeTo, getPortModel(), portTypeMask);

            if (PortConfigUtils.isSupportsInputPort(portTypeMask) && MapUtils.isNotEmpty(inputPorts)) {
                for (InputPort inputPort : inputPorts.values()) {

                    if (inputPort.getId() >= portRangeFrom && inputPort.getId() < portRangeTo) {
                        try {
                            InputPortStatus inputPortStatus = inputPort.getStatus();
                            if (inputPortStatus == null) {
                                inputPort.setStatus(InputPortStatus.OFF);
                                inputPortStatus = inputPort.getStatus();
                            }
                            byte portStatus = inputPortStatus.getType().getType();

                            publishPortState(bidibMessage.getAddr(), LcOutputType.INPUTPORT, inputPort.getId(),
                                portStatus);
                        }
                        catch (Exception ex) {
                            LOGGER.warn("Publish port state failed for port: {}", inputPort, ex);
                        }
                    }
                    else {
                        LOGGER.info("Skip input port that is out of port range: {}", inputPort);
                    }
                }
            }

            LOGGER.info("Send the terminating LC_NA message.");
            publishLcNaResponse(bidibMessage.getAddr());
        }
        catch (ProtocolException ex) {
            LOGGER.warn("Create LcStat response failed.", ex);
        }
        return response;
    }

    protected void publishPortState(byte[] address, LcOutputType outputType, int outputNumber, byte portStatus)
        throws ProtocolException {

        BidibPort bidibPort = prepareBidibPort(getPortModel(), outputType, outputNumber);

        LcStatResponse lcStatResponse = new LcStatResponse(address, getNextSendNum(), bidibPort, portStatus);

        LOGGER.info("Prepared LcStatResponse: {}", lcStatResponse);

        byte[] response = lcStatResponse.getContent();
        sendSpontanousResponse(response);
    }

    protected void publishLcNaResponse(byte[] address) throws ProtocolException {

        BidibPort bidibPort = new BidibPort(new byte[] { ByteUtils.getLowByte(0xFF), ByteUtils.getLowByte(0xFF) });

        LcNotAvailableResponse lcNotAvailableResponse =
            new LcNotAvailableResponse(address, getNextSendNum(), bidibPort);

        LOGGER.info("Prepared LcNotAvailableResponse: {}", lcNotAvailableResponse);

        byte[] response = lcNotAvailableResponse.getContent();
        sendSpontanousResponse(response);
    }

    protected byte[] processLcConfigGetRequest(BidibMessageInterface bidibMessage) {
        LOGGER.info("Process the LcConfigGet request: {}", bidibMessage);
        byte[] response = null;

        try {
            LcConfigGetMessage lcConfigGetMessage = (LcConfigGetMessage) bidibMessage;
            LcOutputType outputType = lcConfigGetMessage.getPortType(getPortModel());
            int outputNumber = lcConfigGetMessage.getPortNumber(getPortModel());

            Port port = null;
            switch (outputType) {
                case INPUTPORT:
                    port = inputPorts.get(Integer.valueOf(outputNumber));
                    break;
                default:
                    LOGGER.warn("LcConfigGet request for unsupported port type detected: {}", outputType);
                    break;
            }

            BidibPort bidibPort = prepareBidibPort(getPortModel(), outputType, outputNumber);
            if (port != null) {
                LcConfigResponse lcConfigResponse =
                    new LcConfigResponse(bidibMessage.getAddr(), getNextSendNum(), bidibPort, port.getPortConfig());
                response = lcConfigResponse.getContent();
            }
            else {
                LOGGER.warn("No port assigned!");
                LcNotAvailableResponse lcNotAvailableResponse =
                    new LcNotAvailableResponse(bidibMessage.getAddr(), getNextSendNum(), bidibPort);
                response = lcNotAvailableResponse.getContent();
            }
        }
        catch (ProtocolException ex) {
            LOGGER.warn("Create LcConfig response failed.", ex);
        }
        return response;
    }

    protected byte[] processLcConfigSetRequest(BidibMessageInterface bidibMessage) {

        LOGGER.info("Process the LcConfigSet request: {}", bidibMessage);
        byte[] response = null;
        try {
            LcConfigSetMessage lcConfigSetMessage = (LcConfigSetMessage) bidibMessage;
            LcOutputType outputType = lcConfigSetMessage.getPortType(getPortModel());
            int outputNumber = lcConfigSetMessage.getPortNumber(getPortModel());

            Port port = null;
            switch (outputType) {
                case INPUTPORT:
                    InputPort inputPort = inputPorts.get(Integer.valueOf(outputNumber));
                    if (inputPort != null) {
                        LOGGER.warn("The input port has no config to set.");
                        port = inputPort;
                    }
                    else {
                        LOGGER.warn("Inputport not available, outputNumber: {}", outputNumber);
                    }
                    break;
                default:
                    LOGGER.warn("LcConfigSet request for unsupported port type detected: {}", outputType);
                    break;
            }

            BidibPort bidibPort = prepareBidibPort(getPortModel(), outputType, outputNumber);
            if (port != null) {
                LcConfigResponse lcConfigResponse =
                    new LcConfigResponse(bidibMessage.getAddr(), getNextSendNum(), bidibPort, port.getPortConfig());
                response = lcConfigResponse.getContent();
            }
            else {
                LOGGER.warn("No port assigned!");
                LcNotAvailableResponse lcNotAvailableResponse =
                    new LcNotAvailableResponse(bidibMessage.getAddr(), getNextSendNum(), bidibPort);
                response = lcNotAvailableResponse.getContent();
            }
        }
        catch (ProtocolException ex) {
            LOGGER.warn("Create LcStat response failed.", ex);
        }
        return response;
    }

    private void publishInputPortChange(Port port) {
        InputPort inputPort = (InputPort) port;
        InputPortStatus status = inputPort.getStatus();

        LOGGER.info("The inputport status has changed, notify the listeners, nodeAddress: {}", nodeAddress);
        EventBus.publish(new InputPortStatusEvent(NodeUtils.formatAddress(nodeAddress), inputPort.getId(), status));
    }

    @Override
    public void queryStatus(Class portClass) {
        if (InputPort.class.equals(portClass)) {
            for (InputPort inputPort : inputPorts.values()) {
                publishInputPortChange(inputPort);
            }
        }
    }

    @Override
    public void setPortsConfig(FlatPortType portType) {
    }

    @Override
    public void setPortsConfig(PortType portType) {
        if (portType == null) {
            return;
        }

        if (portType instanceof InputPortType) {
            inputPortCount = portType.getCount();
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy