package org.myrobotlab.arduino; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Map; import org.myrobotlab.io.FileIO; import org.myrobotlab.logging.LoggerFactory; import org.myrobotlab.service.Arduino; import org.slf4j.Logger; import com.sun.jna.Platform; public class ArduinoUtils { public transient final static Logger log = LoggerFactory.getLogger(ArduinoUtils.class); // TODO: auto-discover? public static String arduinoPath = "c:\\dev\\arduino-1.6.8\\"; // TODO: fix this. a temp directory so we can upload the mrlcomm properly. public static StringBuilder outputBuilder; // not needed ? private static String commandPath = ""; private static String additionalEnv = ""; public static int exitValue; static public String getExeName() { if (Platform.isMac()) { return "Arduino"; } return "arduino_debug"; } public static boolean uploadSketch(String port, String board) throws IOException, InterruptedException { if (!(board.equalsIgnoreCase("uno") || board.equalsIgnoreCase("mega") || board.equalsIgnoreCase("megaADK"))) { // TODO: validate the proper set of values. System.out.println(String.format("Invalid board type:%s", board)); exitValue = 1; return false; } // Assume this is mrlcomm resource! // G-say: FIXME - this will ONLY work in eclipse !!! - should extract it // from /resource //not working FileIO.extractResources(); String sketchFilename = "resource/Arduino/MRLComm/MRLComm.ino"; File sketch = new File(sketchFilename); if (!sketch.exists()){ sketchFilename = "src/resource/Arduino/MRLComm/MRLComm.ino"; sketch = new File(sketchFilename); } // Create the command to run (and it's args.) String arduinoExe = arduinoPath + getExeName(); ArrayList<String> args = new ArrayList<String>(); args.add("--upload"); args.add("--port"); args.add(port); args.add("--board"); args.add("arduino:avr:" + board); args.add(sketch.getAbsolutePath()); // args.add("--verbose-upload"); //args.add("--preserve-temp-files"); // run the command. String result = runCommand(arduinoExe, args); // print stdout/err from running the command log.info("Result..." + result); log.info("Uploaded Sketch."); // take a breath... We think it probably worked? but not sure.. Thread.sleep(2000); // G-says : the following does not return correctly // if it correctly compiles but fails to upload if (result.trim().endsWith(" bytes.")) { return true; } else { return false; } } /** * Helper function to run a system command and return the stdout / stderr as * a string * * @param program * @param args * @return * @throws IOException * @throws InterruptedException */ protected static String runCommand(String program, ArrayList<String> args) throws InterruptedException { ArrayList<String> command = new ArrayList<String>(); command.add(program); if (args != null) { for (String arg : args) { command.add(arg); } } System.out.println("RUNNING COMMAND :" + join(command, " ")); ProcessBuilder builder = new ProcessBuilder(command); // we need to specify environment variables Map<String, String> environment = builder.environment(); String ldLibPath = commandPath; if (additionalEnv.length() > 0) { ldLibPath += ":" + additionalEnv; } environment.put("LD_LIBRARY_PATH", ldLibPath); try { Process handle = builder.start(); InputStream stdErr = handle.getErrorStream(); InputStream stdOut = handle.getInputStream(); // TODO: we likely don't need this // OutputStream stdIn = handle.getOutputStream(); outputBuilder = new StringBuilder(); byte[] buff = new byte[4096]; // TODO: should we read both of these streams? // if we break out of the first loop is the process terminated? // read stderr for (int n; (n = stdErr.read(buff)) != -1;) { outputBuilder.append(new String(buff, 0, n)); } // read stdout for (int n; (n = stdOut.read(buff)) != -1;) { outputBuilder.append(new String(buff, 0, n)); } stdOut.close(); stdErr.close(); // TODO: stdin if we use it. // stdIn.close(); // the process should be closed by now? handle.waitFor(); handle.destroy(); exitValue = handle.exitValue(); // print the output from the command System.out.println(outputBuilder.toString()); System.out.println("Exit Value : " + exitValue); outputBuilder.append("Exit Value : " + exitValue); return outputBuilder.toString(); } catch (IOException e) { exitValue = 5; return e.getMessage(); // throw e; } } /** * Helper function to run a program , return the stderr / stdout as a string * and to catch any exceptions that occur * * @param cmd * @param args * @return */ protected String RunAndCatch(String cmd, ArrayList<String> args) { String returnValue; try { returnValue = runCommand(cmd, args); // } // catch (IOException e) { // // TODO Auto-generated catch block // returnValue = e.getMessage(); // e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block returnValue = e.getMessage(); e.printStackTrace(); } return returnValue; } // TODO: this should be on a string utils static class. private static String join(ArrayList<String> list, String joinChar) { StringBuilder sb = new StringBuilder(); int i = 0; int size = list.size(); for (String part : list) { i++; sb.append(part); if (i != size) { sb.append(joinChar); } } return sb.toString(); } public static String getOutput() { return outputBuilder.toString(); } }