diff --git a/src/atcore.cpp b/src/atcore.cpp index ec91a23..a94c00f 100644 --- a/src/atcore.cpp +++ b/src/atcore.cpp @@ -1,592 +1,592 @@ /* AtCore Copyright (C) <2016> Authors: Tomaz Canabrava Chris Rizzitello Patrick José Pereira Lays Rodrigues This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include #include #include #include #include #include #include #include #include "atcore.h" #include "seriallayer.h" #include "gcodecommands.h" #include "printthread.h" #include "atcore_default_folders.h" -Q_LOGGING_CATEGORY(ATCORE_PLUGIN, "org.kde.atelier.core.plugin"); -Q_LOGGING_CATEGORY(ATCORE_CORE, "org.kde.atelier.core"); +Q_LOGGING_CATEGORY(ATCORE_PLUGIN, "org.kde.atelier.core.plugin") +Q_LOGGING_CATEGORY(ATCORE_CORE, "org.kde.atelier.core") /** * @brief The AtCorePrivate struct */ struct AtCorePrivate { IFirmware *firmwarePlugin = nullptr;//!< @param firmwarePlugin: pointer to firmware plugin SerialLayer *serial = nullptr; //!< @param serial: pointer to the serial layer QPluginLoader pluginLoader; //!< @param pluginLoader: QPluginLoader QDir pluginsDir; //!< @param pluginsDir: Directory where plugins were found QMap plugins; //!< @param plugins: Map of plugins name / path QByteArray lastMessage; //!< @param lastMessage: lastMessage from the printer int extruderCount = 1; //!< @param extruderCount: extruder count Temperature temperature; //!< @param temperature: Temperature object QStringList commandQueue; //!< @param commandQueue: the list of commands to send to the printer bool ready = false; //!< @param ready: True if printer is ready for a command QTimer *tempTimer = nullptr; //!< @param tempTimer: timer connected to the checkTemperature function float percentage; //!< @param percentage: print job percent QByteArray posString; //!< @param posString: stored string from last M114 return AtCore::STATES printerState; //!< @param printerState: State of the Printer QStringList serialPorts; //!< @param seralPorts: Detected serial Ports QTimer *serialTimer = nullptr; //!< @param serialTimer: Timer connected to locateSerialPorts }; AtCore::AtCore(QObject *parent) : QObject(parent), d(new AtCorePrivate) { qRegisterMetaType("AtCore::STATES"); setState(AtCore::DISCONNECTED); d->tempTimer = new QTimer(this); d->tempTimer->setInterval(5000); d->tempTimer->setSingleShot(false); for (const auto &path : AtCoreDirectories::pluginDir) { qCDebug(ATCORE_PLUGIN) << "Lookin for plugins in " << path; if (QDir(path).exists()) { d->pluginsDir = QDir(path); qCDebug(ATCORE_PLUGIN) << "Valid path for plugins found !"; break; } } if (!d->pluginsDir.exists()) { qCritical() << "No valid path for plugin !"; } #if defined(Q_OS_WIN) || defined(Q_OS_MAC) d->pluginsDir = qApp->applicationDirPath() + QStringLiteral("/plugins"); #endif qCDebug(ATCORE_PLUGIN) << d->pluginsDir; findFirmwarePlugins(); setState(AtCore::DISCONNECTED); } SerialLayer *AtCore::serial() const { return d->serial; } IFirmware *AtCore::firmwarePlugin() const { return d->firmwarePlugin; } void AtCore::close() { exit(0); } Temperature &AtCore::temperature() const { return d->temperature; } void AtCore::findFirmware(const QByteArray &message) { if (state() == AtCore::DISCONNECTED) { qWarning() << "Cant find firwmware, serial not connected !"; return; } if (state() == AtCore::CONNECTING) { if (message.contains("start")) { qCDebug(ATCORE_CORE) << "Waiting requestFirmware."; QTimer::singleShot(500, this, &AtCore::requestFirmware); return; } else if (message.contains("Grbl")) { loadFirmwarePlugin(QString::fromLatin1("grbl")); return; } else if (message.contains("Smoothie")) { loadFirmwarePlugin(QString::fromLatin1("smoothie")); return; } } qCDebug(ATCORE_CORE) << "Find Firmware Called" << message; if (!message.contains("FIRMWARE_NAME:")) { qCDebug(ATCORE_CORE) << "No firmware yet."; return; } qCDebug(ATCORE_CORE) << "Found firmware string, Looking for Firmware Name."; QString fwName = QString::fromLocal8Bit(message); fwName = fwName.split(QChar::fromLatin1(':')).at(1); if (fwName.indexOf(QChar::fromLatin1(' ')) == 0) { //remove leading space fwName.remove(0, 1); } if (fwName.contains(QChar::fromLatin1(' '))) { //check there is a space or dont' resize fwName.resize(fwName.indexOf(QChar::fromLatin1(' '))); } fwName = fwName.toLower().simplified(); if (fwName.contains(QChar::fromLatin1('_'))) { fwName.resize(fwName.indexOf(QChar::fromLatin1('_'))); } qCDebug(ATCORE_CORE) << "Firmware Name:" << fwName; if (message.contains("EXTRUDER_COUNT:")) { //this code is broken if more then 9 extruders are detected. since only one char is returned d->extruderCount = message.at(message.indexOf("EXTRUDER_COUNT:") + 15) - '0'; } qCDebug(ATCORE_CORE) << "Extruder Count:" << QString::number(extruderCount()); loadFirmwarePlugin(fwName); } void AtCore::loadFirmwarePlugin(const QString &fwName) { if (d->plugins.contains(fwName)) { d->pluginLoader.setFileName(d->plugins[fwName]); if (!d->pluginLoader.load()) { qCDebug(ATCORE_PLUGIN) << d->pluginLoader.errorString(); } else { qCDebug(ATCORE_PLUGIN) << "Loading plugin."; } d->firmwarePlugin = qobject_cast(d->pluginLoader.instance()); if (!firmwarePluginLoaded()) { qCDebug(ATCORE_PLUGIN) << "No plugin loaded."; qCDebug(ATCORE_PLUGIN) << "Looking plugin in folder:" << d->pluginsDir; setState(AtCore::CONNECTING); } else { qCDebug(ATCORE_PLUGIN) << "Connected to" << firmwarePlugin()->name(); firmwarePlugin()->init(this); disconnect(serial(), &SerialLayer::receivedCommand, this, &AtCore::findFirmware); connect(serial(), &SerialLayer::receivedCommand, this, &AtCore::newMessage); connect(firmwarePlugin(), &IFirmware::readyForCommand, this, &AtCore::processQueue); d->ready = true; // ready on new firmware load if (firmwarePlugin()->name() != QStringLiteral("Grbl")) { connect(d->tempTimer, &QTimer::timeout, this, &AtCore::checkTemperature); d->tempTimer->start(); } setState(IDLE); } } else { qCDebug(ATCORE_CORE) << "No Firmware Loaded"; } } bool AtCore::initSerial(const QString &port, int baud) { d->serial = new SerialLayer(port, baud); if (serialInitialized()) { setState(AtCore::CONNECTING); connect(serial(), &SerialLayer::receivedCommand, this, &AtCore::findFirmware); return true; } else { qCDebug(ATCORE_CORE) << "Failed to open device."; return false; } } bool AtCore::serialInitialized() const { if (!d->serial) { return false; } return d->serial->isOpen(); } QString AtCore::connectedPort() const { return serial()->portName(); } QStringList AtCore::serialPorts() const { QStringList ports; QList serialPortInfoList = QSerialPortInfo::availablePorts(); if (!serialPortInfoList.isEmpty()) { foreach (const QSerialPortInfo &serialPortInfo, serialPortInfoList) { #ifdef Q_OS_MAC //Mac OS has callout serial ports starting with cu. They can only receive data and it's necessary to filter them out if (!serialPortInfo.portName().startsWith(QStringLiteral("cu."), Qt::CaseInsensitive)) { ports.append(serialPortInfo.portName()); } #else ports.append(serialPortInfo.portName()); #endif } } return ports; } void AtCore::locateSerialPort() { QStringList ports = serialPorts(); if (d->serialPorts != ports) { d->serialPorts = ports; emit portsChanged(d->serialPorts); } } quint16 AtCore::serialTimerInterval() const { if (d->serialTimer != nullptr) { return d->serialTimer->interval(); } return 0; } void AtCore::setSerialTimerInterval(const quint16 &newTime) { if (newTime == 0) { if (d->serialTimer) { disconnect(d->serialTimer, &QTimer::timeout, this, &AtCore::locateSerialPort); delete d->serialTimer; } return; } if (!d->serialTimer) { d->serialTimer = new QTimer(); connect(d->serialTimer, &QTimer::timeout, this, &AtCore::locateSerialPort); } d->serialTimer->start(newTime); } void AtCore::newMessage(const QByteArray &message) { d->lastMessage = message; if (message.startsWith(QString::fromLatin1("X:").toLocal8Bit())) { d->posString = message; d->posString.resize(d->posString.indexOf('E')); d->posString.replace(':', ""); } //Check if have temperature info and decode it temperature().decodeTemp(message); emit(receivedMessage(d->lastMessage)); } void AtCore::setRelativePosition() { pushCommand(GCode::toCommand(GCode::G91)); } void AtCore::setAbsolutePosition() { pushCommand(GCode::toCommand(GCode::G90)); } float AtCore::percentagePrinted() const { return d->percentage; } void AtCore::print(const QString &fileName) { if (state() == AtCore::CONNECTING) { qCDebug(ATCORE_CORE) << "Load a firmware plugin to print."; return; } //START A THREAD AND CONNECT TO IT setState(AtCore::STARTPRINT); QThread *thread = new QThread(); PrintThread *printThread = new PrintThread(this, fileName); printThread->moveToThread(thread); connect(printThread, &PrintThread::printProgressChanged, this, &AtCore::printProgressChanged, Qt::QueuedConnection); connect(thread, &QThread::started, printThread, &PrintThread::start); connect(printThread, &PrintThread::finished, thread, &QThread::quit); connect(thread, &QThread::finished, printThread, &PrintThread::deleteLater); if (!thread->isRunning()) { thread->start(); } } void AtCore::pushCommand(const QString &comm) { d->commandQueue.append(comm); if (d->ready) { processQueue(); } } void AtCore::closeConnection() { if (serialInitialized()) { if (state() == AtCore::BUSY) { //we have to clean print if printing. setState(AtCore::STOP); } if (firmwarePluginLoaded()) { disconnect(firmwarePlugin(), &IFirmware::readyForCommand, this, &AtCore::processQueue); if (firmwarePlugin()->name() != QStringLiteral("Grbl")) { disconnect(d->tempTimer, &QTimer::timeout, this, &AtCore::checkTemperature); d->tempTimer->stop(); } } serial()->close(); setState(AtCore::DISCONNECTED); } } AtCore::STATES AtCore::state(void) { return d->printerState; } void AtCore::setState(AtCore::STATES state) { if (state != d->printerState) { qCDebug(ATCORE_CORE) << "Atcore state changed from [" \ << d->printerState << "] to [" << state << "]"; d->printerState = state; emit(stateChanged(d->printerState)); } } void AtCore::stop() { setState(AtCore::STOP); d->commandQueue.clear(); setExtruderTemp(0, 0); setBedTemp(0); home(AtCore::X); } void AtCore::emergencyStop() { if (state() == AtCore::BUSY) { setState(AtCore::STOP); } d->commandQueue.clear(); serial()->pushCommand(GCode::toCommand(GCode::M112).toLocal8Bit()); } void AtCore::requestFirmware() { if (serialInitialized()) { qCDebug(ATCORE_CORE) << "Sending " << GCode::toString(GCode::M115); serial()->pushCommand(GCode::toCommand(GCode::M115).toLocal8Bit()); } else { qCDebug(ATCORE_CORE) << "There is no open device to send commands"; } } bool AtCore::firmwarePluginLoaded() const { if (firmwarePlugin()) { return true; } else { return false; } } void AtCore::findFirmwarePlugins() { d->plugins.clear(); qCDebug(ATCORE_PLUGIN) << "plugin dir:" << d->pluginsDir; QStringList files = d->pluginsDir.entryList(QDir::Files); foreach (const QString &f, files) { QString file = f; #if defined(Q_OS_WIN) if (file.endsWith(QStringLiteral(".dll"))) #elif defined(Q_OS_MAC) if (file.endsWith(QStringLiteral(".dylib"))) #else if (file.endsWith(QStringLiteral(".so"))) #endif file = file.split(QChar::fromLatin1('.')).at(0); else { qCDebug(ATCORE_PLUGIN) << "File" << file << "not plugin."; continue; } qCDebug(ATCORE_CORE) << "Found plugin file" << f; if (file.startsWith(QStringLiteral("lib"))) { file = file.remove(QStringLiteral("lib")); } file = file.toLower().simplified(); QString pluginString; pluginString.append(d->pluginsDir.path()); pluginString.append(QChar::fromLatin1('/')); pluginString.append(f); d->plugins[file] = pluginString; qCDebug(ATCORE_CORE) << tr("plugins[%1]=%2").arg(file, pluginString); } } QStringList AtCore::availableFirmwarePlugins() const { return d->plugins.keys(); } void AtCore::detectFirmware() { connect(serial(), &SerialLayer::receivedCommand, this, &AtCore::findFirmware); } void AtCore::pause(const QString &pauseActions) { pushCommand(GCode::toCommand(GCode::M114)); setState(AtCore::PAUSE); if (!pauseActions.isEmpty()) { QStringList temp = pauseActions.split(QChar::fromLatin1(',')); for (int i = 0; i < temp.length(); i++) { pushCommand(temp.at(i)); } } } void AtCore::resume() { pushCommand(GCode::toCommand(GCode::G0, QString::fromLatin1(d->posString))); setState(AtCore::BUSY); } /*~~~~~Control Slots ~~~~~~~~*/ void AtCore::home() { pushCommand(GCode::toCommand(GCode::G28)); } void AtCore::home(uchar axis) { QString args; if (axis & AtCore::X) { args.append(QStringLiteral("X0 ")); } if (axis & AtCore::Y) { args.append(QStringLiteral("Y0 ")); } if (axis & AtCore::Z) { args.append(QStringLiteral("Z0")); } pushCommand(GCode::toCommand(GCode::G28, args)); } void AtCore::setExtruderTemp(uint temp, uint extruder) { pushCommand(GCode::toCommand(GCode::M104, QString::number(extruder), QString::number(temp))); temperature().setExtruderTargetTemperature(temp); } void AtCore::setBedTemp(uint temp) { pushCommand(GCode::toCommand(GCode::M140, QString::number(temp))); temperature().setBedTargetTemperature(temp); } void AtCore::setFanSpeed(uint speed, uint fanNumber) { pushCommand(GCode::toCommand(GCode::M106, QString::number(fanNumber), QString::number(speed))); } void AtCore::setPrinterSpeed(uint speed) { pushCommand(GCode::toCommand(GCode::M220, QString::number(speed))); } void AtCore::setFlowRate(uint speed) { pushCommand(GCode::toCommand(GCode::M221, QString::number(speed))); } void AtCore::move(AtCore::AXES axis, uint arg) { if (axis & AtCore::X) { pushCommand(GCode::toCommand(GCode::G1, QStringLiteral("X %1").arg(QString::number(arg)))); } else if (axis & AtCore::Y) { pushCommand(GCode::toCommand(GCode::G1, QStringLiteral("Y %1").arg(QString::number(arg)))); } else if (axis & AtCore::Z) { pushCommand(GCode::toCommand(GCode::G1, QStringLiteral("Z %1").arg(QString::number(arg)))); } else if (axis & AtCore::E) { pushCommand(GCode::toCommand(GCode::G1, QStringLiteral("E %1").arg(QString::number(arg)))); } } int AtCore::extruderCount() const { return d->extruderCount; } void AtCore::processQueue() { d->ready = true; if (d->commandQueue.isEmpty()) { return; } if (!serialInitialized()) { qCDebug(ATCORE_PLUGIN) << "Can't process queue ! Serial not initialized."; return; } QString text = d->commandQueue.takeAt(0); if (firmwarePluginLoaded()) { serial()->pushCommand(firmwarePlugin()->translate(text)); } else { serial()->pushCommand(text.toLocal8Bit()); } d->ready = false; } void AtCore::checkTemperature() { if (d->commandQueue.contains(GCode::toCommand(GCode::M105))) { return; } pushCommand(GCode::toCommand(GCode::M105)); } void AtCore::showMessage(const QString &message) { if (!message.isEmpty()) { pushCommand(GCode::toCommand((GCode::M117), message)); } } void AtCore::setUnits(AtCore::UNITS units) { switch (units) { case AtCore::METRIC: pushCommand(GCode::toCommand(GCode::G21)); break; case AtCore::IMPERIAL: pushCommand(GCode::toCommand(GCode::G20)); break; } } QStringList AtCore::portSpeeds() const { return serial()->validBaudRates(); } diff --git a/src/plugins/aprinterplugin.cpp b/src/plugins/aprinterplugin.cpp index 38824f3..0359dda 100644 --- a/src/plugins/aprinterplugin.cpp +++ b/src/plugins/aprinterplugin.cpp @@ -1,56 +1,56 @@ /* AtCore KDE Libary for 3D Printers Copyright (C) <2016> Authors: Tomaz Canabrava Chris Rizzitello Patrick José Pereira This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include #include #include "aprinterplugin.h" #include "temperature.h" #include "atcore.h" QString AprinterPlugin::_ok = QStringLiteral("ok"); -Q_LOGGING_CATEGORY(APRINTER_PLUGIN, "org.kde.atelier.core.firmware.aprinter"); +Q_LOGGING_CATEGORY(APRINTER_PLUGIN, "org.kde.atelier.core.firmware.aprinter") QString AprinterPlugin::name() const { return QStringLiteral("Aprinter"); } AprinterPlugin::AprinterPlugin() { qCDebug(APRINTER_PLUGIN) << name() << " plugin loaded!"; } void AprinterPlugin::validateCommand(const QString &lastMessage) { if (lastMessage.contains(_ok)) { emit readyForCommand(); } } QByteArray AprinterPlugin::translate(const QString &command) { return command.toLocal8Bit(); } diff --git a/src/plugins/marlinplugin.cpp b/src/plugins/marlinplugin.cpp index 0e1751c..2e7a1d4 100644 --- a/src/plugins/marlinplugin.cpp +++ b/src/plugins/marlinplugin.cpp @@ -1,56 +1,56 @@ /* AtCore KDE Libary for 3D Printers Copyright (C) <2016> Authors: Tomaz Canabrava Chris Rizzitello Patrick José Pereira This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include #include #include "marlinplugin.h" #include "temperature.h" #include "atcore.h" QString MarlinPlugin::_ok = QStringLiteral("ok"); -Q_LOGGING_CATEGORY(MARLIN_PLUGIN, "org.kde.atelier.core.firmware.marlin"); +Q_LOGGING_CATEGORY(MARLIN_PLUGIN, "org.kde.atelier.core.firmware.marlin") QString MarlinPlugin::name() const { return QStringLiteral("Marlin"); } MarlinPlugin::MarlinPlugin() { qCDebug(MARLIN_PLUGIN) << name() << " plugin loaded!"; } void MarlinPlugin::validateCommand(const QString &lastMessage) { if (lastMessage.contains(_ok)) { emit readyForCommand(); } } QByteArray MarlinPlugin::translate(const QString &command) { return command.toLocal8Bit(); } diff --git a/src/plugins/repetierplugin.cpp b/src/plugins/repetierplugin.cpp index 20a0531..ad0d138 100644 --- a/src/plugins/repetierplugin.cpp +++ b/src/plugins/repetierplugin.cpp @@ -1,56 +1,56 @@ /* AtCore KDE Libary for 3D Printers Copyright (C) <2016> Authors: Tomaz Canabrava Chris Rizzitello Patrick José Pereira This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include #include #include "repetierplugin.h" #include "temperature.h" #include "atcore.h" QString RepetierPlugin::_ok = QStringLiteral("ok"); -Q_LOGGING_CATEGORY(REPETIER_PLUGIN, "org.kde.atelier.core.firmware.repetier"); +Q_LOGGING_CATEGORY(REPETIER_PLUGIN, "org.kde.atelier.core.firmware.repetier") QString RepetierPlugin::name() const { return QStringLiteral("Repetier"); } RepetierPlugin::RepetierPlugin() { qCDebug(REPETIER_PLUGIN) << name() << " plugin loaded!"; } void RepetierPlugin::validateCommand(const QString &lastMessage) { if (lastMessage.contains(_ok)) { emit readyForCommand(); } } QByteArray RepetierPlugin::translate(const QString &command) { return command.toLocal8Bit(); } diff --git a/src/plugins/smoothieplugin.cpp b/src/plugins/smoothieplugin.cpp index 1c5c2c7..0170c27 100644 --- a/src/plugins/smoothieplugin.cpp +++ b/src/plugins/smoothieplugin.cpp @@ -1,56 +1,56 @@ /* AtCore KDE Libary for 3D Printers Copyright (C) <2016> Authors: Tomaz Canabrava Chris Rizzitello Patrick José Pereira This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include #include #include "smoothieplugin.h" #include "temperature.h" #include "atcore.h" QString SmoothiePlugin::_ok = QStringLiteral("ok"); -Q_LOGGING_CATEGORY(SMOOTHIE_PLUGIN, "org.kde.atelier.core.firmware.smoothie"); +Q_LOGGING_CATEGORY(SMOOTHIE_PLUGIN, "org.kde.atelier.core.firmware.smoothie") QString SmoothiePlugin::name() const { return QStringLiteral("Smoothie"); } SmoothiePlugin::SmoothiePlugin() { qCDebug(SMOOTHIE_PLUGIN) << name() << " plugin loaded!"; } void SmoothiePlugin::validateCommand(const QString &lastMessage) { if (lastMessage.contains(_ok)) { emit readyForCommand(); } } QByteArray SmoothiePlugin::translate(const QString &command) { return command.toLocal8Bit(); } diff --git a/src/plugins/sprinterplugin.cpp b/src/plugins/sprinterplugin.cpp index 00f10b6..c0516b0 100644 --- a/src/plugins/sprinterplugin.cpp +++ b/src/plugins/sprinterplugin.cpp @@ -1,57 +1,57 @@ /* AtCore KDE Libary for 3D Printers Copyright (C) <2016> Authors: Tomaz Canabrava Chris Rizzitello Patrick José Pereira This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include #include #include "sprinterplugin.h" #include "temperature.h" #include "atcore.h" QString SprinterPlugin::_ok = QStringLiteral("ok"); -Q_LOGGING_CATEGORY(SPRINTER_PLUGIN, "org.kde.atelier.core.firmware.sprinter"); +Q_LOGGING_CATEGORY(SPRINTER_PLUGIN, "org.kde.atelier.core.firmware.sprinter") QString SprinterPlugin::name() const { return QStringLiteral("Sprinter"); } SprinterPlugin::SprinterPlugin() { qCDebug(SPRINTER_PLUGIN) << name() << " plugin loaded!"; } void SprinterPlugin::validateCommand(const QString &lastMessage) { if (lastMessage.contains(_ok)) { emit readyForCommand(); } } QByteArray SprinterPlugin::translate(const QString &command) { return command.toLocal8Bit(); } diff --git a/src/plugins/teacupplugin.cpp b/src/plugins/teacupplugin.cpp index db88fdf..ddbee29 100644 --- a/src/plugins/teacupplugin.cpp +++ b/src/plugins/teacupplugin.cpp @@ -1,56 +1,56 @@ /* AtCore KDE Libary for 3D Printers Copyright (C) <2016> Authors: Tomaz Canabrava Chris Rizzitello Patrick José Pereira This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include #include #include "teacupplugin.h" #include "temperature.h" #include "atcore.h" QString TeacupPlugin::_ok = QStringLiteral("ok"); -Q_LOGGING_CATEGORY(TEACUP_PLUGIN, "org.kde.atelier.core.firmware.teacup"); +Q_LOGGING_CATEGORY(TEACUP_PLUGIN, "org.kde.atelier.core.firmware.teacup") QString TeacupPlugin::name() const { return QStringLiteral("Teacup"); } TeacupPlugin::TeacupPlugin() { qCDebug(TEACUP_PLUGIN) << name() << " plugin loaded!"; } void TeacupPlugin::validateCommand(const QString &lastMessage) { if (lastMessage.contains(_ok)) { emit readyForCommand(); } } QByteArray TeacupPlugin::translate(const QString &command) { return command.toLocal8Bit(); } diff --git a/src/printthread.cpp b/src/printthread.cpp index 727252c..b00f9a0 100644 --- a/src/printthread.cpp +++ b/src/printthread.cpp @@ -1,144 +1,144 @@ /* AtCore Copyright (C) <2017> Authors: Chris Rizzitello This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include #include #include "printthread.h" #include "gcodecommands.h" -Q_LOGGING_CATEGORY(PRINT_THREAD, "org.kde.atelier.core.printThread"); +Q_LOGGING_CATEGORY(PRINT_THREAD, "org.kde.atelier.core.printThread") /** * @brief The PrintThreadPrivate class */ class PrintThreadPrivate { public: AtCore *core = nullptr; //!<@param core: Pointer to AtCore QTextStream *gcodestream = nullptr; //!<@param gcodestream: Steam the job is read from float printProgress = 0; //!<@param printProgress: Progress of the print job qint64 totalSize = 0; //!<@param totalSize: total file size qint64 stillSize = 0; //!<@param stillSize: remaining file QString cline; //!<@param cline: current line AtCore::STATES state = AtCore::IDLE;//!<@param state: printer state QFile *file = nullptr; //!<@param file: gcode File to stream from }; PrintThread::PrintThread(AtCore *parent, QString fileName) : d(new PrintThreadPrivate) { d->core = parent; d->state = d->core->state(); d->file = new QFile(fileName); d->file->open(QFile::ReadOnly); d->totalSize = d->file->bytesAvailable(); d->stillSize = d->totalSize; d->gcodestream = new QTextStream(d->file); } void PrintThread::start() { // we only want to do this when printing connect(d->core->firmwarePlugin(), &IFirmware::readyForCommand, this, &PrintThread::processJob, Qt::QueuedConnection); connect(this, &PrintThread::nextCommand, d->core, &AtCore::pushCommand, Qt::QueuedConnection); connect(this, &PrintThread::stateChanged, d->core, &AtCore::setState, Qt::QueuedConnection); connect(d->core, &AtCore::stateChanged, this, &PrintThread::setState, Qt::QueuedConnection); connect(this, &PrintThread::finished, this, &PrintThread::deleteLater); // force a command if the printer doesn't send "wait" when idle processJob(); } void PrintThread::processJob() { if (d->gcodestream->atEnd()) { endPrint(); } switch (d->state) { case AtCore::STARTPRINT: case AtCore::IDLE: case AtCore::BUSY: setState(AtCore::BUSY); nextLine(); while (d->cline.isEmpty() && !d->gcodestream->atEnd()) { nextLine(); } if (!d->cline.isEmpty()) { qCDebug(PRINT_THREAD) << "cline:" << d->cline; emit nextCommand(d->cline); } break; case AtCore::ERRORSTATE: qCDebug(PRINT_THREAD) << "Error State"; break; case AtCore::STOP: { endPrint(); break; } case AtCore::PAUSE: break; default: qCDebug(PRINT_THREAD) << "Unknown State"; break; } } void PrintThread::endPrint() { emit(printProgressChanged(100)); qCDebug(PRINT_THREAD) << "atEnd"; disconnect(d->core->firmwarePlugin(), &IFirmware::readyForCommand, this, &PrintThread::processJob); disconnect(this, &PrintThread::nextCommand, d->core, &AtCore::pushCommand); disconnect(d->core, &AtCore::stateChanged, this, &PrintThread::setState); emit(stateChanged(AtCore::FINISHEDPRINT)); emit(stateChanged(AtCore::IDLE)); disconnect(this, &PrintThread::stateChanged, d->core, &AtCore::setState); emit finished(); } void PrintThread::nextLine() { d->cline = d->gcodestream->readLine(); qCDebug(PRINT_THREAD) << "Nextline:" << d->cline; d->stillSize -= d->cline.size() + 1; //remove read chars d->printProgress = float(d->totalSize - d->stillSize) * 100.0 / float(d->totalSize); qCDebug(PRINT_THREAD) << "progress:" << QString::number(d->printProgress); emit(printProgressChanged(d->printProgress)); if (d->cline.contains(QChar::fromLatin1(';'))) { d->cline.resize(d->cline.indexOf(QChar::fromLatin1(';'))); } d->cline = d->cline.simplified(); } void PrintThread::setState(const AtCore::STATES &newState) { if (newState != d->state) { qCDebug(PRINT_THREAD) << "State Changed from [" << d->state << "] to [" << newState << ']'; disconnect(d->core, &AtCore::stateChanged, this, &PrintThread::setState); d->state = newState; emit(stateChanged(d->state)); connect(d->core, &AtCore::stateChanged, this, &PrintThread::setState, Qt::QueuedConnection); } } diff --git a/src/seriallayer.cpp b/src/seriallayer.cpp index c136f93..ce2504e 100644 --- a/src/seriallayer.cpp +++ b/src/seriallayer.cpp @@ -1,136 +1,136 @@ /* AtCore Copyright (C) <2016> Authors: Patrick José Pereira Chris Rizzitello Tomaz Canabrava This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "seriallayer.h" namespace { QByteArray _return = QByteArray("\r"); QByteArray _newLine = QByteArray("\n"); QByteArray _newLineReturn = QByteArray("\n\r"); QStringList _validBaudRates = { QStringLiteral("9600"), QStringLiteral("14400"), QStringLiteral("19200"), QStringLiteral("28800"), QStringLiteral("38400"), QStringLiteral("57600"), QStringLiteral("76800"), QStringLiteral("115200"), QStringLiteral("230400"), QStringLiteral("250000"), QStringLiteral("500000"), QStringLiteral("1000000") }; -}; +} /** * @brief The SerialLayerPrivate class */ class SerialLayerPrivate { public: bool _serialOpened; //!< @param _serialOpened: is serial port opened QByteArray _rawData; //!< @param _rawData: the raw serial data QVector _rByteCommands; //!< @param _rByteCommand: received Messages QVector _sByteCommands; //!< @param _sByteCommand: sent Messages }; SerialLayer::SerialLayer(const QString &port, uint baud, QObject *parent) : QSerialPort(parent), d(new SerialLayerPrivate()) { setPortName(port); setBaudRate(baud); open(QIODevice::ReadWrite); connect(this, &QSerialPort::readyRead, this, &SerialLayer::readAllData); }; void SerialLayer::readAllData() { d->_rawData.append(readAll()); /* * Check if \r exist and remove * Both \n\r and \n are used in string's end and some protocols */ if (d->_rawData.contains(_return)) { d->_rawData = d->_rawData.replace(_return, QByteArray()); } QByteArray tempArray; QList tempList = d->_rawData.split(_newLine.at(0)); for (auto i = tempList.begin(); i != tempList.end(); ++i) { // Get finished line to _byteCommands if (i < tempList.end() - 1) { d->_rByteCommands.append(*i); emit(receivedCommand(*i)); } else { d->_rawData.clear(); d->_rawData.append(*i); } } } void SerialLayer::pushCommand(const QByteArray &comm, const QByteArray &term) { QByteArray tmp = comm + term; write(tmp); emit(pushedCommand(tmp)); } void SerialLayer::pushCommand(const QByteArray &comm) { pushCommand(comm, _newLineReturn); } void SerialLayer::add(const QByteArray &comm, const QByteArray &term) { QByteArray tmp = comm + term; d->_sByteCommands.append(tmp); } void SerialLayer::add(const QByteArray &comm) { add(comm, _newLineReturn); } void SerialLayer::push() { foreach (const auto &comm, d->_sByteCommands) { write(comm); emit(pushedCommand(comm)); } d->_sByteCommands.clear(); } bool SerialLayer::commandAvailable() const { return !d->_rByteCommands.isEmpty(); } QStringList SerialLayer::validBaudRates() const { return _validBaudRates; } diff --git a/src/temperature.h b/src/temperature.h index abe0694..5156080 100644 --- a/src/temperature.h +++ b/src/temperature.h @@ -1,129 +1,129 @@ /* AtCore Copyright (C) <2016> Authors: Tomaz Canabrava Patrick José Pereira This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #pragma once #include #include "atcore_export.h" class TemperaturePrivate; /** * @brief The Temperature class * * Read and hold the Temperature info for the printer */ class ATCORE_EXPORT Temperature : public QObject { Q_OBJECT - Q_PROPERTY(float bedTemperature READ bedTemperature WRITE setBedTemperature NOTIFY bedTemperatureChanged); - Q_PROPERTY(float bedTargetTemperature READ bedTargetTemperature WRITE setBedTargetTemperature NOTIFY bedTargetTemperatureChanged); - Q_PROPERTY(float extruderTemperature READ extruderTemperature WRITE setExtruderTemperature NOTIFY extruderTemperatureChanged); - Q_PROPERTY(float extruderTargetTemperature READ extruderTargetTemperature WRITE setExtruderTargetTemperature NOTIFY extruderTargetTemperatureChanged); + Q_PROPERTY(float bedTemperature READ bedTemperature WRITE setBedTemperature NOTIFY bedTemperatureChanged) + Q_PROPERTY(float bedTargetTemperature READ bedTargetTemperature WRITE setBedTargetTemperature NOTIFY bedTargetTemperatureChanged) + Q_PROPERTY(float extruderTemperature READ extruderTemperature WRITE setExtruderTemperature NOTIFY extruderTemperatureChanged) + Q_PROPERTY(float extruderTargetTemperature READ extruderTargetTemperature WRITE setExtruderTargetTemperature NOTIFY extruderTargetTemperatureChanged) public: /** * @brief Create a new Temperature object * @param parent */ Temperature(QObject *parent = nullptr); /** * @brief Get bed current temperature */ float bedTemperature() const; /** * @brief Get bed target temperature */ float bedTargetTemperature() const; /** * @brief Get extruder temperature */ float extruderTemperature() const; /** * @brief Get extruder target temperature */ float extruderTargetTemperature() const; /** * @brief decode Temp values from string \p msg * @param msg: string to read vaules from */ void decodeTemp(const QByteArray &msg); public slots: /** * @brief Set bed temperature * @param temp: bed temperature */ void setBedTemperature(float temp); /** * @brief Set bed target temperature * @param temp: bed target temperature */ void setBedTargetTemperature(float temp); /** * @brief Set exturder temperature * @param temp: bed temperature */ void setExtruderTemperature(float temp); /** * @brief Set extruder target temperature * @param temp: extruder target temperature */ void setExtruderTargetTemperature(float temp); signals: /** * @brief bed temperature has changed * @param temp : new bed temperature */ void bedTemperatureChanged(float temp); /** * @brief bed target temperature has changed * @param temp : new bed target temperature */ void bedTargetTemperatureChanged(float temp); /** * @brief extruder temperature has changed * @param temp : new extruder temperature */ void extruderTemperatureChanged(float temp); /** * @brief extruder target temperature has changed * @param temp : new extruder target temperature */ void extruderTargetTemperatureChanged(float temp); private: TemperaturePrivate *d; }; diff --git a/testclient/mainwindow.cpp b/testclient/mainwindow.cpp index 3b70905..a96cd0f 100644 --- a/testclient/mainwindow.cpp +++ b/testclient/mainwindow.cpp @@ -1,554 +1,554 @@ /* AtCore Test Client Copyright (C) <2016> Authors: Patrick José Pereira Lays Rodrigues Chris Rizzitello Tomaz Canabrava This program 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. 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 . */ #include #include #include #include #include #include "mainwindow.h" #include "seriallayer.h" #include "gcodecommands.h" #include "widgets/axiscontrol.h" -Q_LOGGING_CATEGORY(TESTCLIENT_MAINWINDOW, "org.kde.atelier.core"); +Q_LOGGING_CATEGORY(TESTCLIENT_MAINWINDOW, "org.kde.atelier.core") int MainWindow::fanCount = 4; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), core(new AtCore(this)), logFile(new QTemporaryFile(QDir::tempPath() + QStringLiteral("/AtCore_"))) { ui->setupUi(this); ui->serialPortCB->setEditable(true); QValidator *validator = new QIntValidator(); ui->baudRateLE->setValidator(validator); ui->baudRateLE->addItems(core->portSpeeds()); ui->baudRateLE->setCurrentIndex(9); ui->pluginCB->addItem(tr("Autodetect")); ui->pluginCB->addItems(core->availableFirmwarePlugins()); AxisControl *axisControl = new AxisControl; ui->moveDockContents->layout()->addWidget(axisControl); addLog(tr("Attempting to locate Serial Ports")); core->setSerialTimerInterval(1000); populateCBs(); //Icon for actionQuit #ifndef Q_OS_MAC ui->actionQuit->setIcon(QIcon::fromTheme(QStringLiteral("application-exit"))); #endif //hide the printing progress bar. ui->printLayout->setVisible(false); ui->statusBar->addWidget(ui->statusBarWidget); printTime = new QTime(); printTimer = new QTimer(); printTimer->setInterval(1000); printTimer->setSingleShot(false); connect(printTimer, &QTimer::timeout, this, &MainWindow::updatePrintTime); connect(ui->connectPB, &QPushButton::clicked, this, &MainWindow::connectPBClicked); connect(ui->saveLogPB, &QPushButton::clicked, this, &MainWindow::saveLogPBClicked); connect(ui->sendPB, &QPushButton::clicked, this, &MainWindow::sendPBClicked); connect(ui->commandLE, &QLineEdit::returnPressed, this, &MainWindow::sendPBClicked); connect(ui->homeAllPB, &QPushButton::clicked, this, &MainWindow::homeAllPBClicked); connect(ui->homeXPB, &QPushButton::clicked, this, &MainWindow::homeXPBClicked); connect(ui->homeYPB, &QPushButton::clicked, this, &MainWindow::homeYPBClicked); connect(ui->homeZPB, &QPushButton::clicked, this, &MainWindow::homeZPBClicked); connect(ui->bedTempPB, &QPushButton::clicked, this, &MainWindow::bedTempPBClicked); connect(ui->extTempPB, &QPushButton::clicked, this, &MainWindow::extTempPBClicked); connect(ui->mvAxisPB, &QPushButton::clicked, this, &MainWindow::mvAxisPBClicked); connect(ui->fanSpeedPB, &QPushButton::clicked, this, &MainWindow::fanSpeedPBClicked); connect(ui->printPB, &QPushButton::clicked, this, &MainWindow::printPBClicked); connect(ui->printerSpeedPB, &QPushButton::clicked, this, &MainWindow::printerSpeedPBClicked); connect(ui->flowRatePB, &QPushButton::clicked, this, &MainWindow::flowRatePBClicked); connect(ui->showMessagePB, &QPushButton::clicked, this, &MainWindow::showMessage); connect(ui->pluginCB, &QComboBox::currentTextChanged, this, &MainWindow::pluginCBChanged); connect(core, &AtCore::stateChanged, this, &MainWindow::printerStateChanged); connect(this, &MainWindow::printFile, core, &AtCore::print); connect(ui->stopPB, &QPushButton::clicked, core, &AtCore::stop); connect(ui->emergencyStopPB, &QPushButton::clicked, core, &AtCore::emergencyStop); connect(axisControl, &AxisControl::clicked, this, &MainWindow::axisControlClicked); connect(core, &AtCore::portsChanged, this, &MainWindow::locateSerialPort); connect(core, &AtCore::printProgressChanged, this, &MainWindow::printProgressChanged); connect(&core->temperature(), &Temperature::bedTemperatureChanged, [ = ](float temp) { checkTemperature(0x00, 0, temp); ui->plotWidget->appendPoint(tr("Actual Bed"), temp); ui->plotWidget->update(); }); connect(&core->temperature(), &Temperature::bedTargetTemperatureChanged, [ = ](float temp) { checkTemperature(0x01, 0, temp); ui->plotWidget->appendPoint(tr("Target Bed"), temp); ui->plotWidget->update(); }); connect(&core->temperature(), &Temperature::extruderTemperatureChanged, [ = ](float temp) { checkTemperature(0x02, 0, temp); ui->plotWidget->appendPoint(tr("Actual Ext.1"), temp); ui->plotWidget->update(); }); connect(&core->temperature(), &Temperature::extruderTargetTemperatureChanged, [ = ](float temp) { checkTemperature(0x03, 0, temp); ui->plotWidget->appendPoint(tr("Target Ext.1"), temp); ui->plotWidget->update(); }); connect(ui->actionQuit, &QAction::triggered, this, &MainWindow::close); connect(ui->actionShowDockTitles, &QAction::toggled, this, &MainWindow::toggleDockTitles); ui->menuView->insertAction(nullptr, ui->connectDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->tempControlsDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->commandDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->printDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->moveDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->tempTimelineDock->toggleViewAction()); ui->menuView->insertAction(nullptr, ui->logDock->toggleViewAction()); //more dock stuff. setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North); setTabPosition(Qt::RightDockWidgetArea, QTabWidget::North); tabifyDockWidget(ui->moveDock, ui->tempControlsDock); ui->moveDock->raise(); tabifyDockWidget(ui->connectDock, ui->printDock); tabifyDockWidget(ui->connectDock, ui->commandDock); ui->connectDock->raise(); setCentralWidget(nullptr); } void MainWindow::closeEvent(QCloseEvent *event) { core->close(); event->accept(); } MainWindow::~MainWindow() { delete logFile; delete ui; } QString MainWindow::getTime() { return QTime::currentTime().toString(QStringLiteral("hh:mm:ss:zzz")); } QString MainWindow::logHeader() { return QStringLiteral("[%1] ").arg(getTime()); } QString MainWindow::rLogHeader() { return QStringLiteral("[%1]< ").arg(getTime()); } QString MainWindow::sLogHeader() { return QStringLiteral("[%1]> ").arg(getTime()); } void MainWindow::writeTempFile(QString text) { /* A QTemporaryFile will always be opened in QIODevice::ReadWrite mode, this allows easy access to the data in the file. This function will return true upon success and will set the fileName() to the unique filename used. */ logFile->open(); logFile->seek(logFile->size()); logFile->write(text.toLatin1()); logFile->putChar('\n'); logFile->close(); } void MainWindow::addLog(QString msg) { QString message(logHeader() + msg); ui->logTE->appendPlainText(message); writeTempFile(message); } void MainWindow::addRLog(QString msg) { QString message(rLogHeader() + msg); ui->logTE->appendPlainText(message); writeTempFile(message); } void MainWindow::addSLog(QString msg) { QString message(sLogHeader() + msg); ui->logTE->appendPlainText(message); writeTempFile(message); } void MainWindow::checkReceivedCommand(const QByteArray &message) { addRLog(QString::fromUtf8(message)); } void MainWindow::checkPushedCommands(QByteArray bmsg) { QString msg = QString::fromUtf8(bmsg); QRegExp _newLine(QChar::fromLatin1('\n')); QRegExp _return(QChar::fromLatin1('\r')); msg.replace(_newLine, QStringLiteral("\\n")); msg.replace(_return, QStringLiteral("\\r")); addSLog(msg); } void MainWindow::checkTemperature(uint sensorType, uint number, uint temp) { QString msg; switch (sensorType) { case 0x00: // bed msg = QString::fromLatin1("Bed Temperature "); break; case 0x01: // bed target msg = QString::fromLatin1("Bed Target Temperature "); break; case 0x02: // extruder msg = QString::fromLatin1("Extruder Temperature "); break; case 0x03: // extruder target msg = QString::fromLatin1("Extruder Target Temperature "); break; case 0x04: // enclosure msg = QString::fromLatin1("Enclosure Temperature "); break; case 0x05: // enclosure target msg = QString::fromLatin1("Enclosure Target Temperature "); break; } msg.append(QString::fromLatin1("[%1] : %2")); msg = msg.arg(QString::number(number)) .arg(QString::number(temp)); addRLog(msg); } /** * @brief MainWindow::locateSerialPort * Locate all active serial ports on the computer and add to the list * of serial ports */ void MainWindow::locateSerialPort(const QStringList &ports) { ui->serialPortCB->clear(); if (!ports.isEmpty()) { ui->serialPortCB->addItems(ports); addLog(tr("Found %1 Ports").arg(QString::number(ports.count()))); } else { QString portError(tr("No available ports! Please connect a serial device to continue!")); if (! ui->logTE->toPlainText().endsWith(portError)) { addLog(portError); } } } void MainWindow::connectPBClicked() { if (core->state() == AtCore::DISCONNECTED) { core->initSerial(ui->serialPortCB->currentText(), ui->baudRateLE->currentText().toInt()); connect(core, &AtCore::receivedMessage, this, &MainWindow::checkReceivedCommand); connect(core->serial(), &SerialLayer::pushedCommand, this, &MainWindow::checkPushedCommands); addLog(tr("Serial connected")); ui->connectPB->setText(tr("Disconnect")); if (core->state() == AtCore::CONNECTING) { if (ui->pluginCB->currentText().contains(tr("Autodetect"))) { addLog(tr("No plugin loaded !")); addLog(tr("Requesting Firmware...")); core->detectFirmware(); } else { core->loadFirmwarePlugin(ui->pluginCB->currentText()); } } } else { core->closeConnection(); core->setState(AtCore::DISCONNECTED); addLog(tr("Disconnected")); ui->connectPB->setText(tr("Connect")); } } void MainWindow::sendPBClicked() { QString comm = ui->commandLE->text().toUpper(); core->pushCommand(comm); ui->commandLE->clear(); } void MainWindow::homeAllPBClicked() { addSLog(tr("Home All")); core->home(); } void MainWindow::homeXPBClicked() { addSLog(tr("Home X")); core->home(AtCore::X); } void MainWindow::homeYPBClicked() { addSLog(tr("Home Y")); core->home(AtCore::Y); } void MainWindow::homeZPBClicked() { addSLog(tr("Home Z")); core->home(AtCore::Z); } void MainWindow::bedTempPBClicked() { addSLog(GCode::toString(GCode::M140)); core->setBedTemp(ui->bedTempSB->value()); } void MainWindow::extTempPBClicked() { addSLog(GCode::toString(GCode::M104)); core->setExtruderTemp(ui->extTempSB->value(), ui->extTempSelCB->currentIndex()); } void MainWindow::mvAxisPBClicked() { addSLog(GCode::toString(GCode::G1)); if (ui->mvAxisCB->currentIndex() == 0) { core->move(AtCore::X, ui->mvAxisSB->value()); } else if (ui->mvAxisCB->currentIndex() == 1) { core->move(AtCore::Y, ui->mvAxisSB->value()); } else if (ui->mvAxisCB->currentIndex() == 2) { core->move(AtCore::Z, ui->mvAxisSB->value()); } } void MainWindow::fanSpeedPBClicked() { addSLog(GCode::toString(GCode::M106)); core->setFanSpeed(ui->fanSpeedSB->value(), ui->fanSpeedSelCB->currentIndex()); } void MainWindow::printPBClicked() { QString fileName; switch (core->state()) { case AtCore::DISCONNECTED: QMessageBox::information(this, tr("Error"), tr("Not Connected To a Printer")); break; case AtCore::CONNECTING: QMessageBox::information(this, tr("Error"), tr(" A Firmware Plugin was not loaded!\n Please send the command M115 and let us know what your firmware returns, so we can improve our firmware detection. We have loaded the most common plugin \"repetier\" for you. You may try to print again after this message")); ui->pluginCB->setCurrentText(QStringLiteral("repetier")); break; case AtCore::IDLE: fileName = QFileDialog::getOpenFileName(this, tr("Select a file to print"), QDir::homePath(), QStringLiteral("*.gcode")); if (fileName.isNull()) { addLog(tr("No File Selected")); } else { addLog(tr("Print: %1").arg(fileName)); emit(printFile(fileName)); } break; case AtCore::BUSY: core->pause(ui->postPauseLE->text()); break; case AtCore::PAUSE: core->resume(); break; default: qCDebug(TESTCLIENT_MAINWINDOW) << "ERROR / STOP unhandled."; } } void MainWindow::saveLogPBClicked() { // Note that if a file with the name newName already exists, copy() returns false (i.e. QFile will not overwrite it). QString fileName = QDir::homePath() + QChar::fromLatin1('/') + QFileInfo(logFile->fileName()).fileName() + QStringLiteral(".txt"); QString saveFileName = QFileDialog::getSaveFileName(this, tr("Save Log to file"), fileName); QFile::copy(logFile->fileName(), saveFileName); logFile->close(); } void MainWindow::pluginCBChanged(QString currentText) { if (core->state() != AtCore::DISCONNECTED) { if (!currentText.contains(tr("Autodetect"))) { core->loadFirmwarePlugin(currentText); } else { core->detectFirmware(); } } } void MainWindow::flowRatePBClicked() { core->setFlowRate(ui->flowRateSB->value()); } void MainWindow::printerSpeedPBClicked() { core->setPrinterSpeed(ui->printerSpeedSB->value()); } void MainWindow::printerStateChanged(AtCore::STATES state) { QString stateString; switch (state) { case AtCore::IDLE: ui->printPB->setText(tr("Print File")); stateString = QStringLiteral("Connected to ") + core->connectedPort(); break; case AtCore::STARTPRINT: stateString = QStringLiteral("START PRINT"); ui->printPB->setText(tr("Pause Print")); ui->printLayout->setVisible(true); printTime->start(); printTimer->start(); break; case AtCore::FINISHEDPRINT: stateString = QStringLiteral("Finished Print"); ui->printPB->setText(tr("Print File")); ui->printLayout->setVisible(false); printTimer->stop(); break; case AtCore::PAUSE: stateString = QStringLiteral("Paused"); ui->printPB->setText(tr("Resume Print")); break; case AtCore::BUSY: stateString = QStringLiteral("Printing"); ui->printPB->setText(tr("Pause Print")); break; case AtCore::DISCONNECTED: stateString = QStringLiteral("Not Connected"); ui->commandDock->setDisabled(true); ui->moveDock->setDisabled(true); ui->tempControlsDock->setDisabled(true); ui->printDock->setDisabled(true); break; case AtCore::CONNECTING: stateString = QStringLiteral("Connecting"); ui->commandDock->setDisabled(false); ui->moveDock->setDisabled(false); ui->tempControlsDock->setDisabled(false); ui->printDock->setDisabled(false); break; case AtCore::STOP: stateString = QStringLiteral("Stoping Print"); break; case AtCore::ERRORSTATE: stateString = QStringLiteral("Command ERROR"); break; } ui->lblState->setText(stateString); } void MainWindow::populateCBs() { // Extruders for (int count = 0; count < core->extruderCount(); count++) { ui->extTempSelCB->insertItem(count, tr("Extruder %1").arg(count)); } // Fan for (int count = 0; count < fanCount; count++) { ui->fanSpeedSelCB->insertItem(count, tr("Fan %1 speed").arg(count)); } } void MainWindow::showMessage() { core->showMessage(ui->messageLE->text()); } void MainWindow::updatePrintTime() { QTime temp(0, 0, 0); ui->time->setText(temp.addMSecs(printTime->elapsed()).toString(QStringLiteral("hh:mm:ss"))); } void MainWindow::printProgressChanged(int progress) { ui->printingProgress->setValue(progress); if (progress > 0) { QTime temp(0, 0, 0); ui->timeLeft->setText(temp.addMSecs((100 - progress) * (printTime->elapsed() / progress)).toString(QStringLiteral("hh:mm:ss"))); } else { ui->timeLeft->setText(QStringLiteral("??:??:??")); } } void MainWindow::toggleDockTitles() { if (ui->actionShowDockTitles->isChecked()) { delete ui->connectDock->titleBarWidget(); delete ui->logDock->titleBarWidget(); delete ui->tempTimelineDock->titleBarWidget(); delete ui->commandDock->titleBarWidget(); delete ui->moveDock->titleBarWidget(); delete ui->tempControlsDock->titleBarWidget(); delete ui->printDock->titleBarWidget(); } else { ui->connectDock->setTitleBarWidget(new QWidget()); ui->logDock->setTitleBarWidget(new QWidget()); ui->tempTimelineDock->setTitleBarWidget(new QWidget()); ui->commandDock->setTitleBarWidget(new QWidget()); ui->moveDock->setTitleBarWidget(new QWidget()); ui->tempControlsDock->setTitleBarWidget(new QWidget()); ui->printDock->setTitleBarWidget(new QWidget()); } } void MainWindow::axisControlClicked(QChar axis, int value) { core->setRelativePosition(); core->pushCommand(GCode::toCommand(GCode::G1, QStringLiteral("%1%2").arg(axis, QString::number(value)))); core->setAbsolutePosition(); }