/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package tgfx.updater.firmware; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.HashMap; import java.util.ResourceBundle; import java.util.logging.Level; import java.util.logging.Logger; import javafx.application.Platform; import javafx.beans.binding.NumberExpression; import javafx.beans.property.SimpleDoubleProperty; import javafx.concurrent.Task; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Button; import javafx.scene.control.Label; import jfxtras.labs.dialogs.MonologFX; import jfxtras.labs.dialogs.MonologFXBuilder; import jfxtras.labs.dialogs.MonologFXButton; import static jfxtras.labs.dialogs.MonologFXButton.Type.CANCEL; import static jfxtras.labs.dialogs.MonologFXButton.Type.YES; import jfxtras.labs.dialogs.MonologFXButtonBuilder; import jssc.SerialPortException; import tgfx.Main; import tgfx.tinyg.*; import tgfx.utility.UtilityFunctions; /** * FXML Controller class * * @author ril3y */ public class FirmwareUpdaterController implements Initializable { @FXML private static Label firmwareVersion; @FXML private Label hwVersion, buildNumb, hardwareId, latestFirmwareBuild; @FXML private Label currentFirmwareVersionLabel; @FXML private static Button handleUpdateFirmware; private SimpleDoubleProperty _currentVersionString = new SimpleDoubleProperty(); private static String avrdudePath = new String(); private static String avrconfigPath = new String(); static HashMap<String, String> platformSetup = new HashMap<>(); private static Task updateFirmware() { Task task; task = new Task<Void>() { @Override public Void call() throws IOException, Exception { File avc = new File("tools" + File.separator + "config" + File.separator + "avrdude.conf"); avrconfigPath = avc.getAbsolutePath(); if (UtilityFunctions.getOperatingSystem().equals("mac")) { File avd = new File("tools" + File.separator + "avrdude"); avrdudePath = avd.getAbsolutePath(); } else { File avd = new File("tools" + File.separator + "avrdude.exe"); avrdudePath = avd.getAbsolutePath(); } Main.print("Trying to enter bootloader mode"); Main.postConsoleMessage("Entering Bootloader mode. tgFX will be un-responsive for then next 30 seconds.\n" + "Your TinyG will start blinking rapidly while being programmed"); try { enterBootloaderMode(); } catch (SerialPortException ex) { Logger.getLogger(FirmwareUpdaterController.class.getName()).log(Level.SEVERE, null, ex); } //Download TinyG.hex URL url; try { url = new URL(TinygDriver.getInstance().machine.hardwarePlatform.getFirmwareUrl()); URLConnection urlConnection = url.openConnection(); Main.print("Opened Connection to Github"); Main.postConsoleMessage("Downloading tinyg.hex file from github.com"); InputStream input; input = urlConnection.getInputStream(); try (OutputStream output = new FileOutputStream(new File("tinyg.hex"))) { byte[] buffer = new byte[4096]; int n = -1; while ((n = input.read(buffer)) != -1) { if (n > 0) { output.write(buffer, 0, n); } } output.close(); Main.postConsoleMessage("Finished Downloading tinyg.hex"); Main.print("Finished Downloading tinyg.hex"); } } catch (MalformedURLException ex) { Logger.getLogger(FirmwareUpdaterController.class.getName()).log(Level.SEVERE, null, ex); Main.postConsoleMessage("Error downloading the TinyG update from: " + TinygDriver.getInstance().machine.hardwarePlatform.getFirmwareUrl()); Main.postConsoleMessage("Check your internetion connection and try again. Firmware update aborted..."); } catch (IOException ex) { Logger.getLogger(FirmwareUpdaterController.class.getName()).log(Level.SEVERE, null, ex); Main.postConsoleMessage("Error updating your TinyG. IOERROR"); return null; } Runtime rt = Runtime.getRuntime(); try { Main.postConsoleMessage("Updating TinyG Now... Please Wait"); Process process = rt.exec(avrdudePath + " -p x192a3 -C " + avrconfigPath + " -c avr109 -b 115200 -P " + TinygDriver.getInstance().getPortName() + " -U flash:w:tinyg.hex"); InputStream is = process.getInputStream(); Main.postConsoleMessage("Attempting to update TinyG's firmware."); process.waitFor(); Thread.sleep(2000);//sleep a bit and let the firmware init TinygDriver.getInstance().sendReconnectRequest(); Main.postConsoleMessage("Firmware update complete."); toggleUpdateFirmwareButton(true); } catch (MalformedURLException ex) { Main.postConsoleMessage("TinyG update URL: " + TinygDriver.getInstance().machine.hardwarePlatform.getFirmwareUrl() + " is invalid, check the platform config " + "file you are using in the configs directory."); Main.postConsoleMessage("Firmware update aborted..."); return null; } catch (IOException | InterruptedException ex) { Logger.getLogger(FirmwareUpdaterController.class.getName()).log(Level.SEVERE, null, ex); } return null; } }; return task; } private static void toggleUpdateFirmwareButton(boolean choice) { final boolean bChoice = choice; Platform.runLater(new Runnable() { @Override public void run() { handleUpdateFirmware.disableProperty().set(bChoice); //when we are updating we dont want to hit it 2x } }); } /** * Initializes the controller class. */ @FXML public static void handleUpdateFirmware(ActionEvent event) { if (TinygDriver.getInstance().machine.hardwarePlatform.getHardwarePlatformVersion() == -1) { //This code checks to see if a hardware platform has been applied. //if the hpv is -1 then it has not. So we guess that the board is a v8 TinyG. TinygDriver.getInstance().hardwarePlatformManager.setPlatformByName("TinyG"); } if (TinygDriver.getInstance().isTimedout() || TinygDriver.getInstance().machine.hardwarePlatform.isIsUpgradeable()) { //This platform can be upgraded toggleUpdateFirmwareButton(false); Task task = updateFirmware(); new Thread(task).start(); toggleUpdateFirmwareButton(true); } else { Main.postConsoleMessage("Sorry your TinyG platform cannot be auto upgraded at this time. Please see the TinyG wiki for manual upgrade instructions."); } } @FXML private void checkFirmwareUpdate(ActionEvent event) { Main.print("Checking current Firmware Version"); Platform.runLater(new Runnable() { @Override public void run() { try { URL url = new URL(TinygDriver.getInstance().machine.hardwarePlatform.getLatestVersionUrl()); URLConnection urlConnection = url.openConnection(); InputStream input; input = urlConnection.getInputStream(); byte[] buffer = new byte[4096]; Main.print("Checking end"); input.read(buffer); String _currentVersionString = new String(buffer); latestFirmwareBuild.setText(_currentVersionString); Double currentVal; if (TinygDriver.getInstance().machine.getFirmwareBuild() < Double.parseDouble(_currentVersionString)) { //We need to update your firmware Platform.runLater(new Runnable() { @Override public void run() { Main.postConsoleMessage("TinyG Firmware Update Available."); MonologFXButton btnYes = MonologFXButtonBuilder.create() .defaultButton(true) .icon("/testmonologfx/dialog_apply.png") .type(MonologFXButton.Type.YES) .build(); MonologFXButton btnNo = MonologFXButtonBuilder.create() .cancelButton(true) .icon("/testmonologfx/dialog_cancel.png") .type(MonologFXButton.Type.CANCEL) .build(); MonologFX mono = MonologFXBuilder.create() .titleText("Firmware Update Available") .message("There is a firmware update available for your TinyG Hardware. \n" + "\n Click Yes to start your firmware update.") .button(btnYes) .button(btnNo) .type(MonologFX.Type.ERROR) .build(); MonologFXButton.Type retval = mono.showDialog(); switch (retval) { case YES: // logger.info("Clicked Yes"); try { Main.postConsoleMessage("This is going to take about 30 seconds.... Please Wait... Watch the flashies...."); handleUpdateFirmware(new ActionEvent()); } catch (Exception ex) { Main.postConsoleMessage("Error in updating firmware."); } break; case CANCEL: // logger.info("Clicked No"); Main.postConsoleMessage("TinyG firmware update cancelled."); break; } } }); } else { Main.postConsoleMessage("Your " + TinygDriver.getInstance().machine.hardwarePlatform.getPlatformName() + "'s firmware is up to date...\n"); } } catch (MalformedURLException ex) { Logger.getLogger(FirmwareUpdaterController.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(FirmwareUpdaterController.class.getName()).log(Level.SEVERE, null, ex); } } }); } @Override public void initialize(URL url, ResourceBundle rb) { NumberExpression ne = new SimpleDoubleProperty(_currentVersionString.doubleValue()).subtract(TinygDriver.getInstance().machine.getFirmwareBuild()); hardwareId.textProperty().bind(TinygDriver.getInstance().machine.hardwareId); //Bind the tinyg hardware id to the tg driver value //hwVersion.textProperty().bind(TinygDriver.getInstance().machine.hardwareVersion); //Bind the tinyg version to the tg driver value hwVersion.textProperty().bind(TinygDriver.getInstance().machine.hardwareVersion); //Bind the tinyg version to the tg driver value firmwareVersion.textProperty().bind(TinygDriver.getInstance().machine.firmwareVersion); buildNumb.textProperty().bind(TinygDriver.getInstance().machine.firmwareBuild.asString()); } protected static void enterBootloaderMode() throws SerialPortException { if (TinygDriver.getInstance().isConnected().get()) { //We need to disconnect from tinyg after issuing out boot command. try { TinygDriver.getInstance().priorityWrite(CommandManager.CMD_APPLY_BOOTLOADER_MODE); //Set our board into bootloader mode. Thread.sleep(1000); } catch (Exception ex) { Logger.getLogger(FirmwareUpdaterController.class.getName()).log(Level.SEVERE, null, ex); } TinygDriver.getInstance().sendDisconnectRequest(); try { Thread.sleep(500); } catch (InterruptedException ex) { Logger.getLogger(FirmwareUpdaterController.class.getName()).log(Level.SEVERE, null, ex); } } } }