Skip to content

Commit

Permalink
Added "stream finished" event for FluidNC (#2326)
Browse files Browse the repository at this point in the history
* Removed file name from file state event, it can be retrieved from the backend instead.
* Now sends the file stream complete event when a file has finished
* Activate verbose errors on fluidnc
* Added tests for alarm and error commands
* Load the current file from the backend instead of the file state event
  • Loading branch information
breiler committed Oct 3, 2023
1 parent 74bd85c commit 3cb05e4
Show file tree
Hide file tree
Showing 15 changed files with 251 additions and 75 deletions.
Expand Up @@ -1764,10 +1764,10 @@ public void UGSEvent(UGSEvent evt) {
fileModePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(Localization.getString("mainWindow.swing.fileLabel") + ": " + backend.getGcodeFile().getName()));
fileModePanel.setToolTipText(backend.getGcodeFile().getAbsolutePath());
processedGcodeFile = null;
gcodeFile = fileStateEvent.getFile();
gcodeFile = backend.getGcodeFile().getAbsolutePath();
break;
case FILE_LOADED:
processedGcodeFile = fileStateEvent.getFile();
processedGcodeFile = backend.getProcessedGcodeFile().getAbsolutePath();
if (commandTableScrollPane.isEnabled()) {
commandTable.clear();
}
Expand Down
Expand Up @@ -41,16 +41,13 @@ public class VisualizerPanel extends JPanel implements UGSEventListener {
private static final int FPS = 20; // animator's target frames per second

private final VisualizerCanvas canvas;

public VisualizerPanel() {
this(null);
}
private final BackendAPI backend;

public VisualizerPanel(BackendAPI backend) {
super(new BorderLayout());
if (backend != null) {
backend.addUGSEventListener(this);
}
this.backend = backend;
backend.addUGSEventListener(this);


// Create the OpenGL rendering canvas
this.canvas = new VisualizerCanvas();
Expand Down Expand Up @@ -81,11 +78,11 @@ public void UGSEvent(UGSEvent evt) {
FileStateEvent fileStateEvent = (FileStateEvent) evt;
switch (fileStateEvent.getFileState()) {
case FILE_LOADING:
setGcodeFile(fileStateEvent.getFile());
setGcodeFile(backend.getGcodeFile().getAbsolutePath());
break;

case FILE_LOADED:
setProcessedGcodeFile(fileStateEvent.getFile());
setProcessedGcodeFile(backend.getProcessedGcodeFile().getAbsolutePath());
break;

default:
Expand Down
Expand Up @@ -645,14 +645,14 @@ private void updateNumCommands() {
}

// No longer a listener event
protected void fileStreamComplete(String filename) {
protected void fileStreamComplete() {
String duration = Utils.formattedMillis(getSendDuration());
dispatchConsoleMessage(MessageType.INFO, String.format("%n**** Finished sending file in %s ****%n%n", duration));
if (streamStopWatch.isStarted()) {
streamStopWatch.stop();
}
isStreaming.set(false);
dispatchStreamComplete(filename);
dispatchStreamComplete();
}

@Override
Expand Down Expand Up @@ -691,8 +691,7 @@ public void checkStreamFinished() {
this.comm.numActiveCommands() == 0 &&
rowsRemaining() <= 0 &&
(state == ControllerState.CHECK || state == ControllerState.IDLE)) {
String streamName = "queued commands";
this.fileStreamComplete(streamName);
this.fileStreamComplete();
}
}

Expand Down Expand Up @@ -801,8 +800,8 @@ protected void dispatchConsoleMessage(MessageType type, String message) {
}
}

protected void dispatchStreamComplete(String filename) {
listeners.forEach(l -> l.streamComplete(filename));
protected void dispatchStreamComplete() {
listeners.forEach(l -> l.streamComplete());
}

protected void dispatchCommandSkipped(GcodeCommand command) {
Expand Down
Expand Up @@ -25,6 +25,7 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.universalgcodesender.IController;
import com.willwinder.universalgcodesender.IFileService;
import com.willwinder.universalgcodesender.StatusPollTimer;
import com.willwinder.universalgcodesender.Utils;
import com.willwinder.universalgcodesender.communicator.GrblCommunicator;
import com.willwinder.universalgcodesender.communicator.ICommunicator;
import com.willwinder.universalgcodesender.communicator.ICommunicatorListener;
Expand Down Expand Up @@ -597,6 +598,7 @@ private void queryControllerInformation() throws Exception {
String state = getParserStateCommand.getState().orElseThrow(() -> new ConnectionException("Could not get controller state"));
gcodeParser.addCommand(state);

sendAndWaitForCompletion(this, new SystemCommand("$verbose_errors=true"));
refreshFirmwareSettings();
FluidNCUtils.addCapabilities(capabilities, semanticVersion, firmwareSettings);
}
Expand Down Expand Up @@ -730,30 +732,22 @@ public void rawResponseListener(String response) {
messageService.dispatchMessage(MessageType.VERBOSE, response + "\n");
} else if (getActiveCommand().isPresent()) {
GcodeCommand command = getActiveCommand().get();
if (command instanceof FluidNCCommand) {
if (command.isDone()) {
activeCommands.removeFirst();
updateParserModalState(command);

listeners.forEach(l -> l.commandComplete(command));

if (command instanceof GetStatusCommand) {
messageService.dispatchMessage(MessageType.VERBOSE, command.getResponse() + "\n");
} else if (command instanceof SystemCommand) {
messageService.dispatchMessage(MessageType.VERBOSE, command.getResponse() + "\n");
} else {
messageService.dispatchMessage(MessageType.INFO, command.getResponse() + "\n");
}
}
} else {
if (response.startsWith("ok") || response.startsWith("error") || response.startsWith("alarm")) {
command.setDone(true);
if (command.isDone()) {
activeCommands.removeFirst();
updateParserModalState(command);

activeCommands.removeFirst();
listeners.forEach(l -> l.commandComplete(command));
listeners.forEach(l -> l.commandComplete(command));

if (command instanceof GetStatusCommand) {
messageService.dispatchMessage(MessageType.VERBOSE, command.getResponse() + "\n");
} else if (command instanceof SystemCommand) {
messageService.dispatchMessage(MessageType.VERBOSE, command.getResponse() + "\n");
} else {
messageService.dispatchMessage(MessageType.INFO, command.getResponse() + "\n");
}
}

checkStreamFinished();
} else if (FluidNCUtils.isWelcomeResponse(response)) {
messageService.dispatchMessage(MessageType.VERBOSE, response + "\n");
if (isInitialized) {
Expand All @@ -780,6 +774,25 @@ public void rawResponseListener(String response) {
}
}

private void checkStreamFinished() {
if (streamCommands != null &&
!communicator.areActiveCommands() &&
rowsRemaining() <= 0) {
fileStreamComplete();
}
}

private void fileStreamComplete() {
streamCommands = null;
String duration = Utils.formattedMillis(getSendDuration());
messageService.dispatchMessage(MessageType.INFO, String.format("%n**** Finished sending file in %s ****%n%n", duration));
if (streamStopWatch.isStarted()) {
streamStopWatch.stop();
}
ThreadHelper.invokeLater(() ->
listeners.forEach(ControllerListener::streamComplete));
}

@Override
public void commandSent(GcodeCommand command) {
command.setSent(true);
Expand Down
Expand Up @@ -37,7 +37,7 @@ public Map<Integer, String> getErrorCodes() {
Arrays.stream(StringUtils.split(getResponse(), "\n")).forEach(line -> {
Matcher matcher = alarmCodePattern.matcher(line);
if (matcher.find()) {
alarmCodes.put(Integer.parseInt(matcher.group(1)), matcher.group(2));
alarmCodes.put(Integer.parseInt(matcher.group(1)), matcher.group(2).trim());
}
});
return alarmCodes;
Expand Down
Expand Up @@ -37,7 +37,7 @@ public Map<Integer, String> getErrorCodes() {
Arrays.stream(StringUtils.split(getResponse(), "\n")).forEach(line -> {
Matcher matcher = errorCodePattern.matcher(line);
if (matcher.find()) {
errorCodes.put(Integer.parseInt(matcher.group(1)), matcher.group(2));
errorCodes.put(Integer.parseInt(matcher.group(1)), matcher.group(2).trim());
}
});
return errorCodes;
Expand Down
Expand Up @@ -52,7 +52,7 @@ public interface ControllerListener {
/**
* The file streaming has completed.
*/
void streamComplete(String filename);
void streamComplete();

/**
* If an alarm is received from the controller
Expand Down
Expand Up @@ -354,7 +354,7 @@ public void setGcodeFile(File file) throws Exception {
logger.log(Level.INFO, "Setting gcode file. {0}", file.getAbsolutePath());

this.gcodeFile = file;
eventDispatcher.sendUGSEvent(new FileStateEvent(FileState.OPENING_FILE, file.getAbsolutePath()));
eventDispatcher.sendUGSEvent(new FileStateEvent(FileState.OPENING_FILE));
processGcodeFile();
}

Expand All @@ -364,7 +364,7 @@ public void unsetGcodeFile() throws Exception {
gcodeStream.close();
}
if (this.processedGcodeFile != null) {
eventDispatcher.sendUGSEvent(new FileStateEvent(FileState.FILE_UNLOADED, null));
eventDispatcher.sendUGSEvent(new FileStateEvent(FileState.FILE_UNLOADED));
}

initGcodeParser();
Expand All @@ -375,20 +375,16 @@ public void unsetGcodeFile() throws Exception {
@Override
public void reloadGcodeFile() throws Exception {
logger.log(Level.INFO, "Reloading gcode file.");
eventDispatcher.sendUGSEvent(new FileStateEvent(FileState.OPENING_FILE, gcodeFile.getAbsolutePath()));
eventDispatcher.sendUGSEvent(new FileStateEvent(FileState.OPENING_FILE));
processGcodeFile();
}

private void processGcodeFile() throws Exception {
this.processedGcodeFile = null;

eventDispatcher.sendUGSEvent(new FileStateEvent(FileState.FILE_LOADING,
this.gcodeFile.getAbsolutePath()));

eventDispatcher.sendUGSEvent(new FileStateEvent(FileState.FILE_LOADING));
initializeProcessedLines(true, this.gcodeFile, this.gcp);

eventDispatcher.sendUGSEvent(new FileStateEvent(FileState.FILE_LOADED,
processedGcodeFile.getAbsolutePath()));
eventDispatcher.sendUGSEvent(new FileStateEvent(FileState.FILE_LOADED));
}

@Override
Expand Down
Expand Up @@ -106,9 +106,9 @@ public void streamResumed() {
}

@Override
public void streamComplete(String filename) {
public void streamComplete() {
sendUGSEvent(new StreamEvent(StreamEventType.STREAM_COMPLETE));
sendUGSEvent(new FileStateEvent(FileState.FILE_STREAM_COMPLETE, filename));
sendUGSEvent(new FileStateEvent(FileState.FILE_STREAM_COMPLETE));
}

@Override
Expand Down
@@ -1,5 +1,5 @@
/*
Copyright 2021 Will Winder
Copyright 2021-2023 Will Winder
This file is part of Universal Gcode Sender (UGS).
Expand All @@ -26,27 +26,20 @@ This file is part of Universal Gcode Sender (UGS).
*/
public class FileStateEvent implements UGSEvent {
private final FileState fileState;
private final String file;

/**
* Create a file state event
* FILE_LOADING: This event provides a path to an unprocessed gcode file.
* FILE_LOADED: This event provides a path to a processed gcode file which
* should be opened with a GcodeStreamReader.
*
* @param state the new file state.
* @param filepath the file related to the file event.
* @param state the new file state.
*/
public FileStateEvent(FileState state, String filepath) {
public FileStateEvent(FileState state) {
this.fileState = state;
this.file = filepath;
}

public FileState getFileState() {
return fileState;
}

public String getFile() {
return file;
}
}
Expand Up @@ -26,11 +26,7 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.universalgcodesender.gcode.ICommandCreator;
import com.willwinder.universalgcodesender.listeners.ControllerListener;
import com.willwinder.universalgcodesender.listeners.ControllerState;
import com.willwinder.universalgcodesender.listeners.ControllerStatus;
import com.willwinder.universalgcodesender.model.Position;
import com.willwinder.universalgcodesender.model.UnitUtils;
import com.willwinder.universalgcodesender.services.MessageService;
import com.willwinder.universalgcodesender.types.GcodeCommand;
import com.willwinder.universalgcodesender.utils.GcodeStreamTest;
import com.willwinder.universalgcodesender.utils.IGcodeStreamReader;
import com.willwinder.universalgcodesender.utils.Settings;
Expand All @@ -48,7 +44,6 @@ This file is part of Universal Gcode Sender (UGS).

import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
*
Expand Down

0 comments on commit 3cb05e4

Please sign in to comment.