Package com.willwinder.universalgcodesender

Source Code of com.willwinder.universalgcodesender.GrblController

/*
* GRBL Control layer, coordinates all aspects of control.
*/
/*
    Copywrite 2013 Will Winder

    This file is part of Universal Gcode Sender (UGS).

    UGS is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    UGS 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 UGS.  If not, see <http://www.gnu.org/licenses/>.
*/
package com.willwinder.universalgcodesender;

import com.willwinder.universalgcodesender.gcode.GcodeCommandCreator;
import com.willwinder.universalgcodesender.i18n.Localization;
import com.willwinder.universalgcodesender.listeners.GrblSettingsListener;
import com.willwinder.universalgcodesender.types.GcodeCommand;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Timer;
import javax.vecmath.Point3d;

/**
*
* @author wwinder
*/
public class GrblController extends AbstractController {
    // Grbl state
    private double grblVersion = 0.0;        // The 0.8 in 'Grbl 0.8c'
    private String grblVersionLetter = null; // The c in 'Grbl 0.8c'
    private Boolean isReady = false;         // Not ready until version is received.
    private GrblSettingsListener settings;

    // Grbl status members.
    private GrblUtils.Capabilities positionMode = null;
    private Boolean realTimeCapable = false;
    private String grblState;
    private Point3d machineLocation;
    private Point3d workLocation;
    private double maxZLocation;
   
    // Polling state
    private int outstandingPolls = 0;
    private Timer positionPollTimer = null
   
    protected GrblController(AbstractCommunicator comm) {
        super(comm);
       
        this.commandCreator = new GcodeCommandCreator();
        this.positionPollTimer = createPositionPollTimer();
        this.maxZLocation = -1;
        this.settings = new GrblSettingsListener(this);
    }
   
    public GrblController() {
        this(new GrblCommunicator()); //f4grx: connection created at opencomm() time
    }

    @Override
    public long getJobLengthEstimate(Collection<String> jobLines) {
        // Pending update to support cross-platform and multiple GRBL versions.
        return 0;
        //GrblSimulator simulator = new GrblSimulator(settings.getSettings());
        //return simulator.estimateRunLength(jobLines);
    }

    /***********************
     * API Implementation.
     ***********************
     */
   
    @Override
    protected void rawResponseHandler(String response) {
        /*
        // Check if was 'ok' or 'error'.
        if (GcodeCommand.isOkErrorResponse(response)) {
           
            // All Ok/Error messages go to console
            this.sendMessageToConsoleListener(response + "\n");

            // Pop the front of the active list.
            GcodeCommand command = this.activeCommandList.pop();

            command.setResponse(response);

            ListenerUtils.dispatchListenerEvents(ListenerUtils.COMMAND_COMPLETE,
                    this.commandCompleteListeners, command);

            if (this.sendPaused == false) {
                this.streamCommands();
            }
        }
        */
       
        if (GcodeCommand.isOkErrorResponse(response)) {           
            try {
                this.commandComplete(response);
            } catch (Exception e) {
                this.errorMessageForConsole(Localization.getString("controller.error.response")
                        + " <" + response + ">: " + e.getMessage());
            }
           
            this.messageForConsole(response + "\n");
        }
       
        else if (GrblUtils.isGrblVersionString(response)) {
            // Version string goes to console
            this.messageForConsole(response + "\n");
           
            this.grblVersion = GrblUtils.getVersionDouble(response);
            this.grblVersionLetter = GrblUtils.getVersionLetter(response);
            this.isReady = true;
           
            this.realTimeCapable = GrblUtils.isRealTimeCapable(this.grblVersion);
           
            this.positionMode = GrblUtils.getGrblStatusCapabilities(this.grblVersion, this.grblVersionLetter);
            this.beginPollingPosition();
           
            Logger.getLogger(GrblController.class.getName()).log(Level.CONFIG,
                    "{0} = {1}{2}", new Object[]{Localization.getString("controller.log.version"), this.grblVersion, this.grblVersionLetter});
            Logger.getLogger(GrblController.class.getName()).log(Level.CONFIG,
                    "{0} = {1}", new Object[]{Localization.getString("controller.log.realtime"), this.realTimeCapable});
        }
       
        else if (GrblUtils.isGrblStatusString(response)) {
            // Only 1 poll is sent at a time so don't decrement, reset to zero.
            this.outstandingPolls = 0;

            // Status string goes to verbose console
            verboseMessageForConsole(response + "\n");
           
            this.handlePositionString(response);
        }
       
        else {
            // Display any unhandled messages
            this.messageForConsole(response + "\n");
        }
    }
    @Override
    protected void pauseStreamingEvent() throws IOException {
        if (this.realTimeCapable) {
            this.comm.sendByteImmediately(GrblUtils.GRBL_PAUSE_COMMAND);
        }
    }
   
    @Override
    protected void resumeStreamingEvent() throws IOException {
        if (this.realTimeCapable) {
            this.comm.sendByteImmediately(GrblUtils.GRBL_RESUME_COMMAND);
        }
    }
   
    @Override
    protected void closeCommBeforeEvent() {
        this.stopPollingPosition();
    }
   
    @Override
    protected void closeCommAfterEvent() {
        this.grblVersion = 0.0;
        this.grblVersionLetter = null;
    }
   
    @Override
    protected void openCommAfterEvent() throws IOException {
        this.comm.sendByteImmediately(GrblUtils.GRBL_RESET_COMMAND);
    }

    @Override
    protected void isReadyToStreamFileEvent() throws Exception {
        if (this.isReady == false) {
            throw new Exception(Localization.getString("controller.exception.booting"));
        }
    }
   
    @Override
    protected void cancelSendBeforeEvent() {
        // Check if we can get fancy with a soft reset.
        if (this.realTimeCapable == true) {
            // This doesn't seem to work.
            /*
            try {
                if (!this.paused) {
                    this.pauseStreaming();
                }
                this.issueSoftReset();
                this.awaitingResponseQueue.clear();
            } catch (IOException e) {
                // Oh well, was worth a shot.
                System.out.println("Exception while trying to issue a soft reset: " + e.getMessage());
            }
            */
        }
    }
   
    @Override
    protected void cancelSendAfterEvent() {
    }
   
    /**
     * Sends the version specific homing cycle to the machine.
     */
    @Override
    public void performHomingCycle() throws Exception {
        if (this.isCommOpen()) {
            String command = GrblUtils.getHomingCommand(this.grblVersion, this.grblVersionLetter);
            if (!"".equals(command)) {
                this.queueStringForComm(command);
                return;
            }
        }
        // Throw exception
        super.performHomingCycle();
    }
   
    @Override
    public void resetCoordinatesToZero() throws Exception {
        if (this.isCommOpen()) {
            String command = GrblUtils.getResetCoordsToZeroCommand(this.grblVersion, this.grblVersionLetter);
            if (!"".equals(command)) {
                this.queueStringForComm(command);
                return;
            }
        }
        // Throw exception
        super.resetCoordinatesToZero();
    }
   
    @Override
    public void resetCoordinateToZero(final char coord) throws Exception {
        if (this.isCommOpen()) {
            String command = GrblUtils.getResetCoordToZeroCommand(coord, this.grblVersion, this.grblVersionLetter);
            if (!"".equals(command)) {
                this.queueStringForComm(command);
                return;
            }
        }
        // Throw exception
        super.resetCoordinatesToZero();
    }
   
    @Override
    public void returnToHome() throws Exception {
        if (this.isCommOpen()) {
            double max = 4;
            if (this.maxZLocation != -1) {
                max = this.maxZLocation;
            }
            ArrayList<String> commands = GrblUtils.getReturnToHomeCommands(this.grblVersion, this.grblVersionLetter, max);
            if (!commands.isEmpty()) {
                Iterator<String> iter = commands.iterator();
                // Perform the homing commands
                while(iter.hasNext()){
                    String command = iter.next();
                    this.queueStringForComm(command);
                }
                return;
            }
        }
        // Throw exception
        super.returnToHome();
    }
   
    @Override
    public void killAlarmLock() throws Exception {
        if (this.isCommOpen()) {
            String command = GrblUtils.getKillAlarmLockCommand(this.grblVersion, this.grblVersionLetter);
            if (!"".equals(command)) {
                this.queueStringForComm(command);
                return;
            }
        }
        // Throw exception
        super.killAlarmLock();
    }

    @Override
    public void toggleCheckMode() throws Exception {
        if (this.isCommOpen()) {
            String command = GrblUtils.getToggleCheckModeCommand(this.grblVersion, this.grblVersionLetter);
            if (!"".equals(command)) {
                this.queueStringForComm(command);
                return;
            }
        }
        // Throw exception
        super.toggleCheckMode();
    }

    @Override
    public void viewParserState() throws Exception {
        if (this.isCommOpen()) {
            String command = GrblUtils.getViewParserStateCommand(this.grblVersion, this.grblVersionLetter);
            if (!"".equals(command)) {
                this.queueStringForComm(command);
                return;
            }
        }
        // Throw exception
        super.viewParserState();
    }
   
    /**
     * If it is supported, a soft reset real-time command will be issued.
     */
    @Override
    public void softReset() throws IOException {
        if (this.isCommOpen() && this.realTimeCapable) {
            this.comm.sendByteImmediately(GrblUtils.GRBL_RESET_COMMAND);
            //Does GRBL need more time to handle the reset?
            this.comm.softReset();
        }
    }
       
    /************
     * Helpers.
     ************
     */
    public String getGrblVersion() {
        if (this.isCommOpen()) {
            StringBuilder str = new StringBuilder();
            str.append("Grbl ");
            if (this.grblVersion > 0.0) {
                str.append(this.grblVersion);
            }
            if (this.grblVersionLetter != null) {
                str.append(this.grblVersionLetter);
            }
           
            if (this.grblVersion <= 0.0 && this.grblVersionLetter == null) {
                str.append("<" + Localization.getString("unknown") + ">");
            }
           
            return str.toString();
        }
        return "<" + Localization.getString("controller.log.notconnected") + ">";
    }

    /**
     * Create a timer which will execute GRBL's position polling mechanism.
     */
    private Timer createPositionPollTimer() {
        // Action Listener for GRBL's polling mechanism.
        ActionListener actionListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                java.awt.EventQueue.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            if (outstandingPolls == 0) {
                                outstandingPolls++;
                                comm.sendByteImmediately(GrblUtils.GRBL_STATUS_COMMAND);
                            } else {
                                // If a poll is somehow lost after 20 intervals,
                                // reset for sending another.
                                outstandingPolls++;
                                if (outstandingPolls >= 20) {
                                    outstandingPolls = 0;
                                }
                            }
                        } catch (IOException ex) {
                            messageForConsole(Localization.getString("controller.exception.sendingstatus")
                                    + ": " + ex.getMessage() + "\n");
                        }
                    }
                });
               
            }
        };
       
        return new Timer(this.getStatusUpdateRate(), actionListener);
    }
    /**
     * Begin issuing GRBL status request commands.
     */
    private void beginPollingPosition() {
        // Start sending '?' commands if supported and enabled.
        if (this.positionMode != null && this.getStatusUpdatesEnabled()) {
            if (this.positionPollTimer.isRunning() == false) {
                this.outstandingPolls = 0;
                this.positionPollTimer.start();
            }
        }
    }

    /**
     * Stop issuing GRBL status request commands.
     */
    private void stopPollingPosition() {
        if (this.positionPollTimer.isRunning()) {
            this.positionPollTimer.stop();
        }
    }
   
    // No longer a listener event
    private void handlePositionString(String string) {
        if (this.positionMode != null) {
            this.grblState = GrblUtils.getStateFromStatusString(string, this.positionMode);
            this.machineLocation = GrblUtils.getMachinePositionFromStatusString(string, this.positionMode);
            this.workLocation = GrblUtils.getWorkPositionFromStatusString(string, this.positionMode);
            if ( (this.machineLocation != null) &&
                    (this.machineLocation.z > this.maxZLocation)) {
                this.maxZLocation = this.machineLocation.z;
            }
        
            this.dispatchStatusString(this.grblState, this.machineLocation, this.workLocation);
        }
    }
   
    @Override
    protected void statusUpdatesEnabledValueChanged(boolean enabled) {
        if (enabled) {
            beginPollingPosition();
        } else {
            stopPollingPosition();
        }
    }
   
    @Override
    protected void statusUpdatesRateValueChanged(int rate) {
        this.stopPollingPosition();
        this.positionPollTimer = this.createPositionPollTimer();
       
        // This will start the timer up again if it is supported and enabled.
        this.beginPollingPosition();
    }
}
TOP

Related Classes of com.willwinder.universalgcodesender.GrblController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.