diff --git a/app/src/cc/arduino/packages/Uploader.java b/app/src/cc/arduino/packages/Uploader.java index b03ca3d41..81e5cc234 100644 --- a/app/src/cc/arduino/packages/Uploader.java +++ b/app/src/cc/arduino/packages/Uploader.java @@ -26,24 +26,60 @@ package cc.arduino.packages; -import static processing.app.I18n._; - -import java.util.Collection; - import processing.app.I18n; import processing.app.Preferences; import processing.app.debug.MessageConsumer; import processing.app.debug.MessageSiphon; import processing.app.debug.RunnerException; -public abstract class Uploader implements MessageConsumer { +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; - private String error = null; +import static processing.app.I18n._; - protected boolean verbose = Preferences.getBoolean("upload.verbose"); +public abstract class Uploader implements MessageConsumer { - public abstract boolean uploadUsingPreferences(String buildPath, String className, boolean usingProgrammer) - throws RunnerException; + private static final List STRINGS_TO_SUPPRESS; + private static final List AVRDUDE_PROBLEMS; + + static { + STRINGS_TO_SUPPRESS = Arrays.asList("Connecting to programmer:", + "Found programmer: Id = \"CATERIN\"; type = S", + "Software Version = 1.0; No Hardware Version given.", + "Programmer supports auto addr increment.", + "Programmer supports buffered memory access with buffersize=128 bytes.", + "Programmer supports the following devices:", "Device code: 0x44"); + + AVRDUDE_PROBLEMS = Arrays.asList("Programmer is not responding", + "programmer is not responding", + "protocol error", "avrdude: ser_open(): can't open device", + "avrdude: ser_drain(): read error", + "avrdude: ser_send(): write error", + "avrdude: error: buffered memory access not supported."); + } + + private static boolean stringContainsOneOf(String input, List listOfStrings) { + for (String string : listOfStrings) { + if (input.contains(string)) { + return true; + } + } + return false; + } + + private String error; + protected boolean verbose; + protected boolean notFoundError; + + protected Uploader() { + this.error = null; + this.verbose = Preferences.getBoolean("upload.verbose"); + this.notFoundError = false; + } + + public abstract boolean uploadUsingPreferences(File sourcePath, String buildPath, String className, boolean usingProgrammer) throws RunnerException; public abstract boolean burnBootloader() throws RunnerException; @@ -55,13 +91,11 @@ public abstract class Uploader implements MessageConsumer { return null; } - protected boolean executeUploadCommand(Collection command) - throws RunnerException { + protected boolean executeUploadCommand(Collection command) throws RunnerException { return executeUploadCommand(command.toArray(new String[0])); } - protected boolean executeUploadCommand(String command[]) - throws RunnerException { + protected boolean executeUploadCommand(String command[]) throws RunnerException { notFoundError = false; int result = -1; @@ -80,29 +114,21 @@ public abstract class Uploader implements MessageConsumer { } catch (Exception e) { e.printStackTrace(); } - + if (error != null) { RunnerException exception = new RunnerException(error); exception.hideStackTrace(); throw exception; } - return result == 0; + return result == 0; } - boolean notFoundError; - public void message(String s) { // selectively suppress a bunch of avrdude output for AVR109/Caterina that should already be quelled but isn't - if (!verbose && ( - s.indexOf("Connecting to programmer:") != -1 || - s.indexOf("Found programmer: Id = \"CATERIN\"; type = S") != -1 || - s.indexOf("Software Version = 1.0; No Hardware Version given.") != -1 || - s.indexOf("Programmer supports auto addr increment.") != -1 || - s.indexOf("Programmer supports buffered memory access with buffersize=128 bytes.") != -1 || - s.indexOf("Programmer supports the following devices:") != -1 || - s.indexOf("Device code: 0x44") != -1)) + if (!verbose && stringContainsOneOf(s, STRINGS_TO_SUPPRESS)) { s = ""; + } System.err.print(s); @@ -119,13 +145,7 @@ public abstract class Uploader implements MessageConsumer { error = _("Device is not responding, check the right serial port is selected or RESET the board right before exporting"); return; } - if (s.contains("Programmer is not responding") || - s.contains("programmer is not responding") || - s.contains("protocol error") || - s.contains("avrdude: ser_open(): can't open device") || - s.contains("avrdude: ser_drain(): read error") || - s.contains("avrdude: ser_send(): write error") || - s.contains("avrdude: error: buffered memory access not supported.")) { + if (stringContainsOneOf(s, AVRDUDE_PROBLEMS)) { error = _("Problem uploading to board. See http://www.arduino.cc/en/Guide/Troubleshooting#upload for suggestions."); return; } diff --git a/app/src/cc/arduino/packages/uploaders/SSHUploader.java b/app/src/cc/arduino/packages/uploaders/SSHUploader.java index 974a08645..ca4732d3d 100644 --- a/app/src/cc/arduino/packages/uploaders/SSHUploader.java +++ b/app/src/cc/arduino/packages/uploaders/SSHUploader.java @@ -36,7 +36,7 @@ public class SSHUploader extends Uploader { } @Override - public boolean uploadUsingPreferences(String buildPath, String className, boolean usingProgrammer) throws RunnerException { + public boolean uploadUsingPreferences(File sourcePath, String buildPath, String className, boolean usingProgrammer) throws RunnerException { if (usingProgrammer) { System.err.println(_("Http upload using programmer not supported")); return false; @@ -51,7 +51,8 @@ public class SSHUploader extends Uploader { session.setUserInfo(new NetworkMonitor.NoInteractionUserInfo()); session.connect(30000); - String uploadedSketchFile = new SCP(session).scpHexToBoard(buildPath, className); + SCP scp = new SCP(session); + String uploadedSketchFile = scp.scpHexToBoard(buildPath, className); TargetPlatform targetPlatform = Base.getTargetPlatform(); PreferencesMap prefs = Preferences.getMap(); @@ -127,16 +128,9 @@ public class SSHUploader extends Uploader { protected int consumeOutputSyncAndReturnExitCode(Channel channel, InputStream stdout, InputStream stderr) throws IOException { byte[] tmp = new byte[102400]; while (true) { - while (stdout.available() > 0) { - int i = stdout.read(tmp, 0, tmp.length); - if (i < 0) break; - System.out.print(new String(tmp, 0, i)); - } - while (stderr != null && stderr.available() > 0) { - int i = stderr.read(tmp, 0, tmp.length); - if (i < 0) break; - System.err.print(new String(tmp, 0, i)); - } + consumeStream(tmp, stdout, System.out); + consumeStream(tmp, stderr, System.err); + if (channel.isClosed()) { return channel.getExitStatus(); } @@ -148,6 +142,16 @@ public class SSHUploader extends Uploader { } } + private void consumeStream(byte[] buffer, InputStream in, PrintStream out) throws IOException { + while (in != null && in.available() > 0) { + int length = in.read(buffer, 0, buffer.length); + if (length < 0) { + break; + } + out.print(new String(buffer, 0, length)); + } + } + } private static class SSHAVRDude extends SSH { @@ -173,13 +177,13 @@ public class SSHUploader extends Uploader { super(session); } - public String scpHexToBoard(String buildPath, String className) throws JSchException, IOException { + public void scpFile(File from, String absolutePathToDestination) throws JSchException, IOException { Channel channel = null; OutputStream out = null; InputStream in = null; try { channel = session.openChannel("exec"); - ((ChannelExec) channel).setCommand("scp -t " + SKETCH_FILE); + ((ChannelExec) channel).setCommand("scp -t " + absolutePathToDestination); out = channel.getOutputStream(); in = channel.getInputStream(); @@ -188,15 +192,11 @@ public class SSHUploader extends Uploader { ensureAcknowledged(out, in); - File hex = new File(buildPath, className + ".hex"); - - sendFileSizeAndName(out, in, hex); + sendFileSizeAndName(out, in, from); ensureAcknowledged(out, in); - sendFileContents(out, hex); + sendFileContents(out, from); ensureAcknowledged(out, in); - - return SKETCH_FILE; } finally { if (out != null) { out.close(); @@ -210,6 +210,11 @@ public class SSHUploader extends Uploader { } } + public String scpHexToBoard(String buildPath, String className) throws JSchException, IOException { + scpFile(new File(buildPath, className + ".hex"), SKETCH_FILE); + return SKETCH_FILE; + } + private void ensureAcknowledged(OutputStream out, InputStream in) throws IOException { out.flush(); diff --git a/app/src/cc/arduino/packages/uploaders/SerialUploader.java b/app/src/cc/arduino/packages/uploaders/SerialUploader.java index 236ce2bb6..2bd8af49a 100644 --- a/app/src/cc/arduino/packages/uploaders/SerialUploader.java +++ b/app/src/cc/arduino/packages/uploaders/SerialUploader.java @@ -30,6 +30,7 @@ package cc.arduino.packages.uploaders; import static processing.app.I18n._; +import java.io.File; import java.util.ArrayList; import java.util.List; @@ -47,9 +48,7 @@ import processing.app.helpers.StringReplacer; public class SerialUploader extends Uploader { - public boolean uploadUsingPreferences(String buildPath, String className, - boolean usingProgrammer) - throws RunnerException { + public boolean uploadUsingPreferences(File sourcePath, String buildPath, String className, boolean usingProgrammer) throws RunnerException { // FIXME: Preferences should be reorganized TargetPlatform targetPlatform = Base.getTargetPlatform(); PreferencesMap prefs = Preferences.getMap(); @@ -61,7 +60,7 @@ public class SerialUploader extends Uploader { if (usingProgrammer || prefs.get("upload.protocol") == null) { return uploadUsingProgrammer(buildPath, className); } - + // need to do a little dance for Leonardo and derivatives: // open then close the port at the magic baudrate (usually 1200 bps) first // to signal to the sketch that it should reset into bootloader. after doing @@ -70,10 +69,10 @@ public class SerialUploader extends Uploader { // sketch. String t = prefs.get("upload.use_1200bps_touch"); boolean doTouch = t != null && t.equals("true"); - + t = prefs.get("upload.wait_for_upload_port"); boolean waitForUploadPort = (t != null) && t.equals("true"); - + if (doTouch) { String uploadPort = prefs.get("serial.port"); try { @@ -93,7 +92,7 @@ public class SerialUploader extends Uploader { // have already occured before we start scanning. if (!Base.isMacOS()) Thread.sleep(300); - + uploadPort = waitForUploadPort(uploadPort, before); } else { Thread.sleep(400); @@ -109,7 +108,7 @@ public class SerialUploader extends Uploader { else prefs.put("serial.port.file", uploadPort); } - + prefs.put("build.path", buildPath); prefs.put("build.project_name", className); if (verbose) @@ -130,7 +129,7 @@ public class SerialUploader extends Uploader { } catch (Exception e) { throw new RunnerException(e); } - + // Remove the magic baud rate (1200bps) to avoid // future unwanted board resets try { @@ -212,7 +211,7 @@ public class SerialUploader extends Uploader { return uploadPort; } } - + // Something happened while detecting port throw new RunnerException( _("Couldn't find a Board on the selected port. Check that you have the correct port selected. If it is correct, try pressing the board's reset button after initiating the upload.")); @@ -256,10 +255,10 @@ public class SerialUploader extends Uploader { throw new RunnerException(e); } } - + public boolean burnBootloader() throws RunnerException { TargetPlatform targetPlatform = Base.getTargetPlatform(); - + // Find preferences for the selected programmer PreferencesMap programmerPrefs; String programmer = Preferences.get("programmer"); @@ -272,12 +271,12 @@ public class SerialUploader extends Uploader { } else { programmerPrefs = targetPlatform.getProgrammer(programmer); } - + // Build configuration for the current programmer PreferencesMap prefs = Preferences.getMap(); prefs.putAll(Base.getBoardPreferences()); prefs.putAll(programmerPrefs); - + // Create configuration for bootloader tool PreferencesMap toolPrefs = new PreferencesMap(); String tool = prefs.get("bootloader.tool"); @@ -295,7 +294,7 @@ public class SerialUploader extends Uploader { if (toolPrefs.size() == 0) throw new RunnerException(I18n.format(_("Could not find tool {0}"), tool)); - + // Merge tool with global configuration prefs.putAll(toolPrefs); if (verbose) { @@ -305,7 +304,7 @@ public class SerialUploader extends Uploader { prefs.put("erase.verbose", prefs.get("erase.params.quiet")); prefs.put("bootloader.verbose", prefs.get("bootloader.params.quiet")); } - + try { String pattern = prefs.get("erase.pattern"); String[] cmd = StringReplacer.formatAndSplit(pattern, prefs, true); diff --git a/app/src/processing/app/Sketch.java b/app/src/processing/app/Sketch.java index 5c5a7117e..b4911b92a 100644 --- a/app/src/processing/app/Sketch.java +++ b/app/src/processing/app/Sketch.java @@ -1684,7 +1684,7 @@ public class Sketch { } try { - success = uploader.uploadUsingPreferences(buildPath, suggestedClassName, usingProgrammer); + success = uploader.uploadUsingPreferences(getFolder(), buildPath, suggestedClassName, usingProgrammer); } finally { if (uploader.requiresAuthorization() && !success) { Preferences.remove(uploader.getAuthorizationKey());