From ffe00e84fa66e2cce0e3c411fd70c282404d00c6 Mon Sep 17 00:00:00 2001 From: Dan Royer Date: Sun, 2 Jun 2024 16:17:53 -0700 Subject: [PATCH] More robust path searching --- pom.xml | 2 +- .../firmwareuploader/AVRDudeDownloader.java | 29 ++++++++-- .../firmwareuploader/FirmwareUploader.java | 55 +++++++++++++++---- .../FirmwareUploaderPanel.java | 30 +++++----- 4 files changed, 86 insertions(+), 30 deletions(-) diff --git a/pom.xml b/pom.xml index 19f519875..3966bf4a9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.marginallyclever Makelangelo - 7.55.4 + 7.55.5 Makelangelo Makelangelo Software is a Java program that prepares art for CNC plotters. It is especially designed for the Makelangelo Robot. It pairs really well with Marlin-polargraph, the code in the brain of the robot that receives instructions and moves the motors. diff --git a/src/main/java/com/marginallyclever/makelangelo/firmwareuploader/AVRDudeDownloader.java b/src/main/java/com/marginallyclever/makelangelo/firmwareuploader/AVRDudeDownloader.java index b498ef8ac..19cc34e63 100644 --- a/src/main/java/com/marginallyclever/makelangelo/firmwareuploader/AVRDudeDownloader.java +++ b/src/main/java/com/marginallyclever/makelangelo/firmwareuploader/AVRDudeDownloader.java @@ -36,10 +36,21 @@ public static void main(String[] args) throws IOException { } + /** + * Download AVRDude for the current OS architecture. + * @return the path to the extracted avrdude executable. + * @throws IOException if the download fails. + */ public static String downloadAVRDude() throws IOException { return downloadAVRDude(getArch()); } + /** + * Download AVRDude for the given OS architecture. + * @param arch one of WINDOWS, LINUX, MACOS + * @return the path to the extracted avrdude executable. + * @throws IOException if the download fails. + */ public static String downloadAVRDude(String arch) throws IOException { String url = getURLforOS(arch); if (url != null) { @@ -71,7 +82,6 @@ public static String getURLforOS(String arch) throws IOException { if (arduinoPackage != null) { JSONObject avrdudeTool = getLastToolNamedAVRDude(arduinoPackage); - if (avrdudeTool != null) { JSONObject system = getSystemForHost(avrdudeTool, arch); if (system != null) { @@ -82,9 +92,14 @@ public static String getURLforOS(String arch) throws IOException { return null; } - // search the systems list for the one where host contains "apple" - private static JSONObject getSystemForHost(JSONObject avrdudeTool, String arch) { - JSONArray systems = avrdudeTool.getJSONArray("systems"); + /** + * Search the systems list for the one where host contains the given architecture. + * @param jsonObject the avrdude tool object + * @param arch the architecture to search for + * @return the system object that matches the given architecture + */ + private static JSONObject getSystemForHost(JSONObject jsonObject, String arch) { + JSONArray systems = jsonObject.getJSONArray("systems"); for (int i = 0; i < systems.length(); i++) { JSONObject systemObject = systems.getJSONObject(i); if (systemObject.getString("host").contains(arch)) { @@ -94,7 +109,11 @@ private static JSONObject getSystemForHost(JSONObject avrdudeTool, String arch) return null; } - // find the arduinoPackage element with name=avrdude. last is latest release. + /** + * Search the arduinoPackage for element with name=avrdude. the last item is the latest release. + * @param arduinoPackage the package to search + * @return the last item in the tools list with name=avrdude + */ private static JSONObject getLastToolNamedAVRDude(JSONObject arduinoPackage) { JSONArray tools = arduinoPackage.getJSONArray("tools"); JSONObject avrdudeTool = null; diff --git a/src/main/java/com/marginallyclever/makelangelo/firmwareuploader/FirmwareUploader.java b/src/main/java/com/marginallyclever/makelangelo/firmwareuploader/FirmwareUploader.java index 638103f6a..605da85a9 100644 --- a/src/main/java/com/marginallyclever/makelangelo/firmwareuploader/FirmwareUploader.java +++ b/src/main/java/com/marginallyclever/makelangelo/firmwareuploader/FirmwareUploader.java @@ -7,29 +7,58 @@ import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Optional; /** * Common methods for uploading firmware to an AVR microcontroller. */ public class FirmwareUploader { private static final Logger logger = LoggerFactory.getLogger(FirmwareUploader.class); + private static final String CONF = "avrdude.conf"; + protected String installPath = ""; protected String avrdudePath = ""; protected String hexPath = ""; protected String confPath = ""; + protected FirmwareUploader() { super(); } + /** + * Search the tree starting at avrdudePath for the given filename. + * @param target the name of the file to find. + * @return the file if found, null otherwise. + */ + public File findFile(String target) { + logger.info("Searching for "+target+" starting in "+installPath); + Path startPath = Paths.get(installPath); + try { + Optional filePath = Files.walk(startPath) + .filter(path -> path.getFileName().toString().equals(target)) + .findFirst(); + return filePath.map(Path::toFile).orElse(null); + } catch (IOException e) { + logger.error("An error occurred while searching for the file: ", e); + return null; + } + } + + public boolean findAVRDude() { + String path = "avrdude"; + if( OSHelper.isWindows()) path+=".exe"; + File f = findFile(path); + if(!f.exists()) return false; + avrdudePath = f.getAbsolutePath(); + return true; + } + // find avrdude.conf public boolean findConf() { - logger.info("Searching for conf starting in "+avrdudePath); - int i=0; - File f = attemptToFindConf(i++, ".."+File.separator+"etc"+File.separator+"avrdude.conf"); - if(!f.exists()) f = attemptToFindConf(i++, "avrdude.conf"); - if(!f.exists()) f = attemptToFindConf(i++, ".."+File.separator+"avrdude.conf"); - if(!f.exists()) f = attemptToFindConf(i++, ".."+File.separator+".."+File.separator+"etc"+File.separator+"avrdude.conf"); + File f = findFile(CONF); if(!f.exists()) return false; confPath = f.getAbsolutePath(); return true; @@ -46,15 +75,13 @@ protected File attemptToFindConf(int i, String filename) { * @return 0 if successful. * @throws Exception if the process fails. */ - public int run(String portName) throws Exception { - logger.debug("update started"); + public int performUpdate(String portName) throws Exception { + logger.debug("uploading firmware..."); // setup avrdude command - String path = avrdudePath + "avrdude"; - if( OSHelper.isWindows()) path+=".exe"; String [] options = new String[] { - path, + avrdudePath, "-C"+confPath, "-v","-V", "-patmega2560", @@ -121,6 +148,12 @@ public void setHexPath(String s) { } public void setAVRDude(String avrDudePath) { + logger.debug("setting avrdude to {}",avrDudePath); avrdudePath = avrDudePath; } + + public void setInstallPath(String avrDudePath) { + logger.debug("setting install path to {}",avrDudePath); + installPath = avrDudePath; + } } diff --git a/src/main/java/com/marginallyclever/makelangelo/firmwareuploader/FirmwareUploaderPanel.java b/src/main/java/com/marginallyclever/makelangelo/firmwareuploader/FirmwareUploaderPanel.java index aea373b79..f99298dd8 100644 --- a/src/main/java/com/marginallyclever/makelangelo/firmwareuploader/FirmwareUploaderPanel.java +++ b/src/main/java/com/marginallyclever/makelangelo/firmwareuploader/FirmwareUploaderPanel.java @@ -25,13 +25,11 @@ public class FirmwareUploaderPanel extends JPanel { private final FirmwareDownloader firmwareDownloader = new FirmwareDownloader(); private final FirmwareUploader firmwareUploader = new FirmwareUploader(); private final SelectOneOfMany port = new SelectOneOfMany("port",Translator.get("Port")); - private final SelectButton refreshButton = new SelectButton("refresh","⟳"); - private final SelectButton startM5 = new SelectButton("startM5",Translator.get("FirmwareUploaderPanel.startM5")); + private final SelectButton startM5 = new SelectButton("startM5",Translator.get("FirmwareUploaderPanel.startM5")); private final SelectButton startHuge = new SelectButton("startHuge",Translator.get("FirmwareUploaderPanel.startHuge")); - private final SelectReadOnlyText help = new SelectReadOnlyText("help",Translator.get("FirmwareUploader.help")); - public FirmwareUploaderPanel() { + public FirmwareUploaderPanel() { super(new GridBagLayout()); this.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); @@ -39,7 +37,10 @@ public FirmwareUploaderPanel() { JPanel connectTo = new JPanel(new BorderLayout()); connectTo.add(port,BorderLayout.CENTER); - connectTo.add(refreshButton,BorderLayout.EAST); + + SelectButton refreshButton = new SelectButton("refresh", "⟳"); + refreshButton.addActionListener(e -> updateCOMPortList()); + connectTo.add(refreshButton,BorderLayout.EAST); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; @@ -48,7 +49,8 @@ public FirmwareUploaderPanel() { c.weightx=1; c.weighty=0; - add(help,c); + SelectReadOnlyText help = new SelectReadOnlyText("help", Translator.get("FirmwareUploader.help")); + add(help,c); c.gridy++; c.gridwidth=2; add(connectTo,c); @@ -61,7 +63,6 @@ public FirmwareUploaderPanel() { c.gridx++; add(startHuge,c); - refreshButton.addActionListener(e -> updateCOMPortList()); startM5.addActionListener(e -> run(e,"firmware-m5.hex")); startHuge.addActionListener(e -> run(e,"firmware-huge.hex")); } @@ -78,13 +79,11 @@ private String[] getListOfCOMPorts() { private void run(ActionEvent evt, String name) { String title = Translator.get("FirmwareUploaderPanel.status"); - String AVRDudePath=""; - logger.debug("maybe downloading avrdude..."); try { - AVRDudePath = AVRDudeDownloader.downloadAVRDude(); - firmwareUploader.setAVRDude(AVRDudePath); + String AVRDudePath = AVRDudeDownloader.downloadAVRDude(); + firmwareUploader.setInstallPath(AVRDudePath); } catch(Exception e) { JOptionPane.showMessageDialog(this,Translator.get("FirmwareUploaderPanel.avrdudeNotDownloaded"),title,JOptionPane.ERROR_MESSAGE); return; @@ -96,6 +95,12 @@ private void run(ActionEvent evt, String name) { return; } + logger.debug("finding avrdude file..."); + if(!firmwareUploader.findAVRDude()) { + JOptionPane.showMessageDialog(this,Translator.get("FirmwareUploaderPanel.avrdudeNotFound"),title,JOptionPane.ERROR_MESSAGE); + return; + } + logger.debug("finding conf file..."); if(!firmwareUploader.findConf()) { JOptionPane.showMessageDialog(this,Translator.get("FirmwareUploaderPanel.confNotFound"),title,JOptionPane.ERROR_MESSAGE); @@ -116,8 +121,7 @@ private void run(ActionEvent evt, String name) { int messageType = JOptionPane.PLAIN_MESSAGE; int result = 1; try { - logger.debug("uploading firmware..."); - result = firmwareUploader.run(port.getSelectedItem()); + result = firmwareUploader.performUpdate(port.getSelectedItem()); } catch (Exception e1) { logger.error("failed to run avrdude: ",e1); status = e1.getMessage();