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

org.bidib.wizard.mvc.debug.controller.DebugInterfaceController Maven / Gradle / Ivy

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

import java.awt.Component;
import java.awt.Container;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.JOptionPane;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.bidib.jbidibc.core.ConnectionListener;
import org.bidib.jbidibc.core.exception.PortNotFoundException;
import org.bidib.jbidibc.core.exception.PortNotOpenedException;
import org.bidib.jbidibc.debug.DebugInterface;
import org.bidib.jbidibc.debug.DebugMessageListener;
import org.bidib.jbidibc.debug.DebugMessageReceiver;
import org.bidib.jbidibc.debug.DebugReader;
import org.bidib.wizard.locale.Resources;
import org.bidib.wizard.mvc.common.model.CommPort;
import org.bidib.wizard.mvc.common.view.DockKeys;
import org.bidib.wizard.mvc.debug.controller.listener.DebugInterfaceControllerListener;
import org.bidib.wizard.mvc.debug.model.DebugInterfaceModel;
import org.bidib.wizard.mvc.debug.view.DebugInterfaceView;
import org.bidib.wizard.mvc.debug.view.listener.DebugInterfaceViewListener;
import org.bidib.wizard.mvc.debug.view.listener.ProgressStatusCallback;
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.SingleDockableContainer;
import com.vlsolutions.swing.docking.TabbedDockableContainer;

public class DebugInterfaceController implements DebugInterfaceControllerListener {

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

    private final DockingDesktop desktop;

    private DebugInterfaceModel debugInterfaceModel;

    private DebugInterfaceView debugInterfaceView;

    private DebugInterface debugReader;

    private DebugMessageReceiver messageReceiver;

    private DebugMessageListener messageListener;

    private List firmwareContent;

    protected final ScheduledExecutorService sendFileWorker = Executors.newScheduledThreadPool(1);

    public DebugInterfaceController(final DockingDesktop desktop) {
        this.desktop = desktop;
    }

    public void start() {
        // check if the debug interface view is already opened
        String searchKey = DockKeys.DEBUG_INTERFACE_VIEW;
        LOGGER.info("Search for view with key: {}", searchKey);
        Dockable view = desktop.getContext().getDockableByKey(searchKey);
        if (view != null) {
            LOGGER.info("Select the existing debug interface view instead of open a new one.");
            selectWindow(view);
            return;
        }

        LOGGER.info("Create new DebugInterfaceView.");
        debugInterfaceModel = new DebugInterfaceModel();

        debugInterfaceView = new DebugInterfaceView(desktop, this, debugInterfaceModel);

        DockableState[] dockables = desktop.getDockables();
        LOGGER.info("Current dockables: {}", new Object[] { dockables });
        if (dockables.length > 1) {

            DockableState tabPanelNodeDetails = null;
            // search the node details tab panel
            for (DockableState dockable : dockables) {

                if (DockKeys.DOCKKEY_TAB_PANEL.equals(dockable.getDockable().getDockKey())) {
                    LOGGER.info("Found the tab panel dockable.");
                    tabPanelNodeDetails = dockable;

                    break;
                }
            }

            Dockable dock = desktop.getDockables()[1].getDockable();
            if (tabPanelNodeDetails != null) {
                LOGGER.info("Add the debug interface view next to the node details panel.");
                dock = tabPanelNodeDetails.getDockable();

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

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

        debugInterfaceView.addDebugInterfaceViewListener(new DebugInterfaceViewListener() {

            @Override
            public void openConnection() {

                Integer baudRate = debugInterfaceModel.getBaudRate();

                if (baudRate == null) {
                    LOGGER.warn("No baudrate selected!");

                    JOptionPane.showMessageDialog(debugInterfaceView.getComponent(),
                        Resources.getString(DebugInterfaceController.class, "select-baudrate"), "Debug Interface",
                        JOptionPane.ERROR_MESSAGE);
                    return;
                }
                // PreferencesPortType debugPort = Preferences.getInstance().getPreviousSelectedDebugPort();
                CommPort debugPort = debugInterfaceModel.getSelectedPort();
                if (debugPort == null || StringUtils.isBlank(debugPort.getName())) {
                    LOGGER.warn("No debugPort selected!");

                    JOptionPane.showMessageDialog(debugInterfaceView.getComponent(),
                        Resources.getString(DebugInterfaceController.class, "select-port"), "Debug Interface",
                        JOptionPane.ERROR_MESSAGE);

                    return;
                }
                LOGGER.info("Current debugPort: {}", debugPort);
                String portName = debugPort.getName();

                if (debugReader == null) {
                    LOGGER.info("Create new instance of debug reader.");

                    try {
                        messageListener = new DebugMessageListener() {

                            @Override
                            public void debugMessage(final String message) {
                                LOGGER.info("debug message received: {}", message);
                                debugInterfaceView.addLog(message);
                            }
                        };
                        messageReceiver = new DebugMessageReceiver();
                        messageReceiver.addMessageListener(messageListener);
                        debugReader = new DebugReader(messageReceiver);
                    }
                    catch (Exception ex) {
                        LOGGER.warn("Open debug port failed.", ex);
                    }
                }

                try {
                    debugReader.open(portName, baudRate, new ConnectionListener() {

                        @Override
                        public void opened(String port) {
                            LOGGER.info("Port opened: {}", port);

                            debugInterfaceModel.setConnected(true);
                        }

                        @Override
                        public void closed(String port) {
                            LOGGER.info("Port closed: {}", port);
                            debugInterfaceModel.setConnected(false);
                        }
                    }, null);
                }
                catch (PortNotFoundException | PortNotOpenedException ex) {
                    LOGGER.warn("Open debug port failed.", ex);

                    JOptionPane.showMessageDialog(debugInterfaceView.getComponent(), "Open debug Port failed. Reason: "
                        + ex.getReason(), "Debug Interface", JOptionPane.ERROR_MESSAGE);
                }
                catch (Exception ex) {
                    LOGGER.warn("Open debug port failed.", ex);
                }
            }

            @Override
            public void closeConnection() {
                LOGGER.info("Close the debug connection.");

                fireCloseConnection();
            }

            @Override
            public void transmit() {
                String sendText = debugInterfaceModel.getSendText();
                LOGGER.info("Send text to debugReader: {}", sendText);

                if (debugReader != null) {

                    debugReader.send(sendText);
                }
            }

            @Override
            public void transmitFile(final AtomicBoolean continueTransmit, final ProgressStatusCallback callback) {
                fireTransmitFile(continueTransmit, callback);
            }
        });
    }

    private void fireTransmitFile(final AtomicBoolean continueTransmit, final ProgressStatusCallback callback) {
        File sendFile = debugInterfaceModel.getSendFile();
        LOGGER.info("Send file content to debugReader: {}", sendFile);

        if (debugReader != null) {
            // TODO prepare the data to send
            this.firmwareContent = null;

            InputStream input = null;
            List firmwareContent = new ArrayList<>();
            try {
                byte[] buffer = new byte[200];
                input = new FileInputStream(sendFile);

                int readBytes = IOUtils.read(input, buffer);
                while (readBytes > 0) {
                    LOGGER.debug("Number of bytes read: {}", readBytes);
                    byte[] packet = Arrays.copyOf(buffer, readBytes);
                    firmwareContent.add(packet);

                    readBytes = IOUtils.read(input, buffer);
                }

                // keep the firmware content
                this.firmwareContent = firmwareContent;
            }
            catch (IOException ex) {
                LOGGER.info("No firmware content file found.");
            }
            finally {
                if (input != null) {
                    try {
                        input.close();
                    }
                    catch (Exception e) {
                        LOGGER.warn("Close input stream failed.", e);
                    }
                    input = null;
                }
            }

            if (CollectionUtils.isNotEmpty(this.firmwareContent)) {
                LOGGER.info("Send first packet to debug reader.");

                debugInterfaceModel.setTransferInProgress(true);

                sendFirmwarePackets(continueTransmit, callback);
            }
        }
    }

    private void sendFirmwarePackets(final AtomicBoolean continueTransmit, final ProgressStatusCallback callback) {

        Runnable runnable = new Runnable() {
            public void run() {
                LOGGER.info("Start sending firmware packets.");

                int packetsSent = 0;
                int totalPackets = firmwareContent.size();
                try {
                    for (byte[] content : firmwareContent) {

                        if (!continueTransmit.get()) {
                            LOGGER.warn("Transfer firmware was aborted by user.");
                            break;
                        }

                        debugReader.send(content);

                        packetsSent++;
                        if (callback != null) {
                            callback.statusChanged((packetsSent * 100) / totalPackets);
                        }
                    }
                }
                catch (Exception ex) {
                    LOGGER.warn("Send firmware content to debug reader failed.", ex);
                }

                debugInterfaceModel.setTransferInProgress(false);

                if (callback != null) {
                    callback.transferFinished();
                }
            }
        };
        // Start the send firmware files process
        sendFileWorker.execute(runnable);

    }

    private void selectWindow(Dockable dockable) {

        // TODO this should also work with non-tabbed windows
        TabbedDockableContainer container = DockingUtilities.findTabbedDockableContainer(dockable);
        if (container != null) {
            container.setSelectedDockable(dockable);
        }
        else {
            LOGGER.warn("Container not available, select component directly.");

            SingleDockableContainer singleContainer = DockingUtilities.findSingleDockableContainer(dockable);
            if (singleContainer != null) {
                try {
                    Component comp = (Component) singleContainer;

                    Container container2 = comp.getParent();
                    if (container2 != null) {
                        container2 = container2.getParent();
                    }

                    if (container2 != null) {
                        LOGGER.info("Request focus: {}", container2);
                        container2.requestFocus();
                    }
                }
                catch (Exception ex) {
                    LOGGER.warn("Request focus in single container failed.", ex);
                }
            }
            else {
                dockable.getComponent().requestFocusInWindow();
            }
        }
    }

    private void fireCloseConnection() {
        if (debugReader != null) {
            LOGGER.info("Close the debug reader.");
            debugReader.close();

            debugInterfaceModel.setConnected(false);

            messageReceiver.removeMessageListener(messageListener);
            messageListener = null;
            messageReceiver = null;

            debugReader = null;
        }
        else {
            LOGGER.info("debug reader not available.");
        }
    }

    @Override
    public void viewClosed() {
        LOGGER.info("The view is closed.");

        fireCloseConnection();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy