diff --git a/src/core/atcore.h b/src/core/atcore.h --- a/src/core/atcore.h +++ b/src/core/atcore.h @@ -470,6 +470,13 @@ */ void sdCardPrintStatus(); + /** + * @brief Write a file to the machines SdCard + * @param fileName: Local file to send to machine + * @return True if successful + */ + bool writeFiletoSd(const QString &fileName); + private slots: /** * @brief processQueue send commands from the queue. diff --git a/src/core/atcore.cpp b/src/core/atcore.cpp --- a/src/core/atcore.cpp +++ b/src/core/atcore.cpp @@ -780,3 +780,47 @@ } pushCommand(GCode::toCommand(GCode::M27)); } + +bool AtCore::writeFiletoSd(const QString &fileName) +{ + //Do a few sanity checks before attempting to write to SD. + + //Can't write an empty fileName. + if (fileName.isEmpty()) { + return false; + } + //Can not write if plugin doesn't have Sd Support. + if (!d->firmwarePlugin->isSdSupported()) { + return false; + } + + //If the card is not mounted try to read the file list and mount it. + if (!d->sdCardMounted) { + getSDFileList(); + if (!d->sdCardMounted) { + return false; + } + } + // Be sure the printer is IDLE + if (d->printerState != AtCore::IDLE) { + return false; + } + + QString fname = fileName.mid(fileName.lastIndexOf(QStringLiteral("/")) + 1, fileName.length()); + QFile *file = new QFile(fileName); + file->open(QFile::ReadOnly); + QTextStream *txtStream = new QTextStream(file); + + setState(AtCore::BUSY); + pushCommand(GCode::toCommand(GCode::M28, fname)); + + while (!txtStream->atEnd()) { + pushCommand(txtStream->readLine()); + } + + file->close(); + pushCommand(GCode::toCommand(GCode::M29, fname)); + setState(AtCore::IDLE); + getSDFileList(); + return true; +} diff --git a/src/plugins/marlinplugin.h b/src/plugins/marlinplugin.h --- a/src/plugins/marlinplugin.h +++ b/src/plugins/marlinplugin.h @@ -55,9 +55,26 @@ */ QString name() const override; + /** + * @brief Translate common commands to firmware specific command. + * @param command: command to translate + * @return firmware specific translated command + */ + QByteArray translate(const QString &command) override; + /** * @brief validateCommand to filter commands from messages * @param lastMessage: last Message from printer */ void validateCommand(const QString &lastMessage) override; + +private: + /** + * @brief Convert a filename to 8.3 Because Marlin will only accept those, Generates a 8.3 like Filename. + * This is Close to but not a 8.3 filename for instance we do not check the Filesystem so ~# will not be added if files with similar names are on the sd card + * Marlin will overwrite files with the samename. + * @param fileName: to convert to 8.3 format. + * @return Return a 8.3 Format name + */ + QString to83(const QString &fileName); }; diff --git a/src/plugins/marlinplugin.cpp b/src/plugins/marlinplugin.cpp --- a/src/plugins/marlinplugin.cpp +++ b/src/plugins/marlinplugin.cpp @@ -45,6 +45,23 @@ qCDebug(MARLIN_PLUGIN) << name() << " plugin loaded!"; } +QByteArray MarlinPlugin::translate(const QString &command) +{ + QString temp = command; + if (command.contains(QStringLiteral("M28"))) { + QString filename = temp.mid(4, temp.length()); + filename = to83(filename); + temp = QStringLiteral("M28 %1").arg(filename); + + } else if (command.contains(QStringLiteral("M29"))) { + QString filename = temp.mid(4, temp.length()); + filename = to83(filename); + temp = QStringLiteral("M29 %1").arg(filename); + } + + return temp.toLocal8Bit(); +} + void MarlinPlugin::validateCommand(const QString &lastMessage) { if (lastMessage.contains(QStringLiteral("End file list"))) { @@ -96,3 +113,19 @@ } } } + +QString MarlinPlugin::to83(const QString &fileName) +{ + //Generate an 8.3 Like FileName. + QString newName; + if (fileName.lastIndexOf(QStringLiteral(".") < 9)) { + newName = fileName.mid(0, fileName.lastIndexOf(QStringLiteral("."))); + } else { + newName = fileName.mid(0, 8); + } + if (newName.length() > 8) { + newName.resize(8); + } + newName = newName.append(fileName.mid(fileName.lastIndexOf(QStringLiteral(".")), 4)); + return newName.toUpper(); +} diff --git a/src/widgets/sdwidget.h b/src/widgets/sdwidget.h --- a/src/widgets/sdwidget.h +++ b/src/widgets/sdwidget.h @@ -52,6 +52,11 @@ */ void printSdFile(const QString &fileName); + /** + * @brief User has selected to write a file for the sd card. + */ + void writeSdFile(); + /** * @brief User has selected to delete a file for the sd card. * @param fileName: file to delete diff --git a/src/widgets/sdwidget.cpp b/src/widgets/sdwidget.cpp --- a/src/widgets/sdwidget.cpp +++ b/src/widgets/sdwidget.cpp @@ -15,6 +15,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#include #include #include #include @@ -42,6 +43,12 @@ } }); + newButton = new QPushButton(tr("Send File")); + hBoxLayout->addWidget(newButton); + connect(newButton, &QPushButton::clicked, this, [this] { + emit writeSdFile(); + }); + newButton = new QPushButton(tr("Delete Selected")); hBoxLayout->addWidget(newButton); connect(newButton, &QPushButton::clicked, this, [this] { diff --git a/testclient/mainwindow.h b/testclient/mainwindow.h --- a/testclient/mainwindow.h +++ b/testclient/mainwindow.h @@ -136,6 +136,11 @@ */ void initWidgets(); + /** + * @brief Handle WriteToSd + */ + void writeToSd(); + //Private GUI Items //menuView is global to allow for docks to be added / removed. QMenu *menuView = nullptr; diff --git a/testclient/mainwindow.cpp b/testclient/mainwindow.cpp --- a/testclient/mainwindow.cpp +++ b/testclient/mainwindow.cpp @@ -53,6 +53,7 @@ connect(core, &AtCore::stateChanged, this, &MainWindow::printerStateChanged); connect(core, &AtCore::portsChanged, this, &MainWindow::locateSerialPort); connect(core, &AtCore::sdCardFileListChanged, sdWidget, &SdWidget::updateFilelist); + connect(sdWidget, &SdWidget::writeSdFile, this, &MainWindow::writeToSd); } void MainWindow::initMenu() @@ -568,3 +569,22 @@ printWidget->updateFanCount(fanCount); } } +void MainWindow::writeToSd() +{ + static QString filter = tr("GCode Files(*.gco *.gcode)"); + QString fileName = QFileDialog::getOpenFileName( + this + , tr("Write file to SD") + , QDir::homePath() + , tr("All Files(*.*);;GCode Files(*.gco *.gcode)") + , &filter + ); + + if (!fileName.isEmpty()) { + if (core->writeFiletoSd(fileName)) { + QMessageBox::information(this, tr("Write to Sd"), tr("Writing Finished")); + } else { + QMessageBox::warning(this, tr("Write to Sd"), tr("Writing FAILED")); + } + } +}