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.0-M1
Show newest version
package org.bidib.wizard.simulation;

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

import org.bidib.jbidibc.core.BidibLibrary;
import org.bidib.jbidibc.core.BidibPort;
import org.bidib.jbidibc.core.Feature;
import org.bidib.jbidibc.core.enumeration.LcOutputType;
import org.bidib.jbidibc.core.exception.ProtocolException;
import org.bidib.jbidibc.core.message.BidibCommand;
import org.bidib.jbidibc.core.message.LcKeyMessage;
import org.bidib.jbidibc.core.message.LcKeyResponse;
import org.bidib.jbidibc.core.message.NodeLostResponse;
import org.bidib.jbidibc.core.message.NodeNewResponse;
import org.bidib.jbidibc.core.message.NodeTabCountResponse;
import org.bidib.jbidibc.core.message.NodeTabResponse;
import org.bidib.jbidibc.core.node.MacroFunctionsNode;
import org.bidib.jbidibc.core.utils.ByteUtils;
import org.bidib.jbidibc.core.utils.NodeUtils;
import org.bidib.jbidibc.simulation.InterfaceNode;
import org.bidib.jbidibc.simulation.SimulatorNode;
import org.bidib.jbidibc.simulation.SimulatorRegistry;
import org.bidib.jbidibc.simulation.SwitchingFunctionsNode;
import org.bidib.jbidibc.simulation.events.NodeAvailableEvent;
import org.bidib.jbidibc.simulation.events.NodeLostEvent;
import org.bidib.jbidibc.simulation.net.SimulationBidibMessageProcessor;
import org.bidib.jbidibc.simulation.nodes.DefaultNodeSimulator;
import org.bidib.jbidibc.simulation.nodes.InputPortType;
import org.bidib.jbidibc.simulation.nodes.PortType;
import org.bidib.wizard.comm.InputPortStatus;
import org.bidib.wizard.mvc.main.model.InputPort;
import org.bidib.wizard.mvc.main.model.Port;
import org.bidib.wizard.simulation.events.InputPortStatusEvent;
import org.bushe.swing.event.EventBus;
import org.bushe.swing.event.annotation.AnnotationProcessor;
import org.bushe.swing.event.annotation.EventSubscriber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OneHubSimulator extends DefaultNodeSimulator
    implements InterfaceNode, SwitchingFunctionsNode, MacroFunctionsNode {
    private static final Logger LOGGER = LoggerFactory.getLogger(OneHubSimulator.class);

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

    private byte localAddrIndex;

    private final Map inputPorts = new HashMap();

    private int inputPortCount;

    public OneHubSimulator(byte[] nodeAddress, long uniqueId, boolean autoAddFeature,
        SimulationBidibMessageProcessor messageReceiver) {
        super(nodeAddress, uniqueId, autoAddFeature, messageReceiver);
        // TODO Auto-generated constructor stub

        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
    protected void prepareCVs() {

        super.prepareCVs();

    }

    /**
     * @return the subNodes
     */
    public Map getSubNodes() {
        return subNodes;
    }

    /**
     * Add a new subnode.
     * 
     * @param simulator
     *            the simulator
     */
    @Override
    public void addSubNode(SimulatorNode simulator) {
        String nodeAddress = simulator.getLocalAddress().trim();
        LOGGER.info("Add new subnode, address: {}, simulator: {}", nodeAddress, simulator);
        subNodes.put(nodeAddress, simulator);
    }

    @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(BidibCommand bidibMessage) {

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

    protected byte[] processLcKeyQueryRequest(BidibCommand bidibMessage) {

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

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

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

        return response;
    }

    protected byte[] processNodeTabGetAllRequest(BidibCommand bidibMessage) {

        // reset the local addr
        localAddrIndex = 0;
        byte tabCount = (byte) subNodes.size();

        LOGGER.info("Return number of nodeTabs in current node: {}", tabCount);

        byte[] response = null;
        try {
            NodeTabCountResponse nodeTabCountResponse =
                new NodeTabCountResponse(bidibMessage.getAddr(), getNextSendNum(), tabCount);
            response = nodeTabCountResponse.getContent();
        }
        catch (ProtocolException ex) {
            LOGGER.warn("Create nodeTabCount response failed.", ex);
        }
        return response;
    }

    protected byte[] processNodeTabGetNextRequest(BidibCommand bidibMessage) {

        // 02.01.2014 14:50:11.961: send NodeTabGetAllMessage[num=4,type=11,data=[]] : FE 03 00 04 0B 93 FE
        // 02.01.2014 14:50:11.974: receive NodeTabCountResponse[[0],num=1,type=136,data=[2]] : 04 00 01 88 02
        // 02.01.2014 14:50:11.977: send NodeTabGetNextMessage[num=5,type=12,data=[]] : FE 03 00 05 0C D4 FE
        // 02.01.2014 14:50:11.990: receive NodeTabResponse[[0],num=2,type=137,data=[1, 0, 210, 0, 13, 104, 0, 0, 54]] :
        // 0C 00 02 89 01 00 D2 00 0D 68 00 00 36
        // 02.01.2014 14:50:11.994: send SysMagicMessage[num=6,type=1,data=[]] : FE 03 00 06 01 7C FE
        // 02.01.2014 14:50:12.006: receive SysMagicResponse[[0],num=0,type=129,data=[254, 175]] : 05 00 00 81 FE AF
        // 02.01.2014 14:50:12.008: send NodeTabGetNextMessage[num=7,type=12,data=[]] : FE 03 00 07 0C 45 FE
        // 02.01.2014 14:50:12.022: receive NodeTabResponse[[0],num=1,type=137,data=[1, 1, 5, 0, 13, 107, 0, 105, 234]]
        // : 0C 00 01 89 01 01 05 00 0D 6B 00 69 EA
        // 02.01.2014 14:50:12.031: send SysMagicMessage[num=0,type=1,data=[]] : FE 04 01 00 00 01 CE FE
        // 02.01.2014 14:50:12.038: receive SysMagicResponse[[1],num=0,type=129,data=[254, 175]] : 06 01 00 00 81 FE AF

        byte[] response = null;
        byte nodeTabVersion = 1;
        byte localAddr = localAddrIndex;

        LOGGER.info("get the simulator with local address: {}", localAddr);

        String[] nodeAddresses = subNodes.keySet().toArray(new String[0]);

        byte addr = ByteUtils.getLowByte(Integer.parseInt(nodeAddresses[localAddr], 16));

        SimulatorNode simulator = subNodes.get(nodeAddresses[localAddr]);
        long uniqueId = simulator.getUniqueId();

        LOGGER.info("localAddr: {}, nodeAddr: {}, uniqueId: {}", localAddr, addr, uniqueId);

        try {
            NodeTabResponse nodeTabResponse =
                new NodeTabResponse(bidibMessage.getAddr(), getNextSendNum(), nodeTabVersion, addr, uniqueId);
            response = nodeTabResponse.getContent();
            LOGGER.info("Prepared nodeTab response: {}", ByteUtils.bytesToHex(response));
        }
        catch (ProtocolException ex) {
            LOGGER.warn("Create nodeTab response failed.", ex);
        }

        localAddrIndex++;

        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(ByteUtils.bytesToHex(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(PortType portType) {
        if (portType == null) {
            return;
        }

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

    @EventSubscriber(eventClass = NodeLostEvent.class)
    public void nodeLostEvent(NodeLostEvent nodeLostEvent) {
        byte[] nodeAddr = nodeLostEvent.getNodeAddr();

        // check if the node is a subnode of this node
        if (!NodeUtils.isSubNode(nodeAddress, nodeAddr)) {
            return;
        }

        final byte nodeLocalAddress = nodeAddr[nodeAddr.length - 1];
        long uniqueId = nodeLostEvent.getUniqueId();
        LOGGER
            .info("The node lost event was requested, nodeLocalAddress: {}, uniqueId: {}", nodeLocalAddress, uniqueId);

        // publish event
        byte[] response = null;
        byte nodeTabVersion = ByteUtils.getLowByte(SimulatorRegistry.getInstance().getNextNodeTabVersion());
        try {
            byte addr = nodeLocalAddress;
            NodeLostResponse nodeLostResponse =
                new NodeLostResponse(nodeAddress, getNextSendNum(), nodeTabVersion, addr, uniqueId);

            response = nodeLostResponse.getContent();
            LOGGER.info("Prepared nodeLost response: {}", ByteUtils.bytesToHex(response));
        }
        catch (ProtocolException ex) {
            LOGGER.warn("Create nodeLost response failed.", ex);
        }

        LOGGER.info("Publish the current response: {}", response);
        publishResponse(response);
    }

    @EventSubscriber(eventClass = NodeAvailableEvent.class)
    public void nodeAvailableEvent(NodeAvailableEvent nodeAvailableEvent) {
        byte[] nodeAddr = nodeAvailableEvent.getNodeAddr();

        // check if the node is a subnode of this node
        if (!NodeUtils.isSubNode(nodeAddress, nodeAddr)) {
            return;
        }

        final byte nodeLocalAddress = nodeAddr[nodeAddr.length - 1];
        long uniqueId = nodeAvailableEvent.getUniqueId();
        LOGGER.info("The node available event was requested, nodeLocalAddress: {}, uniqueId: {}", nodeLocalAddress,
            uniqueId);

        // publish event
        byte[] response = null;
        byte nodeTabVersion = ByteUtils.getLowByte(SimulatorRegistry.getInstance().getNextNodeTabVersion());
        try {
            byte addr = nodeLocalAddress;
            NodeNewResponse nodeNewResponse =
                new NodeNewResponse(nodeAddress, getNextSendNum(), nodeTabVersion, addr, uniqueId);

            response = nodeNewResponse.getContent();
            LOGGER.info("Prepared nodeNew response: {}", ByteUtils.bytesToHex(response));
        }
        catch (ProtocolException ex) {
            LOGGER.warn("Create nodeNew response failed.", ex);
        }

        LOGGER.info("Publish the current response: {}", response);
        publishResponse(response);
    }

    @Override
    public boolean isPortFlatModelAvailable() {
        return false;
    }

    @Override
    public LcOutputType getPortType(BidibPort bidibPort) {
        return null;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy