
org.bidib.wizard.mvc.firmware.controller.FirmwareController Maven / Gradle / Ivy
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