File indexing completed on 2024-05-12 04:41:09

0001 /* AtCore KDE Libary for 3D Printers
0002     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0003     SPDX-FileCopyrightText: 2016, 2018 Tomaz Canabrava <tcanabrava@kde.org>
0004     SPDX-FileCopyrightText: 2016-2019 Chris Rizzitello <rizzitello@kde.org>
0005     SPDX-FileCopyrightText: 2016-2019 Patrick José Pereira <patrickjp@kde.org>
0006     SPDX-FileCopyrightText: 2016, 2019 Lays Rodrigues <lays.rodrigues@kde.org>
0007     SPDX-FileCopyrightText: 2018 Leandro Santiago <leandrosansilva@gmail.com>
0008 */
0009 
0010 #pragma once
0011 #include <QObject>
0012 #include <QSerialPort>
0013 #include <QSerialPortInfo>
0014 #include <memory>
0015 
0016 #include "atcore_export.h"
0017 #include "beddeform.h"
0018 #include "ifirmware.h"
0019 #include "temperature.h"
0020 
0021 class SerialLayer;
0022 class IFirmware;
0023 class QTime;
0024 
0025 /**
0026  * @brief The AtCore class
0027  * aims to provides a high level interface for serial based gcode devices<br />
0028  *
0029  * #### General Workflow
0030  * - Connect to a serial port with newConnection()
0031  * - Send commands to the device (pushCommand(), print(), ...)
0032  * - AtCore::close() when you are all done.
0033 
0034  * #### How AtCore Finds Plugins.
0035  * AtCore will check each directory below for plugins.
0036  *  1. QApplication::applicationDirPath/plugins (runtime)
0037  *  2. QApplication::applicationDirPath/AtCore (runtime)
0038  *  3. QApplication::applicationDirPath/../PlugIns/AtCore (runtime)
0039  *  4. Fullpath of KDE_PLUGIN_DIR (buildtime)
0040  *  5. Qt Plugin path/AtCore (runtime)
0041  *  6. ECM set KDE PLUGIN DIR  (buildtime)
0042  *  7. Build Dir/plugins (buildtime)
0043  */
0044 class ATCORE_EXPORT AtCore : public QObject
0045 {
0046     Q_OBJECT
0047     Q_PROPERTY(QString version READ version CONSTANT)
0048     Q_PROPERTY(QStringList availableFirmwarePlugins READ availableFirmwarePlugins NOTIFY availableFirmwarePluginsChanged)
0049     Q_PROPERTY(int extruderCount READ extruderCount WRITE setExtruderCount NOTIFY extruderCountChanged)
0050     Q_PROPERTY(int temperatureTimerInterval READ temperatureTimerInterval WRITE setTemperatureTimerInterval NOTIFY temperatureTimerIntervalChanged);
0051     Q_PROPERTY(int serialTimerInterval READ serialTimerInterval WRITE setSerialTimerInterval NOTIFY serialTimerIntervalChanged)
0052     Q_PROPERTY(QStringList serialPorts READ serialPorts NOTIFY portsChanged)
0053     Q_PROPERTY(float percentagePrinted READ percentagePrinted NOTIFY printProgressChanged)
0054     Q_PROPERTY(QStringList portSpeeds READ portSpeeds CONSTANT)
0055     Q_PROPERTY(QString connectedPort READ connectedPort CONSTANT)
0056     Q_PROPERTY(AtCore::STATES state READ state WRITE setState NOTIFY stateChanged)
0057     Q_PROPERTY(bool sdMount READ isSdMounted WRITE setSdMounted NOTIFY sdMountChanged)
0058     Q_PROPERTY(QStringList sdFileList READ sdFileList NOTIFY sdCardFileListChanged)
0059     Q_PROPERTY(bool autoTemperatureReport READ autoTemperatureReport WRITE setAutoTemperatureReport NOTIFY autoTemperatureReportChanged)
0060     Q_PROPERTY(Temperature *temperature READ temperature CONSTANT)
0061 
0062     friend class AtCoreTests;
0063     // Add friends as Sd Card support is extended to more plugins.
0064     friend class RepetierPlugin;
0065     friend class MarlinPlugin;
0066     // friend class SmoothiePlugin;
0067     // friend class TeacupPlugin;
0068     // friend class AprinterPlugin;
0069     // friend class SprinterPlugin;
0070 
0071 public:
0072     /**
0073      * @brief STATES enum Possible states the printer can be in
0074      */
0075     enum STATES {
0076         DISCONNECTED,  //!< Not Connected to a printer, initial state
0077         CONNECTING,    //!< Attempting to connect, Fw not probed
0078         IDLE,          //!< Connected to printer and ready for commands
0079         BUSY,          //!< Printer is Printing or working
0080         PAUSE,         //!< Printer is paused
0081         ERRORSTATE,    //!< Printer Returned Error
0082         STOP,          //!< Stop Printing and Clean Queue
0083         STARTPRINT,    //!< Just Starting a print job
0084         FINISHEDPRINT, //!< Just Finished print job
0085     };
0086     Q_ENUM(STATES)
0087     /**
0088      * @brief The AXES enum - Printer Axes.
0089      */
0090     enum AXES {
0091         X = 1 << 0, //!< X Axis: X Motor
0092         Y = 1 << 1, //!< Y Axis Y Motor
0093         Z = 1 << 2, //!< Z Axis Z Motor
0094         E = 1 << 3, //!< E Axis: Extruder Motor 0
0095     };
0096     Q_ENUM(AXES)
0097     /**
0098      * @brief The UNITS enum - Possible Mesurment Units
0099      */
0100     enum UNITS {
0101         METRIC,  //!< Metric Units (Meters)
0102         IMPERIAL //!< Imperial Units (Feet)
0103     };
0104     Q_ENUM(UNITS)
0105     /**
0106      * @brief AtCore create a new instance of AtCore
0107      * @param parent: parent of the object
0108      */
0109     explicit AtCore(QObject *parent = nullptr);
0110     ~AtCore();
0111 
0112     /**
0113      * @brief version
0114      * @return Version number
0115      */
0116     QString version() const;
0117 
0118     /**
0119      * @brief Returns a List of detected serial ports
0120      * @return List of detected ports
0121      * @sa newConnection(), serial(), closeConnection()
0122      */
0123     QStringList serialPorts() const;
0124 
0125     /**
0126      * @brief connectedPort
0127      * @return the port atcore is connected to or empty string if none
0128      */
0129     QString connectedPort() const;
0130 
0131     /**
0132      * @brief Connect to a device.
0133      * @param port: the port to initialize
0134      * @param baud: the baud of the port
0135      * @param fwName: Firmware name of plugin to use (will try to autodetect if fwName is unknown)
0136      * @param disableROC: atcore will attempt to disable reset on connect for this device.
0137      * @return True is connection was successful
0138      * @sa serialPorts(), serial(), closeConnection()
0139      */
0140     Q_INVOKABLE bool newConnection(const QString &port, int baud, const QString &fwName, bool disableROC = false);
0141 
0142     /**
0143      * @brief Returns a list of valid baud speeds
0144      */
0145     QStringList portSpeeds() const;
0146 
0147     /**
0148      * @brief Close the current serial connection
0149      * @sa newConnection(), serial(), serialPorts(), close()
0150      */
0151     Q_INVOKABLE void closeConnection();
0152 
0153     /**
0154      * @brief Main access to the loaded firmware plugin
0155      * @return IFirmware * to currently loaded plugin
0156      * @sa availableFirmwarePlugins(), loadFirmwarePlugin()
0157      */
0158     Q_INVOKABLE IFirmware *firmwarePlugin() const;
0159 
0160     /**
0161      * @brief List of available firmware plugins
0162      * @sa loadFirmwarePlugin(), firmwarePlugin()
0163      */
0164     QStringList availableFirmwarePlugins() const;
0165 
0166     /**
0167      * @brief Get Printer state
0168      * @return State of the printer
0169      * @sa setState(), stateChanged(), AtCore::STATES
0170      */
0171     AtCore::STATES state();
0172 
0173     /**
0174      * @brief extruderCount
0175      * @return The number of detected Extruders Default is 1
0176      * @sa setExtruderCount(int newCount), extruderCountChanged(int newCount)
0177      */
0178     int extruderCount() const;
0179 
0180     /**
0181      * @brief Return printed percentage
0182      * @sa printProgressChanged()
0183      */
0184     float percentagePrinted() const;
0185 
0186     /**
0187      * @brief The Bed Deform data as told by the Firmware.
0188      */
0189     std::shared_ptr<BedDeform> bedDeform();
0190 
0191     /**
0192      * @brief The temperature of the current hotend as told by the Firmware.
0193      */
0194     Temperature *temperature();
0195 
0196     /**
0197      * @brief Return the amount of miliseconds the serialTimer is set to. 0 = Disabled
0198      */
0199     int serialTimerInterval() const;
0200 
0201     /**
0202      * @brief Return the amount of miliseconds the temperatureTimer is set to. 0 = Disabled
0203      */
0204     int temperatureTimerInterval() const;
0205 
0206     /**
0207      * @brief Attempt to Mount an sd card
0208      * @param slot: Sd card Slot on machine (0 is default)
0209      */
0210     Q_INVOKABLE void mountSd(uint slot = 0);
0211 
0212     /**
0213      * @brief Attempt to Unmount an sd card
0214      * @param slot: Sd card Slot on machine (0 is default)
0215      */
0216     Q_INVOKABLE void umountSd(uint slot = 0);
0217 
0218     /**
0219      * @brief sdFileList
0220      * @return List of files on the sd card.
0221      */
0222     QStringList sdFileList();
0223 
0224     /**
0225      * @brief Check if an sd card is mounted on the printer
0226      * @return True if card mounted
0227      */
0228     bool isSdMounted() const;
0229 
0230     /**
0231      * @brief Check if using automatic Temperature reporting to monitor temperatures
0232      * @return True if using automatic temperature reporting
0233      */
0234     bool autoTemperatureReport() const;
0235 
0236 signals:
0237 
0238     /**
0239      * @brief Message emit from atcore these should be displayed to the user for debug.
0240      *
0241      * Possable Messages Are:
0242      *   - Waiting for firmware detect.
0243      *   - No Plugin found for (detected FW)
0244      *   - Failed to open device in Read / Write mode.
0245      *   - Device Errors.
0246      * @param msg: the message.
0247      */
0248     void atcoreMessage(const QString &msg);
0249 
0250     /**
0251      * @brief New number of extruders
0252      * @sa extruderCount(), setExtruderCount(int newCount)
0253      */
0254     void extruderCountChanged(const int newCount);
0255 
0256     /**
0257      * @brief Print job's precentage changed.
0258      * @param newProgress : Message
0259      * @sa percentagePrinted()
0260      */
0261     void printProgressChanged(const float newProgress);
0262 
0263     /**
0264      * @brief New message was received from the printer
0265      * @param message: Message that was received
0266      */
0267     void receivedMessage(const QByteArray &message);
0268 
0269     /**
0270      * @brief New interval for serial timer
0271      * @sa setSerialTimerInterval()
0272      */
0273     void serialTimerIntervalChanged(const int newTime);
0274 
0275     /**
0276      * @brief New interval for temperature timer
0277      * @sa setTemperatureTimerInterval()
0278      */
0279     void temperatureTimerIntervalChanged(const int newTime);
0280 
0281     /**
0282      * @brief use of automatic temperature reporting has changed
0283      * @param autoReport: True if using automatic Reporting mode.
0284      */
0285     void autoTemperatureReportChanged(bool autoReport);
0286 
0287     /**
0288      * @brief New interval for automatic temperature report
0289      * @sa setautoTemperatureReport()
0290      */
0291     void autoCheckTemperatureIntervalChanged(const int newTime);
0292 
0293     /**
0294      * @brief The Printer's State Changed
0295      * @param newState : the new state of the printer
0296      * @sa setState(), state(), AtCore::STATES
0297      */
0298     void stateChanged(AtCore::STATES newState);
0299 
0300     /**
0301      * @brief Available serialports Changed
0302      */
0303     void portsChanged(const QStringList &portList);
0304 
0305     /**
0306      * @brief Sd Card Mount Changed
0307      */
0308     void sdMountChanged(bool newState);
0309 
0310     /**
0311      * @brief The files on the sd card have changed.
0312      */
0313     void sdCardFileListChanged(const QStringList &fileList);
0314 
0315     /**
0316      * @brief pushedCommand via serialLayer connect this to your log to see send commands
0317      * @param comm: the command sent.
0318      */
0319     void pushedCommand(const QByteArray &comm);
0320 
0321     /**
0322      * @brief availableFirmwarePluginsChanged notify about the new plugins available
0323      */
0324     void availableFirmwarePluginsChanged();
0325 
0326 public slots:
0327 
0328     /**
0329      * @brief Set the printers state
0330      * @param state : printer state.
0331      * @sa state(), stateChanged(), AtCore::STATES
0332      */
0333     void setState(AtCore::STATES state);
0334 
0335     /**
0336      * @brief updateFWPlugins Check for new Firmware plugins.
0337      */
0338     Q_INVOKABLE void updateFWPlugins();
0339 
0340     /**
0341      * @brief Push a command into the command queue
0342      *
0343      * @param comm : Command
0344      */
0345     Q_INVOKABLE void pushCommand(const QString &comm);
0346 
0347     /**
0348      * @brief Public Interface for printing a file
0349      * @param fileName: the gcode file to print.
0350      * @param sdPrint: set true to print fileName from Sd card
0351      */
0352     Q_INVOKABLE void print(const QString &fileName, bool sdPrint = false);
0353 
0354     /**
0355      * @brief Stop the Printer by empting the queue and aborting the print job (if running)
0356      * @sa emergencyStop(), pause(), resume()
0357      */
0358     Q_INVOKABLE void stop();
0359 
0360     /**
0361      * @brief stop the printer via the emergency stop Command (M112)
0362      * @sa stop(), pause(), resume()
0363      */
0364     Q_INVOKABLE void emergencyStop();
0365 
0366     /**
0367      * @brief pause an in process print job
0368      *
0369      * Sends M114 on pause to store the location where the head stoped.
0370      * This is known to cause problems on fake printers
0371      * @param pauseActions: Gcode to run after pausing commands are ',' separated
0372      * @sa resume(), stop(), emergencyStop()
0373      */
0374     void pause(const QString &pauseActions);
0375 
0376     /**
0377      * @brief resume a paused print job.
0378      * After returning to location pause was triggered.
0379      * @sa pause(), stop(), emergencyStop()
0380      */
0381     Q_INVOKABLE void resume();
0382 
0383     /**
0384      * @brief Send home \p axis command
0385      * @param axis: the axis(es) to home (use X Y Z or any combo of)
0386      * @sa home(), move()
0387      */
0388     Q_INVOKABLE void home(uchar axis);
0389 
0390     /**
0391      * @brief Send home all command
0392      * @sa home(uchar axis), move()
0393      */
0394     Q_INVOKABLE void home();
0395 
0396     /**
0397      * @brief Set extruder temperature
0398      * @param temp : new temperature
0399      * @param extruder : extruder number
0400      * @param andWait: True for heat and ignore commands until temperature is reached
0401      */
0402     Q_INVOKABLE void setExtruderTemp(uint temp = 0, uint extruder = 0, bool andWait = false);
0403 
0404     /**
0405      * @brief move an axis of the printer
0406      * @param axis the axis to move AXES (X Y Z E )
0407      * @param arg the distance to move the axis or the place to move to depending on printer mode
0408      * @sa home(), home(uchar axis), move(QLatin1Char axis, int arg)
0409      */
0410     Q_INVOKABLE void move(AtCore::AXES axis, double arg);
0411 
0412     /**
0413      * @brief move an axis of the printer
0414      * @param axis the axis to move AXES (X Y Z E )
0415      * @param arg the distance to move the axis or the place to move to depending on printer mode
0416      * @sa home(), home(uchar axis), move(AtCore::AXES, int arg)
0417      */
0418     Q_INVOKABLE void move(QLatin1Char axis, double arg);
0419 
0420     /**
0421      * @brief Set the bed temperature
0422      * @param temp : new temperature
0423      * @param andWait: True for heat and ignore commands until temperature is reached
0424      * @sa setExtruderTemp()
0425      */
0426     Q_INVOKABLE void setBedTemp(uint temp = 0, bool andWait = false);
0427 
0428     /**
0429      * @brief setFanSpeed set the fan speed
0430      * @param fanNumber: fan number
0431      * @param speed: new speed of the fan 0-100
0432      */
0433     Q_INVOKABLE void setFanSpeed(uint speed = 0, uint fanNumber = 0);
0434 
0435     /**
0436      * @brief Set printer to absolute position mode
0437      * @sa setRelativePosition()
0438      */
0439     Q_INVOKABLE void setAbsolutePosition();
0440 
0441     /**
0442      * @brief Set printer to relative position mode
0443      * @sa setAbsolutePosition()
0444      */
0445     Q_INVOKABLE void setRelativePosition();
0446 
0447     /**
0448      * @brief Disable motors after a delay
0449      * @param delay: Seconds until motors are disabled. 0= No delay
0450      */
0451     Q_INVOKABLE void disableMotors(uint delay = 0);
0452 
0453     /**
0454      * @brief set the Printers speed
0455      * @param speed: speed in % (default is 100);
0456      */
0457     Q_INVOKABLE void setPrinterSpeed(uint speed = 100);
0458 
0459     /**
0460      * @brief set extruder Flow rate
0461      * @param rate: flow rate in % (default is 100)
0462      */
0463     Q_INVOKABLE void setFlowRate(uint rate = 100);
0464 
0465     /**
0466      * @brief close any open items.
0467      * You should call this on close events to force any stuck jobs to close
0468      * @sa closeConnection()
0469      */
0470     Q_INVOKABLE void close();
0471 
0472     /**
0473      * @brief showMessage push a message to the printers LCD
0474      * @param message: message to show on the LCD
0475      */
0476     Q_INVOKABLE void showMessage(const QString &message);
0477 
0478     /**
0479      * @brief setUnits sets the measurement units do be used
0480      * @param units : the measurement units to use(METRIC / IMPERIAL)
0481      * @sa AtCore::UNITS
0482      */
0483     Q_INVOKABLE void setUnits(AtCore::UNITS units);
0484 
0485     /**
0486      * @brief Set the time between checks for new serialPorts (0 is default)
0487      * @param newTime: Milliseconds between checks. values <= 0 will Disable Checks.
0488      */
0489     void setSerialTimerInterval(int newTime);
0490 
0491     /**
0492      * @brief Set the time between checks for new Temperature (5000 is default on new connections)
0493      * @param newTime: Milliseconds between checks. values <= 0 will Disable Checks.
0494      */
0495     void setTemperatureTimerInterval(int newTime);
0496 
0497     /** @brief Set if atcore should Enable auto temperature reporting. Temperature timer will also be stopped.
0498      *  @param autoReport: True to enable automatic reporting of temperatures.
0499      *  @sa setAutoCheckTemperature
0500      */
0501     void setAutoTemperatureReport(bool autoReport);
0502 
0503     /**
0504      * @brief Tell the machine to start reporting its temperature automaticly
0505      * @param newTime: Time in seconds between reports (0: disabled)
0506      */
0507     Q_INVOKABLE void setAutoCheckTemperatureInterval(int newTime);
0508 
0509     /**
0510      * @brief delete file from sd card
0511      */
0512     Q_INVOKABLE void sdDelete(const QString &fileName);
0513 
0514     /**
0515      * @brief Queue the Printer for status of sd card print
0516      */
0517     void sdCardPrintStatus();
0518 
0519 private slots:
0520     /**
0521      * @brief processQueue send commands from the queue.
0522      */
0523     void processQueue();
0524 
0525     /**
0526      * @brief Send M105 to the printer if one is not in the Queue
0527      */
0528     void checkTemperature();
0529 
0530     /**
0531      * @brief Connect to SerialLayer::receivedCommand
0532      * @param message: new message.
0533      */
0534     void newMessage(const QByteArray &message);
0535 
0536     /**
0537      * @brief Connect to SerialLayer::pushedCommand
0538      * @param command: newCommand.
0539      */
0540     void newCommand(const QByteArray &command);
0541 
0542     /**
0543      * @brief Search for firmware string in message.
0544      * A Helper function for Firmware detection
0545      * @param message
0546      */
0547     void findFirmware(const QByteArray &message);
0548 
0549     /**
0550      * @brief Search for new serial ports
0551      */
0552     void locateSerialPort();
0553 
0554     /**
0555      * @brief Attempts to disableResetOnConnect for the selected port.
0556      * @param port: the port.
0557      */
0558     void disableResetOnConnect(const QString &port);
0559 
0560     /**
0561      * @brief Send request to the printer for the sd card file list.
0562      */
0563     void getSDFileList();
0564 
0565     /**
0566      * @brief Handle serial Errors.
0567      */
0568     void handleSerialError(QSerialPort::SerialPortError error);
0569 
0570 private:
0571     /**
0572      * @brief Load A firmware plugin
0573      * @param fwName : name of the firmware
0574      * @sa firmwarePlugin(), availableFirmwarePlugins()
0575      */
0576     Q_INVOKABLE void loadFirmwarePlugin(const QString &fwName);
0577 
0578     /**
0579      * @brief True if a firmware plugin is loaded
0580      */
0581     bool firmwarePluginLoaded() const;
0582 
0583     /**
0584      * @brief True if a serial port is initialized
0585      */
0586     bool serialInitialized() const;
0587 
0588     /**
0589      * @brief send firmware request to the printer
0590      */
0591     void requestFirmware();
0592 
0593     /**
0594      * @brief returns AtCorePrivate::sdCardReadingFileList
0595      * @return True if printer is returning sd card file list
0596      */
0597     bool isReadingSdCardList() const;
0598 
0599     /**
0600      * @brief stops print just for sd prints used internally
0601      * @sa stop(), emergencyStop()
0602      */
0603     void stopSdPrint();
0604 
0605     /**
0606      * @brief New connections need to wait for the machine to be ready if it needs reboot
0607      * @param message: message from the firmware
0608      * @param fwName: fwName to load
0609      */
0610     void waitForPrinterReboot(const QByteArray &message, const QString &fwName);
0611 
0612     /**
0613      * @brief Hold private data of AtCore.
0614      */
0615     struct AtCorePrivate;
0616     std::unique_ptr<AtCorePrivate> d;
0617 
0618 protected:
0619     /**
0620      * @brief Set the number of extruders on the machine.
0621      * @param newCount
0622      * @sa extruderCount(), extruderCountChanged(int newCount)
0623      */
0624     void setExtruderCount(int newCount);
0625     /**
0626      * @brief Append a file to AtCorePrivate::sdCardFileList.
0627      * @param fileName: new FileName
0628      */
0629     void appendSdCardFileList(const QString &fileName);
0630 
0631     /**
0632      * @brief Clear AtCorePrivate::sdCardFileList.
0633      */
0634     void clearSdCardFileList();
0635 
0636     /**
0637      * @brief Set if the sd card is mounted by the printer
0638      * @param mounted: True is mounted
0639      */
0640     void setSdMounted(const bool mounted);
0641 
0642     /**
0643      * @brief set AtCorePrivate::sdCardReadingFileList
0644      * @param readingList set true if reading file list
0645      */
0646     void setReadingSdCardList(bool readingList);
0647 };