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

org.bidib.wizard.mvc.ping.controller.PingTableController Maven / Gradle / Ivy

There is a newer version: 2.0.0-M1
Show newest version
package org.bidib.wizard.mvc.ping.controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.List;

import javax.swing.SwingUtilities;
import javax.swing.Timer;

import org.apache.commons.collections4.CollectionUtils;
import org.bidib.jbidibc.core.DefaultMessageListener;
import org.bidib.jbidibc.core.Node;
import org.bidib.jbidibc.core.utils.ByteUtils;
import org.bidib.jbidibc.core.utils.NodeUtils;
import org.bidib.wizard.comm.Communication;
import org.bidib.wizard.comm.CommunicationFactory;
import org.bidib.wizard.comm.listener.CommunicationListener;
import org.bidib.wizard.mvc.common.view.DockKeys;
import org.bidib.wizard.mvc.main.controller.MainControllerInterface;
import org.bidib.wizard.mvc.main.model.listener.DefaultNodeListListener;
import org.bidib.wizard.mvc.main.model.listener.NodeListListener;
import org.bidib.wizard.mvc.ping.model.NodePingModel;
import org.bidib.wizard.mvc.ping.model.NodePingState;
import org.bidib.wizard.mvc.ping.model.PingTableModel;
import org.bidib.wizard.mvc.ping.view.PingTableView;
import org.bidib.wizard.utils.DockUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vlsolutions.swing.docking.Dockable;
import com.vlsolutions.swing.docking.DockableState;
import com.vlsolutions.swing.docking.DockingConstants;
import com.vlsolutions.swing.docking.DockingDesktop;
import com.vlsolutions.swing.docking.DockingUtilities;
import com.vlsolutions.swing.docking.RelativeDockablePosition;
import com.vlsolutions.swing.docking.TabbedDockableContainer;
import com.vlsolutions.swing.docking.event.DockableStateChangeEvent;
import com.vlsolutions.swing.docking.event.DockableStateChangeListener;

public class PingTableController {

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

    private PingTableView pingTableView;

    private PingTableModel pingTableModel;

    private DefaultMessageListener messageListener;

    private Timer pingTimer;

    private Communication communication;

    public void start(final DockingDesktop desktop, final MainControllerInterface mainController) {

        // check if the ping view is already opened
        String searchKey = DockKeys.PING_TABLE_VIEW;
        LOGGER.info("Search for view with key: {}", searchKey);
        Dockable view = desktop.getContext().getDockableByKey(searchKey);
        if (view != null) {
            LOGGER.info("Select the existing ping table view.");
            DockUtils.selectWindow(view);
            return;
        }

        LOGGER.info("Create new PingTableView.");

        pingTableModel = new PingTableModel();

        pingTableView = new PingTableView(pingTableModel);

        // add the ping table panel next to the booster panel
        DockableState[] dockables = desktop.getDockables();
        LOGGER.info("Current dockables: {}", new Object[] { dockables });
        if (dockables.length > 1) {

            DockableState boosterTableView = null;
            // search the booster table view
            for (DockableState dockable : dockables) {

                if (DockKeys.DOCKKEY_BOOSTER_TABLE_VIEW.equals(dockable.getDockable().getDockKey())) {
                    LOGGER.info("Found the booster table view dockable.");
                    boosterTableView = dockable;

                    break;
                }
            }

            Dockable dock = desktop.getDockables()[1].getDockable();
            if (boosterTableView != null) {
                LOGGER.info("Add the ping table view to the booster table view panel.");
                dock = boosterTableView.getDockable();

                TabbedDockableContainer container = DockingUtilities.findTabbedDockableContainer(dock);
                int order = 0;
                if (container != null) {
                    order = container.getTabCount();
                }
                LOGGER.info("Add new ping table panel at order: {}", order);

                desktop.createTab(dock, pingTableView, order, true);
            }
            else {
                desktop.split(dock, pingTableView, DockingConstants.SPLIT_RIGHT);
            }
        }
        else {
            desktop.addDockable(pingTableView, RelativeDockablePosition.RIGHT);
        }

        // create the nodeList listener
        final NodeListListener nodeListListener = new DefaultNodeListListener() {

            @Override
            public void listNodeAdded(org.bidib.wizard.mvc.main.model.Node node) {
                LOGGER.info("The nodelist has a new node: {}", node);

                nodeNew(node.getNode());
            }

            @Override
            public void listNodeRemoved(org.bidib.wizard.mvc.main.model.Node node) {
                LOGGER.info("The nodelist has a node removed: {}", node);
                nodeLost(node.getNode());
            }
        };
        // register as nodeList listener at the main controller
        mainController.addNodeListListener(nodeListListener);

        try {
            CommunicationFactory.addCommunicationListener(new CommunicationListener() {

                @Override
                public void status(String statusText, int displayDuration) {
                }

                @Override
                public void opened(String port) {
                    LOGGER.info("The communication was opened.");

                    if (pingTimer != null && !pingTimer.isRunning()) {
                        LOGGER.info("Start the ping timer.");

                        pingTimer.start();
                    }
                }

                @Override
                public void initialized() {
                }

                @Override
                public void closed(String port) {
                    LOGGER.info("The communication was closed.");

                    // stop the ping timer
                    if (pingTimer != null) {
                        LOGGER.info("Stop the ping timer.");
                        pingTimer.stop();
                    }

                    List boosters = new LinkedList<>(pingTableModel.getNodes());
                    for (NodePingModel booster : boosters) {
                        pingTableModel.removeNode(booster.getNode());
                    }
                }
            });

            messageListener = new DefaultMessageListener() {
                @Override
                public void pong(final byte[] address, final int marker) {
                    LOGGER.debug("Set the pong marker: {}", marker);
                    if (SwingUtilities.isEventDispatchThread()) {
                        pingTableModel.setPongMarker(address, marker);
                    }
                    else {
                        SwingUtilities.invokeLater(new Runnable() {

                            @Override
                            public void run() {
                                pingTableModel.setPongMarker(address, marker);
                            }
                        });
                    }
                }
            };
            CommunicationFactory.addMessageListener(messageListener);

            final Communication communication = CommunicationFactory.getInstance();
            // get the current nodes
            List nodes = communication.getNodes();
            if (CollectionUtils.isNotEmpty(nodes)) {
                for (Node node : nodes) {
                    LOGGER.info("Initially add node.");
                    nodeNew(node);
                }
            }
        }
        catch (Exception ex) {
            LOGGER.warn("Register controller as node listener failed.", ex);
        }

        // listen on window close
        desktop.addDockableStateChangeListener(new DockableStateChangeListener() {

            @Override
            public void dockableStateChanged(DockableStateChangeEvent event) {
                if (event.getNewState().getDockable().equals(pingTableView) && event.getNewState().isClosed()) {
                    LOGGER.info("PingTableView was closed, free resources.");

                    try {
                        // remove node listener from communication factory
                        if (nodeListListener != null) {
                            mainController.removeNodeListListener(nodeListListener);
                        }
                        if (messageListener != null) {
                            CommunicationFactory.removeMessageListener(messageListener);
                        }
                    }
                    catch (Exception ex) {
                        LOGGER.warn("Register controller as node listener failed.", ex);
                    }

                    // stop the ping timer
                    if (pingTimer != null) {
                        LOGGER.info("Stop the ping timer.");
                        pingTimer.stop();
                        pingTimer = null;
                    }
                }
            }
        });

        try {
            communication = CommunicationFactory.getInstance();

            // start the ping timer
            pingTimer = new Timer(
                1000, new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        LOGGER.trace("The ping timer has elapsed.");

                        long now = System.currentTimeMillis();

                        // trigger the model
                        List nodePingModels = pingTableModel.getNodes();
                        for (NodePingModel nodePingModel : nodePingModels) {
                            if (nodePingModel.getNodePingState() == NodePingState.ON
                                && nodePingModel.getPingInterval() != null
                                && nodePingModel.getLastPing() < (now - (nodePingModel.getPingInterval() * 1000))) {
                                // perform a ping
                                try {
                                    int data = 12;
                                    LOGGER.info("Ping the node: {}, data: {}", nodePingModel, data);
                                    communication.ping(nodePingModel.getNode(), ByteUtils.getLowByte(data));

                                    nodePingModel.setLastPing(now);
                                }
                                catch (Exception ex) {
                                    LOGGER.warn("Ping node failed: {}", nodePingModel, ex);
                                }
                            }
                        }
                    }
                }) {
                private static final long serialVersionUID = 1L;

                @Override
                public void start() {
                    LOGGER.info("Fetch communication instance.");
                    communication = CommunicationFactory.getInstance();

                    super.start();
                }

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

                    LOGGER.info("Release communication instance.");
                    communication = null;
                }
            };
            pingTimer.setCoalesce(true);
            if (communication.isOpened()) {
                LOGGER.info("Start the ping timer.");
                communication = null;
                pingTimer.start();
            }
            else {
                LOGGER.info("The communication is not opened, the ping timer is not started.");
                communication = null;
            }
        }
        catch (Exception ex) {
            LOGGER.warn("Start the ping timer failed.", ex);
        }

    }

    private void nodeLost(final Node node) {
        LOGGER.info("Remove node from model: {}", node);
        if (SwingUtilities.isEventDispatchThread()) {
            pingTableModel.removeNode(node);
        }
        else {
            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    pingTableModel.removeNode(node);
                }
            });
        }
    }

    private void nodeNew(final Node node) {
        LOGGER.info("New node in system detected: {}", node);
        if (SwingUtilities.isEventDispatchThread()) {
            internalNewNode(node);
        }
        else {
            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    internalNewNode(node);
                }
            });
        }

        // if the node is a hub then we must get it's subnodes ...
        if (NodeUtils.hasSubNodesFunctions(node.getUniqueId())) {
            final Communication communication = CommunicationFactory.getInstance();
            List subNodes = new LinkedList<>(communication.getSubNodes(node));
            if (CollectionUtils.isNotEmpty(subNodes)) {
                for (Node subNode : subNodes) {
                    LOGGER.info("Found a subnode: {}", subNode);
                    nodeNew(subNode);
                }
            }
        }
    }

    private void internalNewNode(final Node node) {
        pingTableModel.addNode(node);

        // trigger the first ping from timer
        // CommunicationFactory.getInstance().ping(node, (byte) 1);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy