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

org.bidib.wizard.mvc.firmware.controller.FirmwareController Maven / Gradle / Ivy

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

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JFrame;

import org.bidib.jbidibc.core.FirmwareUpdateStat;
import org.bidib.jbidibc.core.enumeration.FirmwareUpdateOperation;
import org.bidib.jbidibc.core.enumeration.FirmwareUpdateState;
import org.bidib.jbidibc.core.exception.NoAnswerException;
import org.bidib.jbidibc.core.utils.ByteUtils;
import org.bidib.jbidibc.core.utils.CollectionUtils;
import org.bidib.jbidibc.core.utils.NodeUtils;
import org.bidib.jbidibc.exchange.bidib.FirmwareFactory;
import org.bidib.jbidibc.exchange.firmware.FirmwareNode;
import org.bidib.wizard.comm.Communication;
import org.bidib.wizard.comm.CommunicationFactory;
import org.bidib.wizard.locale.Resources;
import org.bidib.wizard.mvc.firmware.controller.listener.FirmwareControllerListener;
import org.bidib.wizard.mvc.firmware.model.FirmwareModel;
import org.bidib.wizard.mvc.firmware.model.FirmwareUpdatePart;
import org.bidib.wizard.mvc.firmware.model.UpdateStatus;
import org.bidib.wizard.mvc.firmware.view.FirmwareView;
import org.bidib.wizard.mvc.firmware.view.listener.FirmwareViewListener;
import org.bidib.wizard.mvc.main.model.MainModel;
import org.bidib.wizard.mvc.main.model.Node;
import org.bidib.wizard.mvc.main.model.listener.DefaultNodeListListener;
import org.bidib.wizard.mvc.main.model.listener.NodeListListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FirmwareController {
    private static final Logger LOGGER = LoggerFactory.getLogger(FirmwareController.class);

    private final Collection listeners = new LinkedList();

    private final Node node;

    private final JFrame parent;

    private final int x;

    private final int y;

    private final FirmwareModel model = new FirmwareModel();

    private final MainModel mainModel;

    private NodeListListener nodeListListener;

    public FirmwareController(JFrame parent, Node node, int x, int y, final MainModel mainModel) {
        this.parent = parent;
        this.node = node;
        this.x = x;
        this.y = y;
        this.mainModel = mainModel;
    }

    public void addFirmwareControllerListener(FirmwareControllerListener l) {
        listeners.add(l);
    }

    private void fireClose() {
        LOGGER.info("Close the firmware controller.");
        if (nodeListListener != null) {
            LOGGER.info("Remove the nodelist listener.");
            mainModel.removeNodeListListener(nodeListListener);
            nodeListListener = null;
        }

        for (FirmwareControllerListener l : listeners) {
            l.close();
        }
    }

    public void start() {
        final Communication communication = CommunicationFactory.getInstance();

        // get current values
        model.setNodeName(node.getLabel() != null ? node.getLabel() : NodeUtils.prepareNodeLabel(node.getNode()));
        model.setUniqueId(NodeUtils.getUniqueIdAsString(node.getNode().getUniqueId()));
        model.setVersion(communication.getSoftwareVersion(node.getNode()).toString());

        nodeListListener = new DefaultNodeListListener() {

            @Override
            public void listNodeRemoved(Node node) {
                LOGGER.info("Node was removed. Verify that it's not the node to be updated: {}", node);

                if (node.equals(FirmwareController.this.node)) {
                    LOGGER.error("The node that is updated was removed! Cancel all firmware update operations.");

                    model.setUpdateStatus(UpdateStatus.NODE_LOST);

                    model.addProcessingStatus(Resources.getString(FirmwareController.class, "status.node-lost"), 1);
                }
            }
        };
        mainModel.addNodeListListener(nodeListListener);

        final FirmwareView view = new FirmwareView(parent, model, x + 20, y + 20);

        view.addFirmwareViewListener(new FirmwareViewListener() {

            @Override
            public void close() {
                if (UpdateStatus.NONE.equals(model.getUpdateStatus())
                    || UpdateStatus.NODE_LOST.equals(model.getUpdateStatus())) {
                    LOGGER.info("No software update was started or node was lost: {}", model.getUpdateStatus());
                }
                else {
                    LOGGER.info("Send the firmware update operation EXIT command.");
                    try {
                        sendCommand(CommunicationFactory.getInstance(), FirmwareUpdateOperation.EXIT);
                    }
                    catch (InterruptedException e) {
                        LOGGER.warn("Send exit operation failed.", e);
                        throw new RuntimeException(e);
                    }
                }
                LOGGER.info("Close the dialog.");
                fireClose();
            }

            @Override
            public void updateFirmware() {
                // start the firmware update with the selected files
                final List firmwareFiles = model.getFirmwareFiles();
                final String firmwareArchivePath = model.getFirmwareArchivePath();

                LOGGER.info("Start the firmware update process, firmwareArchivePath: {}", firmwareArchivePath);

                if (CollectionUtils.hasElements(firmwareFiles)) {
                    // start a new thread to send the firmware to the node
                    new Thread() {
                        @Override
                        public void run() {
                            List firmwareUpdateParts = new LinkedList<>();
                            int fileSize = 0;
                            // Load the firmware into memory
                            for (FirmwareNode firmwareNode : firmwareFiles) {

                                File firmwareFile = new File(firmwareArchivePath);
                                int destination = firmwareNode.getDestinationNumber();

                                List firmwareContent = new ArrayList();
                                try {
                                    LOGGER.info("Load firmware from file into buffer: {}", firmwareArchivePath);

                                    firmwareContent =
                                        FirmwareFactory.getFirmwareContent(firmwareFile, firmwareNode.getFilename());

                                    // TODO optimize
                                    if (CollectionUtils.hasElements(firmwareContent)) {
                                        for (String line : firmwareContent) {
                                            fileSize += line.length();
                                        }
                                    }
                                    LOGGER
                                        .info(
                                            "Load firmware from file into buffer passed. Total number of packets to transfer: {}",
                                            firmwareContent.size());

                                    model.addProcessingStatus(
                                        Resources.getString(FirmwareController.class, "status.load-firmware-passed"),
                                        0, firmwareNode.getFilename());
                                }
                                catch (Exception e) {
                                    LOGGER.warn("Load firmware from file into buffer failed", e);

                                    model.addProcessingStatus(
                                        Resources.getString(FirmwareController.class, "status.load-firmware-failed"),
                                        1, firmwareNode.getFilename());
                                    model.setUpdateStatus(UpdateStatus.PREPARE_FAILED);
                                    model.setInProgress(false);
                                    return;
                                }

                                FirmwareUpdatePart firmwareUpdatePart =
                                    new FirmwareUpdatePart(firmwareNode.getFilename(), firmwareContent, destination);
                                firmwareUpdateParts.add(firmwareUpdatePart);
                            }

                            try {
                                LOGGER.info("Transfer file with length: {}", fileSize);
                                model.setUpdateStatus(UpdateStatus.PREPARE);
                                boolean enterFwUpdateModePassed =
                                    sendCommand(communication, FirmwareUpdateOperation.ENTER,
                                        ByteUtils.convertLongToUniqueId(node.getNode().getUniqueId()));
                                if (enterFwUpdateModePassed) {
                                    model.setUpdateStatus(UpdateStatus.ENTRY_PASSED);

                                    int currentSize = 0;
                                    boolean errorDetected = false;
                                    // transfer all selected parts
                                    for (FirmwareUpdatePart part : firmwareUpdateParts) {
                                        int destIdentifier = part.getDestination();

                                        LOGGER.info("Set the destination for the firmware: {}", destIdentifier);
                                        if (sendCommand(communication, FirmwareUpdateOperation.SETDEST,
                                            ByteUtils.getLowByte(destIdentifier))) {

                                            LOGGER.info("Set the destination for the firmware passed: {}",
                                                ByteUtils.getLowByte(destIdentifier));

                                            model.setUpdateStatus(UpdateStatus.DATA_TRANSFER);
                                            model.addProcessingStatus(
                                                Resources.getString(FirmwareController.class, "status.start-transfer"),
                                                0, part.getFilename());

                                            int block = 0;
                                            for (String line : part.getFirmwareContent()) {
                                                currentSize += line.length();
                                                model.setProgressValue(currentSize * 100 / fileSize);
                                                LOGGER.trace("Send block: {}, line: {}", block, line);

                                                if (!sendCommand(communication, FirmwareUpdateOperation.DATA,
                                                    line.getBytes())) {
                                                    LOGGER
                                                        .warn(
                                                            "Unexpected answer from node while sending fw data (block#: {}, line: {}).",
                                                            block, line);

                                                    errorDetected = true;
                                                    model.addProcessingStatus(Resources.getString(
                                                        FirmwareController.class, "status.unexpected-answer"), 1);
                                                    model.addProcessingStatus(Resources.getString(
                                                        FirmwareController.class, "status.transfer-aborted"), 1, part
                                                        .getFilename());

                                                    break;
                                                }
                                                block++;
                                            }

                                            if (!errorDetected) {
                                                LOGGER.info("Send the firmware update done command.");
                                                sendCommand(communication, FirmwareUpdateOperation.DONE);
                                                model.addProcessingStatus(Resources.getString(FirmwareController.class,
                                                    "status.transfer-finished"), 0, part.getFilename());
                                            }
                                            else {
                                                LOGGER.warn("There was an error detected during firmware update.");
                                            }
                                        }

                                        if (errorDetected) {
                                            LOGGER
                                                .info("Error detected during firmware update. Cancel update process.");

                                            model.setUpdateStatus(UpdateStatus.DATA_TRANSFER_FAILED);
                                            break;
                                        }
                                    }

                                    if (!errorDetected) {
                                        // all parts were transfered
                                        model.setUpdateStatus(UpdateStatus.DATA_TRANSFER_PASSED);
                                        LOGGER.info("The firmware update has passed.");
                                    }
                                    else {
                                        LOGGER.warn("The firmware update has not passed.");
                                    }

                                    model.setProgressValue(100);
                                    model.setInProgress(false);
                                }
                                else {
                                    LOGGER.warn("Enter firmware update operation failed.");
                                    model.setProgressValue(0);
                                    model.setInProgress(false);
                                    model.addProcessingStatus(Resources.getString(FirmwareController.class,
                                        "status.enter-firmware-update-mode-failed"), 1);
                                }
                            }
                            catch (Exception e) {
                                LOGGER.warn("Transfer firmware udpate to node failed.", e);

                                model.addProcessingStatus(
                                    Resources.getString(FirmwareController.class, "status.transfer-firmware-failed"), 1);
                                model.setUpdateStatus(UpdateStatus.DATA_TRANSFER_FAILED);
                                model.setInProgress(false);
                            }
                        }
                    }.start();
                }
                else {
                    model.setInProgress(false);
                }
            }
        });

        view.setVisible(true);
    }

    private boolean sendCommand(Communication communication, FirmwareUpdateOperation operation, byte... data)
        throws InterruptedException {
        boolean result = false;

        // try {
        // Thread.sleep(5);
        // }
        // catch (InterruptedException ex) {
        // LOGGER.warn("Sleep before send message was interrupted.", ex);
        // }

        FirmwareUpdateStat updateStat = null;
        // handle firmware update operations
        try {
            updateStat = communication.sendFirmwareUpdateOperation(node.getNode(), operation, data);
        }
        catch (NoAnswerException ex) {
            switch (operation) {
                case ENTER:
                    LOGGER.warn("No answer received during enter firmware update mode.", ex);
                    break;
                case EXIT:
                    LOGGER.warn("No answer received during exit firmware update mode.", ex);
                    break;
                default:
                    LOGGER.warn("No answer received during firmware update, try send data again.", ex);
                    traceTimeout(operation);
                    break;
            }
        }

        if (updateStat != null) {
            LOGGER.info("Received update stat, timeout: {}, state: {}, last operation: {}", updateStat.getTimeout(),
                updateStat.getState(), operation);
            Thread.sleep(updateStat.getTimeout() * 10);

            FirmwareUpdateState state = updateStat.getState();

            if ((operation == FirmwareUpdateOperation.ENTER && state == FirmwareUpdateState.READY)
                || (operation == FirmwareUpdateOperation.SETDEST && state == FirmwareUpdateState.DATA)
                || (operation == FirmwareUpdateOperation.DATA && state == FirmwareUpdateState.DATA)) {
                result = true;
            }
        }
        else {
            LOGGER.warn("No updateStat received for operation: {}", operation);
        }
        LOGGER.debug("sendCommand return result: {}", result);
        return result;
    }

    private void traceTimeout(final FirmwareUpdateOperation operation) {
        model.addProcessingStatus(Resources.getString(FirmwareController.class, "status.transfer-firmware-timeout"), 1,
            operation);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy