/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.cirqwizard.fx.services; import javafx.application.Platform; import javafx.beans.property.Property; import javafx.beans.property.SimpleStringProperty; import javafx.concurrent.Service; import javafx.concurrent.Task; import org.cirqwizard.fx.MainApplication; import org.cirqwizard.fx.util.ExceptionAlert; import org.cirqwizard.logging.LoggerFactory; import org.cirqwizard.serial.ExecutionException; import org.cirqwizard.serial.SerialException; import java.io.IOException; import java.io.LineNumberReader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; public class SerialInterfaceService extends Service { private MainApplication mainApplication; private List<String> programLines; private Property<String> executionTime = new SimpleStringProperty(""); private Property<String> responses = new SimpleStringProperty(""); private boolean readResponses; private boolean suppressExceptions; public SerialInterfaceService(MainApplication mainApplication) { this.mainApplication = mainApplication; } public void setProgram(String program) { setProgram(program, false, false); } public void setProgram(String program, boolean readResponses, boolean suppressExceptions) { this.readResponses = readResponses; this.suppressExceptions = suppressExceptions; programLines = new ArrayList<>(); LineNumberReader reader = new LineNumberReader(new StringReader(program)); String str; try { while ((str = reader.readLine()) != null) programLines.add(str); } catch (IOException e) { LoggerFactory.logException("Error reading a program from StringReader", e); } } public Property<String> executionTimeProperty() { return executionTime; } public Property<String> responsesProperty() { return responses; } @Override protected Task createTask() { return new SerialInterfaceTask(); } private String formatTime(long time) { return String.format("%02d:%02d:%02d", time / 3600, (time % 3600) / 60, time % 60); } public class SerialInterfaceTask extends Task { @Override protected Object call() throws Exception { try { final StringBuilder responseBuilder = new StringBuilder(); if (readResponses) Platform.runLater(() -> responses.setValue("")); long executionStartTime = System.currentTimeMillis(); for (int i = 0; i < programLines.size(); i++) { if (isCancelled()) throw new InterruptedException(); try { mainApplication.getSerialInterface().send(programLines.get(i), 20000000, responseBuilder, false); } catch (SerialException | ExecutionException e) { if (!suppressExceptions) throw e; } if (readResponses) Platform.runLater(() -> responses.setValue(responseBuilder.toString())); updateProgress(i, programLines.size()); final String s = formatTime((System.currentTimeMillis() - executionStartTime) / 1000); Platform.runLater(() -> executionTime.setValue(s)); } } catch (SerialException | ExecutionException e) { LoggerFactory.logException("Error communicating with the controller", e); mainApplication.getCNCController().interruptProgram(); ExceptionAlert alert = new ExceptionAlert("Oops! That's embarrassing!", "Communication error", "Something went wrong while communicating with the controller. " + "The most sensible thing to do now would be to close the program and start over again. Sorry about that.", e); alert.showAndWait(); } catch (InterruptedException e) { mainApplication.getCNCController().interruptProgram(); } return null; } } }