1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-09-02 02:42:36 +02:00

Fixed SDCard config

This commit is contained in:
Stefan de Bruijn
2021-05-26 12:40:27 +02:00
parent 8df0d4daa8
commit e96308c11b
12 changed files with 146 additions and 129 deletions

View File

@@ -403,7 +403,7 @@ void MachineConfig::afterParse() {
}
if (_sdCard == nullptr) {
_sdCard = new SDCardPin();
_sdCard = new SDCard();
}
if (_control == nullptr) {

View File

@@ -26,7 +26,7 @@
#include "WebUI/BTConfig.h"
#include "Control.h"
#include "Probe.h"
#include "SDCardPin.h"
#include "SDCard.h"
#include "Spindles/Spindle.h"
// TODO FIXME: Split this file up into several files, perhaps put it in some folder and namespace Machine?
@@ -374,7 +374,7 @@ public:
Communications* _comms = nullptr;
Control* _control = nullptr;
UserOutputs* _userOutputs = nullptr;
SDCardPin* _sdCard = nullptr;
SDCard* _sdCard = nullptr;
Spindles::Spindle* _spindle = nullptr;
int _pulseMicroSeconds = 3;

View File

@@ -546,10 +546,10 @@ void mc_reset() {
sys_analog_all_off();
#ifdef ENABLE_SD_CARD
// do we need to stop a running SD job?
if (sdCard.get_state(false) == SDCard::State::BusyPrinting) {
if (config->_sdCard->get_state(false) == SDCard::State::BusyPrinting) {
//Report print stopped
report_feedback_message(Message::SdFileQuit);
sdCard.closeFile();
config->_sdCard->closeFile();
}
#endif
// Kill steppers only if in any motion state, i.e. cycle, actively holding, or homing.

View File

@@ -140,16 +140,17 @@ void protocol_main_loop() {
int c;
for (;;) {
#ifdef ENABLE_SD_CARD
if (sdCard._ready_next) {
auto sdcard = config->_sdCard;
if (sdcard->_ready_next) {
char fileLine[255];
if (sdCard.readFileLine(fileLine, 255)) {
sdCard._ready_next = false;
report_status_message(execute_line(fileLine, sdCard._client, sdCard._auth_level), sdCard._client);
if (sdcard->readFileLine(fileLine, 255)) {
sdcard->_ready_next = false;
report_status_message(execute_line(fileLine, sdcard->_client, sdcard->_auth_level), sdcard->_client);
} else {
char temp[50];
sdCard.get_current_filename(temp);
sdcard->get_current_filename(temp);
grbl_notifyf("SD print done", "%s print is successful", temp);
sdCard.closeFile(); // close file and clear SD ready/running flags
sdcard->closeFile(); // close file and clear SD ready/running flags
}
}
#endif

View File

@@ -204,11 +204,12 @@ static String report_util_axis_values(const float* axis_value) {
// from a critical error, such as a triggered hard limit. Interface should always monitor for these
// responses.
void report_status_message(Error status_code, uint8_t client) {
auto sdCard = config->_sdCard;
switch (status_code) {
case Error::Ok: // Error::Ok
#ifdef ENABLE_SD_CARD
if (sdCard.get_state(false) == SDCard::State::BusyPrinting) {
sdCard._ready_next = true; // flag so system_execute_line() will send the next line
if (sdCard->get_state(false) == SDCard::State::BusyPrinting) {
sdCard->_ready_next = true; // flag so system_execute_line() will send the next line
} else {
grbl_send(client, "ok\r\n");
}
@@ -219,16 +220,16 @@ void report_status_message(Error status_code, uint8_t client) {
default:
#ifdef ENABLE_SD_CARD
// do we need to stop a running SD job?
if (sdCard.get_state(false) == SDCard::State::BusyPrinting) {
if (sdCard->get_state(false) == SDCard::State::BusyPrinting) {
if (status_code == Error::GcodeUnsupportedCommand) {
grbl_sendf(client, "error:%d\r\n", status_code); // most senders seem to tolerate this error and keep on going
grbl_sendf(CLIENT_ALL, "error:%d in SD file at line %d\r\n", status_code, sdCard.get_current_line_number());
grbl_sendf(CLIENT_ALL, "error:%d in SD file at line %d\r\n", status_code, sdCard->get_current_line_number());
// don't close file
sdCard._ready_next = true; // flag so system_execute_line() will send the next line
sdCard->_ready_next = true; // flag so system_execute_line() will send the next line
} else {
grbl_notifyf("SD print error", "Error:%d during SD file at line: %d", status_code, sdCard.get_current_line_number());
grbl_sendf(CLIENT_ALL, "error:%d in SD file at line %d\r\n", status_code, sdCard.get_current_line_number());
sdCard.closeFile();
grbl_notifyf("SD print error", "Error:%d during SD file at line: %d", status_code, sdCard->get_current_line_number());
grbl_sendf(CLIENT_ALL, "error:%d in SD file at line %d\r\n", status_code, sdCard->get_current_line_number());
sdCard->closeFile();
}
return;
}
@@ -274,8 +275,8 @@ std::map<Message, const char*> MessageText = {
void report_feedback_message(Message message) { // ok to send to all clients
#if defined(ENABLE_SD_CARD)
if (message == Message::SdFileQuit) {
grbl_notifyf("SD print canceled", "Reset during SD file at line: %d", sdCard.get_current_line_number());
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Reset during SD file at line: %d", sdCard.get_current_line_number());
grbl_notifyf("SD print canceled", "Reset during SD file at line: %d", config->_sdCard->get_current_line_number());
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Reset during SD file at line: %d", config->_sdCard->get_current_line_number());
} else
#endif //ENABLE_SD_CARD
@@ -740,10 +741,10 @@ void report_realtime_status(uint8_t client) {
}
}
#ifdef ENABLE_SD_CARD
if (sdCard.get_state(false) == SDCard::State::BusyPrinting) {
sprintf(temp, "|SD:%4.2f,", sdCard.report_perc_complete());
if (config->_sdCard->get_state(false) == SDCard::State::BusyPrinting) {
sprintf(temp, "|SD:%4.2f,", config->_sdCard->report_perc_complete());
strcat(status, temp);
sdCard.get_current_filename(temp);
config->_sdCard->get_current_filename(temp);
strcat(status, temp);
}
#endif

View File

@@ -19,14 +19,21 @@
*/
#include "Config.h"
#ifdef ENABLE_SD_CARD
# include "SDCard.h"
# include "MachineConfig.h"
SDCard sdCard;
#include "SDCard.h"
#include "MachineConfig.h"
#include <FS.h>
#include <SD.h>
#include <SPI.h>
struct SDCard::FileWrap {
FileWrap() : _file(nullptr) {}
File _file;
};
SDCard::SDCard() :
_file(nullptr), _current_line_number(0), _state(State::Idle), _readyNext(false), _client(CLIENT_SERIAL),
_pImpl(new FileWrap()), _current_line_number(0), _state(State::Idle), _readyNext(false), _client(CLIENT_SERIAL),
_auth_level(WebUI::AuthenticationLevel::LEVEL_GUEST) {}
// attempt to mount the SD card
@@ -64,8 +71,8 @@ void SDCard::listDir(fs::FS& fs, const char* dirname, uint8_t levels, uint8_t cl
}
bool SDCard::openFile(fs::FS& fs, const char* path) {
_file = fs.open(path);
if (!_file) {
_pImpl->_file = fs.open(path);
if (!_pImpl->_file) {
//report_status_message(Error::FsFailedRead, CLIENT_SERIAL);
return false;
}
@@ -76,13 +83,13 @@ bool SDCard::openFile(fs::FS& fs, const char* path) {
}
bool SDCard::closeFile() {
if (!_file) {
if (!_pImpl->_file) {
return false;
}
set_state(State::Idle);
_readyNext = false;
_current_line_number = 0;
_file.close();
_pImpl->_file.close();
SD.end();
return true;
}
@@ -95,32 +102,33 @@ bool SDCard::closeFile() {
return true if a line is
*/
bool SDCard::readFileLine(char* line, int maxlen) {
if (!_file) {
if (!_pImpl->_file) {
report_status_message(Error::FsFailedRead, _client);
return false;
}
_current_line_number += 1;
int len = 0;
while (_file.available()) {
while (_pImpl->_file.available()) {
if (len >= maxlen) {
return false;
}
char c = _file.read();
char c = _pImpl->_file.read();
if (c == '\n') {
break;
}
line[len++] = c;
}
line[len] = '\0';
return len || _file.available();
return len || _pImpl->_file.available();
}
// return a percentage complete 50.5 = 50.5%
float SDCard::report_perc_complete() {
if (!_file) {
if (!_pImpl->_file) {
return 0.0;
}
return (float)_file.position() / (float)_file.size() * 100.0f;
return (float)_pImpl->_file.position() / (float)_pImpl->_file.size() * 100.0f;
}
uint32_t SDCard::get_current_line_number() {
@@ -176,10 +184,32 @@ SDCard::State SDCard::set_state(SDCard::State state) {
}
void SDCard::get_current_filename(char* name) {
if (_file) {
strcpy(name, _file.name());
if (_pImpl->_file) {
strcpy(name, _pImpl->_file.name());
} else {
name[0] = 0;
}
}
#endif //ENABLE_SD_CARD
void SDCard::init() {
static bool init_message = true; // used to show messages only once.
if (init_message) {
if (_cardDetect.defined()) {
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "SD Card Detect on pin %s", _cardDetect.name().c_str());
}
init_message = false;
}
_cardDetect.setAttr(Pin::Attr::Output);
}
void SDCard::validate() const {}
void SDCard::handle(Configuration::HandlerBase& handler) {
handler.handle("card_detect", _cardDetect);
}
SDCard::~SDCard() {
delete _pImpl;
}

View File

@@ -15,12 +15,17 @@
* D1 -
*/
#include "Grbl.h"
#include <FS.h>
#include <SD.h>
#include <SPI.h>
#include <cstdint>
#include "Configuration/Configurable.h"
#include "WebUI/Authentication.h"
#include "Pin.h"
class SDCard {
// Forward declaration:
namespace fs {
class FS;
}
class SDCard : public Configuration::Configurable {
public:
enum class State : uint8_t {
Idle = 0,
@@ -31,12 +36,17 @@ public:
BusyParsing = 4,
};
class FileWrap; // holds a single 'File'; we don't want to include <FS.h> here
private:
File _file;
uint32_t _current_line_number; // the most recent line number read
char comment[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated.
static const int COMMENT_SIZE = 256;
FileWrap* _pImpl; // this is actually a 'File'; we don't want to include <FS.h>
uint32_t _current_line_number; // the most recent line number read
char comment[COMMENT_SIZE]; // Line to be executed. Zero-terminated.
State _state;
Pin _cardDetect;
public:
bool _readyNext;
@@ -44,20 +54,29 @@ public:
WebUI::AuthenticationLevel _auth_level;
SDCard();
SDCard(const SDCard&) = delete;
SDCard& operator=(const SDCard&) = delete;
bool _ready_next; // Grbl has processed a line and is waiting for another
//bool mount();
SDCard::State get_state(bool refresh);
SDCard::State set_state(SDCard::State state);
void listDir(fs::FS& fs, const char* dirname, uint8_t levels, uint8_t client);
bool openFile(fs::FS& fs, const char* path);
bool closeFile();
bool readFileLine(char* line, int len);
void readFile(fs::FS& fs, const char* path);
float report_perc_complete();
uint32_t get_current_line_number();
void get_current_filename(char* name);
~SDCard() = default;
void listDir(fs::FS& fs, const char* dirname, uint8_t levels, uint8_t client);
bool openFile(fs::FS& fs, const char* path);
bool closeFile();
bool readFileLine(char* line, int len);
float report_perc_complete();
uint32_t get_current_line_number();
void get_current_filename(char* name);
// Initializes pins.
void init();
// Configuration handlers.
void validate() const override;
void handle(Configuration::HandlerBase& handler) override;
~SDCard();
};
extern SDCard sdCard;

View File

@@ -1,21 +0,0 @@
#include "Grbl.h"
#include "SDCardPin.h"
void SDCardPin::init() {
static bool init_message = true; // used to show messages only once.
if (init_message) {
if (_cardDetect.defined()) {
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "SD Card Detect on pin %s", _cardDetect.name().c_str());
}
init_message = false;
}
_cardDetect.setAttr(Pin::Attr::Output);
}
void SDCardPin::validate() const {}
void SDCardPin::handle(Configuration::HandlerBase& handler) {
handler.handle("card_detect", _cardDetect);
}

View File

@@ -1,18 +0,0 @@
// TODO: This should be merged with SDCard.h but for now doing so
// causes strange include conflicts.
class SDCardPin : public Configuration::Configurable {
public:
Pin _cardDetect;
SDCardPin() = default;
// Initializes pins.
void init();
// Configuration handlers.
void validate() const override;
void handle(Configuration::HandlerBase& handler) override;
~SDCardPin() = default;
};

View File

@@ -162,7 +162,7 @@ void clientCheckTask(void* pvParameters) {
execute_realtime_command(static_cast<Cmd>(data), client);
} else {
#if defined(ENABLE_SD_CARD)
if (sdCard.get_state(false) < SDCard::State::Busy) {
if (config->_sdCard->get_state(false) < SDCard::State::Busy) {
#endif //ENABLE_SD_CARD
vTaskEnterCritical(&myMutex);
client_buffer[client].write(data);

View File

@@ -279,16 +279,17 @@ namespace WebUI {
# ifdef ENABLE_SD_CARD
if ((path.substring(0, 4) == "/SD/")) {
auto sdCard = config->_sdCard;
//remove /SD
path = path.substring(3);
if (SDCard::State::Idle != sdCard.get_state(true)) {
if (SDCard::State::Idle != sdCard->get_state(true)) {
String content = "cannot open: ";
content += path + ", SD is not available.";
_webserver->send(500, "text/plain", content);
}
if (SD.exists(pathWithGz) || SD.exists(path)) {
sdCard.set_state(SDCard::State::BusyUploading);
sdCard->set_state(SDCard::State::BusyUploading);
if (SD.exists(pathWithGz)) {
path = pathWithGz;
}
@@ -319,10 +320,10 @@ namespace WebUI {
if (i != totalFileSize) {
//error: TBD
}
sdCard.set_state(SDCard::State::Idle);
sdCard->set_state(SDCard::State::Idle);
return;
}
sdCard.set_state(SDCard::State::Idle);
sdCard->set_state(SDCard::State::Idle);
}
String content = "cannot find ";
content += path;
@@ -1232,7 +1233,7 @@ namespace WebUI {
bool list_files = true;
uint64_t totalspace = 0;
uint64_t usedspace = 0;
SDCard::State state = sdCard.get_state(true);
SDCard::State state = config->_sdCard->get_state(true);
if (state != SDCard::State::Idle) {
String status = "{\"status\":\"";
status += state == SDCard::State::NotPresent ? "No SD Card\"}" : "Busy\"}";
@@ -1240,7 +1241,7 @@ namespace WebUI {
_webserver->send(200, "application/json", status);
return;
}
sdCard.set_state(SDCard::State::BusyParsing);
config->_sdCard->set_state(SDCard::State::BusyParsing);
//get current path
if (_webserver->hasArg("path")) {
@@ -1333,7 +1334,7 @@ namespace WebUI {
s += " does not exist on SD Card\"}";
_webserver->send(200, "application/json", s);
SD.end();
sdCard.set_state(SDCard::State::Idle);
config->_sdCard->set_state(SDCard::State::Idle);
return;
}
if (list_files) {
@@ -1410,7 +1411,7 @@ namespace WebUI {
jsonfile += "}";
_webserver->sendHeader("Cache-Control", "no-cache");
_webserver->send(200, "application/json", jsonfile);
sdCard.set_state(SDCard::State::Idle);
config->_sdCard->set_state(SDCard::State::Idle);
SD.end();
}
@@ -1437,13 +1438,13 @@ namespace WebUI {
filename = "/" + upload.filename;
}
//check if SD Card is available
if (sdCard.get_state(true) != SDCard::State::Idle) {
if (config->_sdCard->get_state(true) != SDCard::State::Idle) {
_upload_status = UploadStatusType::FAILED;
grbl_send(CLIENT_ALL, "[MSG:Upload cancelled]\r\n");
pushError(ESP_ERROR_UPLOAD_CANCELLED, "Upload cancelled");
} else {
sdCard.set_state(SDCard::State::BusyUploading);
config->_sdCard->set_state(SDCard::State::BusyUploading);
//delete file on SD Card if already present
if (SD.exists(filename)) {
SD.remove(filename);
@@ -1477,9 +1478,10 @@ namespace WebUI {
//Upload write
//**************
} else if (upload.status == UPLOAD_FILE_WRITE) {
auto sdCard = config->_sdCard;
vTaskDelay(1 / portTICK_RATE_MS);
if (sdUploadFile && (_upload_status == UploadStatusType::ONGOING) &&
(sdCard.get_state(false) == SDCard::State::BusyUploading)) {
(sdCard->get_state(false) == SDCard::State::BusyUploading)) {
//no error write post data
if (upload.currentSize != sdUploadFile.write(upload.buf, upload.currentSize)) {
_upload_status = UploadStatusType::FAILED;
@@ -1517,7 +1519,7 @@ namespace WebUI {
}
if (_upload_status == UploadStatusType::ONGOING) {
_upload_status = UploadStatusType::SUCCESSFUL;
sdCard.set_state(SDCard::State::Idle);
config->_sdCard->set_state(SDCard::State::Idle);
} else {
_upload_status = UploadStatusType::FAILED;
pushError(ESP_ERROR_UPLOAD, "Upload error");
@@ -1525,7 +1527,7 @@ namespace WebUI {
} else { //Upload cancelled
_upload_status = UploadStatusType::FAILED;
sdCard.set_state(SDCard::State::Idle);
config->_sdCard->set_state(SDCard::State::Idle);
grbl_send(CLIENT_ALL, "[MSG:Upload failed]\r\n");
if (sdUploadFile) {
sdUploadFile.close();
@@ -1543,7 +1545,7 @@ namespace WebUI {
if (SD.exists(filename)) {
SD.remove(filename);
}
sdCard.set_state(SDCard::State::Idle);
config->_sdCard->set_state(SDCard::State::Idle);
}
COMMANDS::wait(0);
}

View File

@@ -28,6 +28,7 @@
#include <SPIFFS.h>
#include <esp_wifi.h>
#include <esp_ota_ops.h>
#include <SD.h>
#include "ESPResponse.h"
#include "WebServer.h"
@@ -678,7 +679,7 @@ namespace WebUI {
if (path[0] != '/') {
path = "/" + path;
}
SDCard::State state = sdCard.get_state(true);
SDCard::State state = config->_sdCard->get_state(true);
if (state != SDCard::State::Idle) {
if (state == SDCard::State::NotPresent) {
webPrintln("No SD Card");
@@ -688,7 +689,7 @@ namespace WebUI {
return Error::FsFailedBusy;
}
}
if (!sdCard.openFile(SD, path.c_str())) {
if (!config->_sdCard->openFile(SD, path.c_str())) {
report_status_message(Error::FsFailedRead, (espresponse) ? espresponse->client() : CLIENT_ALL);
webPrintln("");
return Error::FsFailedOpenFile;
@@ -703,13 +704,13 @@ namespace WebUI {
if ((err = openSDFile(parameter)) != Error::Ok) {
return err;
}
sdCard._client = (espresponse) ? espresponse->client() : CLIENT_ALL;
config->_sdCard->_client = (espresponse) ? espresponse->client() : CLIENT_ALL;
char fileLine[255];
while (sdCard.readFileLine(fileLine, 255)) {
while (config->_sdCard->readFileLine(fileLine, 255)) {
webPrintln(fileLine);
}
webPrintln("");
sdCard.closeFile();
config->_sdCard->closeFile();
return Error::Ok;
}
@@ -726,18 +727,20 @@ namespace WebUI {
if ((err = openSDFile(parameter)) != Error::Ok) {
return err;
}
auto sdCard = config->_sdCard;
char fileLine[255];
if (!sdCard.readFileLine(fileLine, 255)) {
if (!sdCard->readFileLine(fileLine, 255)) {
//No need notification here it is just a macro
sdCard.closeFile();
sdCard->closeFile();
webPrintln("");
return Error::Ok;
}
sdCard._client = (espresponse) ? espresponse->client() : CLIENT_ALL;
sdCard._auth_level = auth_level;
sdCard->_client = (espresponse) ? espresponse->client() : CLIENT_ALL;
sdCard->_auth_level = auth_level;
// execute the first line now; Protocol.cpp handles later ones when sdCard._ready_next
report_status_message(execute_line(fileLine, sdCard._client, sdCard._auth_level), sdCard._client);
report_realtime_status(sdCard._client);
report_status_message(execute_line(fileLine, sdCard->_client, sdCard->_auth_level), sdCard->_client);
report_realtime_status(sdCard->_client);
webPrintln("");
return Error::Ok;
}
@@ -748,7 +751,7 @@ namespace WebUI {
webPrintln("Missing file name!");
return Error::InvalidValue;
}
SDCard::State state = sdCard.get_state(true);
SDCard::State state = config->_sdCard->get_state(true);
if (state != SDCard::State::Idle) {
webPrintln((state == SDCard::State::NotPresent) ? "No SD card" : "Busy");
return Error::Ok;
@@ -780,7 +783,7 @@ namespace WebUI {
}
static Error listSDFiles(char* parameter, AuthenticationLevel auth_level) { // ESP210
SDCard::State state = sdCard.get_state(true);
SDCard::State state = config->_sdCard->get_state(true);
if (state != SDCard::State::Idle) {
if (state == SDCard::State::NotPresent) {
webPrintln("No SD Card");
@@ -791,7 +794,7 @@ namespace WebUI {
}
}
webPrintln("");
sdCard.listDir(SD, "/", 10, espresponse->client());
config->_sdCard->listDir(SD, "/", 10, espresponse->client());
String ssd = "[SD Free:" + ESPResponseStream::formatBytes(SD.totalBytes() - SD.usedBytes());
ssd += " Used:" + ESPResponseStream::formatBytes(SD.usedBytes());
ssd += " Total:" + ESPResponseStream::formatBytes(SD.totalBytes());
@@ -878,7 +881,7 @@ namespace WebUI {
static Error showSDStatus(char* parameter, AuthenticationLevel auth_level) { // ESP200
const char* resp = "No SD card";
#ifdef ENABLE_SD_CARD
switch (sdCard.get_state(true)) {
switch (config->_sdCard->get_state(true)) {
case SDCard::State::Idle:
resp = "SD card detected";
break;