package com.willwinder.universalgcodesender; import org.apache.commons.lang3.StringUtils; import com.willwinder.universalgcodesender.types.Simulator; import java.io.*; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; /** * Created with IntelliJ IDEA. * User: MerrellM * Date: 2/17/14 * Time: 10:09 AM * To change this template use File | Settings | File Templates. */ public class GrblSimulator extends Simulator { public GrblSimulator() { } public GrblSimulator(Collection<String> configurationCommands) { super(configurationCommands); } protected Process getSimulatorProcess() throws IOException { ProcessBuilder pb = new ProcessBuilder("sim.exe", "1"); return pb.start(); } protected void sendCommands(Collection<String> commands, BufferedWriter simInputBuffer) throws IOException{ for (String command : commands) { simInputBuffer.write(command); simInputBuffer.newLine(); simInputBuffer.flush(); } } protected List<String> runSimulation(Collection<String> commands) throws IOException { BufferedWriter simInputBuffer = null; ProcessBuffer simOutputBuffer = null; Thread parserThread = null; try { Process simulation = getSimulatorProcess(); simInputBuffer = new BufferedWriter(new OutputStreamWriter(simulation.getOutputStream())); simOutputBuffer = new ProcessBuffer(simulation); parserThread = new Thread(simOutputBuffer); parserThread.start(); while (!simOutputBuffer.isReady()) { try { Thread.sleep(10); } catch (InterruptedException ioe) { parserThread.interrupt(); return null; } } sendCommands(configStrings, simInputBuffer); sendCommands(commands, simInputBuffer); simInputBuffer.close(); try { simulation.waitFor(); parserThread.join(); } catch (InterruptedException ie) { return null; } } finally { if (simInputBuffer != null) simInputBuffer.close(); if (parserThread.isAlive()) parserThread.interrupt(); } return simOutputBuffer.getErrLines(); } protected long parseResults(List<String> simOutput) { long result = 0; for (int i = simOutput.size() - 1; i >= 0; i--) { String line = simOutput.get(i).trim(); if (line.startsWith("#")) continue; int ci = line.indexOf(','); if (ci > 0) { String secondsString = line.substring(0, ci); Double seconds; try { seconds = Double.parseDouble(secondsString); } catch (Exception e) { continue; } result = StrictMath.round(seconds * 1000); break; } } return result; } @Override public long estimateRunLength(Collection<String> commands) { long result = 0; List<String> buffer = null; try { buffer = runSimulation(commands); } catch (Exception e) { e.printStackTrace(); } if (buffer != null) { result = parseResults(buffer); } return result; } public class ProcessBuffer implements Runnable { protected Process process; protected List<String> stderrList; protected List<String> stdoutList; protected List<String> outList; protected boolean ready; public boolean isReady() { return ready; } public ProcessBuffer(Process process) { this.process = process; } public List<String> getErrLines() { return getLines(stderrList); } public List<String> getStdLines() { return getLines(stdoutList); } public List<String> getAllLines() { return getLines(outList); } private List<String> getLines(List<String> list) { if (list == null) return null; int size = list.size(); List<String> result = new ArrayList<>(size); for (int i = 0; i < size; i++) { result.add(list.get(i)); } return result; } @Override public void run() { outList = new ArrayList<>(); List<String> syncList = Collections.synchronizedList(outList); stderrList = new ArrayList<>(); stdoutList = new ArrayList<>(); Thread errReader = new Thread(new Buffer(process.getErrorStream(), stderrList, syncList)); Thread stdReader = new Thread(new Buffer(process.getInputStream(), stdoutList, syncList)); stdReader.start(); errReader.start(); while (stdoutList.size() < 2 || ! StringUtils.join(getStdLines(), "").contains(" for help]")) { try { Thread.sleep(10); } catch (InterruptedException ioe) { process.destroy(); return; } } ready = true; try { stdReader.join(); errReader.join(); } catch (InterruptedException ie) { process.destroy(); return; } } } public class Buffer implements Runnable { private final BufferedReader reader; List<String> buffer; List<String> globalBuffer; public Buffer(InputStream in, List<String> buffer, List<String> globalBuffer) { reader = new BufferedReader(new InputStreamReader(in)); this.buffer = buffer; this.globalBuffer = globalBuffer; } @Override public void run() { buffer.clear(); String line; try { while ((line = reader.readLine()) != null) { buffer.add(line); globalBuffer.add(line); } } catch (IOException ioe) { return; } } } }