mirror of
https://github.com/bdring/Grbl_Esp32.git
synced 2025-08-26 15:54:29 +02:00
$sd/show and handle settings in SD files (#629)
* $sd/show and handle settings in SD files * Added $LocalFs/Show and fixed $LocalFs/Run output * Infer / at beginning of SD path name The LocalFS path processing code already inserts a / at the beginning of the path is one isn't present. This patch does the same for SD files. * Show $ command responses in WebUI console * Added $Settings/ListChanged AKA $SC This is useful for saving settings in a compact form that leaves defaults unchanged. * $sd/show works in idle or alarm state * Apply idle/alarm checks to SPIFFS files too
This commit is contained in:
@@ -159,6 +159,16 @@ Error list_settings(const char* value, WebUI::AuthenticationLevel auth_level, We
|
||||
}
|
||||
return Error::Ok;
|
||||
}
|
||||
Error list_changed_settings(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ESPResponseStream* out) {
|
||||
for (Setting* s = Setting::List; s; s = s->next()) {
|
||||
const char* value = s->getStringValue();
|
||||
if (!auth_failed(s, value, auth_level) && strcmp(value, s->getDefaultString())) {
|
||||
show_setting(s->getName(), value, NULL, out);
|
||||
}
|
||||
}
|
||||
grbl_sendf(out->client(), "(Passwords not shown)\r\n");
|
||||
return Error::Ok;
|
||||
}
|
||||
Error list_commands(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ESPResponseStream* out) {
|
||||
for (Command* cp = Command::List; cp; cp = cp->next()) {
|
||||
const char* name = cp->getName();
|
||||
@@ -383,6 +393,7 @@ void make_grbl_commands() {
|
||||
new GrblCommand("+", "ExtendedSettings/List", report_extended_settings, notCycleOrHold);
|
||||
new GrblCommand("L", "GrblNames/List", list_grbl_names, notCycleOrHold);
|
||||
new GrblCommand("S", "Settings/List", list_settings, notCycleOrHold);
|
||||
new GrblCommand("SC","Settings/ListChanged", list_changed_settings, notCycleOrHold);
|
||||
new GrblCommand("CMD", "Commands/List", list_commands, notCycleOrHold);
|
||||
new GrblCommand("E", "ErrorCodes/List", listErrorCodes, anyState);
|
||||
new GrblCommand("G", "GCode/Modes", report_gcode, anyState);
|
||||
|
@@ -142,7 +142,7 @@ void protocol_main_loop() {
|
||||
char fileLine[255];
|
||||
if (readFileLine(fileLine, 255)) {
|
||||
SD_ready_next = false;
|
||||
report_status_message(gc_execute_line(fileLine, SD_client), SD_client);
|
||||
report_status_message(execute_line(fileLine, SD_client, SD_auth_level), SD_client);
|
||||
} else {
|
||||
char temp[50];
|
||||
sd_get_current_filename(temp);
|
||||
|
@@ -23,6 +23,7 @@
|
||||
File myFile;
|
||||
bool SD_ready_next = false; // Grbl has processed a line and is waiting for another
|
||||
uint8_t SD_client = CLIENT_SERIAL;
|
||||
WebUI::AuthenticationLevel SD_auth_level = WebUI::AuthenticationLevel::LEVEL_GUEST;
|
||||
uint32_t sd_current_line_number; // stores the most recent line number read from the SD
|
||||
static char comment[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated.
|
||||
|
||||
|
@@ -31,6 +31,7 @@ const int SDCARD_BUSY_PARSING = 8;
|
||||
|
||||
extern bool SD_ready_next; // Grbl has processed a line and is waiting for another
|
||||
extern uint8_t SD_client;
|
||||
extern WebUI::AuthenticationLevel SD_auth_level;
|
||||
|
||||
//bool sd_mount();
|
||||
uint8_t get_sd_state(bool refresh);
|
||||
|
@@ -129,6 +129,12 @@ Error IntSetting::setStringValue(char* s) {
|
||||
return Error::Ok;
|
||||
}
|
||||
|
||||
const char* IntSetting::getDefaultString() {
|
||||
static char strval[32];
|
||||
sprintf(strval, "%d", _defaultValue);
|
||||
return strval;
|
||||
}
|
||||
|
||||
const char* IntSetting::getStringValue() {
|
||||
static char strval[32];
|
||||
|
||||
@@ -226,10 +232,8 @@ const char* AxisMaskSetting::getCompatibleValue() {
|
||||
return strval;
|
||||
}
|
||||
|
||||
const char* AxisMaskSetting::getStringValue() {
|
||||
static char strval[32];
|
||||
static char* maskToString(uint32_t mask, char* strval) {
|
||||
char* s = strval;
|
||||
uint32_t mask = get();
|
||||
for (int i = 0; i < MAX_N_AXIS; i++) {
|
||||
if (mask & bit(i)) {
|
||||
*s++ = "XYZABC"[i];
|
||||
@@ -239,6 +243,16 @@ const char* AxisMaskSetting::getStringValue() {
|
||||
return strval;
|
||||
}
|
||||
|
||||
const char* AxisMaskSetting::getDefaultString() {
|
||||
static char strval[32];
|
||||
return maskToString(_defaultValue, strval);
|
||||
}
|
||||
|
||||
const char* AxisMaskSetting::getStringValue() {
|
||||
static char strval[32];
|
||||
return maskToString(get(), strval);
|
||||
}
|
||||
|
||||
void AxisMaskSetting::addWebui(WebUI::JSONencoder* j) {
|
||||
if (getDescription()) {
|
||||
j->begin_webui(getName(), getDescription(), "I", getStringValue(), 0, (1 << MAX_N_AXIS) - 1);
|
||||
@@ -312,6 +326,12 @@ Error FloatSetting::setStringValue(char* s) {
|
||||
return Error::Ok;
|
||||
}
|
||||
|
||||
const char* FloatSetting::getDefaultString() {
|
||||
static char strval[32];
|
||||
(void)sprintf(strval, "%.3f", _defaultValue);
|
||||
return strval;
|
||||
}
|
||||
|
||||
const char* FloatSetting::getStringValue() {
|
||||
static char strval[32];
|
||||
(void)sprintf(strval, "%.3f", get());
|
||||
@@ -395,17 +415,21 @@ Error StringSetting::setStringValue(char* s) {
|
||||
return Error::Ok;
|
||||
}
|
||||
|
||||
const char* StringSetting::getStringValue() {
|
||||
// If the string is a password do not display it
|
||||
if (_checker && (
|
||||
static bool isPassword(bool (*_checker)(char*)) {
|
||||
#ifdef ENABLE_WIFI
|
||||
_checker == (bool (*)(char*))WebUI::WiFiConfig::isPasswordValid ||
|
||||
#endif
|
||||
_checker == (bool (*)(char*))WebUI::COMMANDS::isLocalPasswordValid)) {
|
||||
return "******";
|
||||
} else {
|
||||
return _currentValue.c_str();
|
||||
if (_checker == (bool (*)(char*))WebUI::WiFiConfig::isPasswordValid) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return _checker == (bool (*)(char*))WebUI::COMMANDS::isLocalPasswordValid;
|
||||
}
|
||||
|
||||
const char* StringSetting::getDefaultString() {
|
||||
// If the string is a password do not display it
|
||||
return (_checker && isPassword(_checker)) ? "******" : _defaultValue.c_str();
|
||||
}
|
||||
const char* StringSetting::getStringValue() {
|
||||
return (_checker && isPassword(_checker)) ? "******" : get();
|
||||
}
|
||||
|
||||
void StringSetting::addWebui(WebUI::JSONencoder* j) {
|
||||
@@ -485,14 +509,20 @@ Error EnumSetting::setStringValue(char* s) {
|
||||
return Error::Ok;
|
||||
}
|
||||
|
||||
const char* EnumSetting::getStringValue() {
|
||||
const char* EnumSetting::enumToString(int8_t value) {
|
||||
for (enum_opt_t::iterator it = _options->begin(); it != _options->end(); it++) {
|
||||
if (it->second == _currentValue) {
|
||||
if (it->second == value) {
|
||||
return it->first;
|
||||
}
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
const char* EnumSetting::getDefaultString() {
|
||||
return enumToString(_defaultValue);
|
||||
}
|
||||
const char* EnumSetting::getStringValue() {
|
||||
return enumToString(get());
|
||||
}
|
||||
|
||||
void EnumSetting::addWebui(WebUI::JSONencoder* j) {
|
||||
if (!getDescription()) {
|
||||
@@ -557,6 +587,9 @@ Error FlagSetting::setStringValue(char* s) {
|
||||
}
|
||||
return Error::Ok;
|
||||
}
|
||||
const char* FlagSetting::getDefaultString() {
|
||||
return _defaultValue ? "On" : "Off";
|
||||
}
|
||||
const char* FlagSetting::getStringValue() {
|
||||
return get() ? "On" : "Off";
|
||||
}
|
||||
@@ -635,10 +668,14 @@ Error IPaddrSetting::setStringValue(char* s) {
|
||||
return Error::Ok;
|
||||
}
|
||||
|
||||
const char* IPaddrSetting::getDefaultString() {
|
||||
static String s;
|
||||
s = IPAddress(_defaultValue).toString();
|
||||
return s.c_str();
|
||||
}
|
||||
const char* IPaddrSetting::getStringValue() {
|
||||
static String s;
|
||||
IPAddress ipaddr(get());
|
||||
s = ipaddr.toString();
|
||||
s = IPAddress(get()).toString();
|
||||
return s.c_str();
|
||||
}
|
||||
|
||||
|
@@ -134,6 +134,7 @@ public:
|
||||
Error setStringValue(String s) { return setStringValue(s.c_str()); }
|
||||
virtual const char* getStringValue() = 0;
|
||||
virtual const char* getCompatibleValue() { return getStringValue(); }
|
||||
virtual const char* getDefaultString() = 0;
|
||||
};
|
||||
|
||||
class IntSetting : public Setting {
|
||||
@@ -173,6 +174,7 @@ public:
|
||||
void addWebui(WebUI::JSONencoder*);
|
||||
Error setStringValue(char* value);
|
||||
const char* getStringValue();
|
||||
const char* getDefaultString();
|
||||
|
||||
int32_t get() { return _currentValue; }
|
||||
};
|
||||
@@ -202,6 +204,7 @@ public:
|
||||
Error setStringValue(char* value);
|
||||
const char* getCompatibleValue();
|
||||
const char* getStringValue();
|
||||
const char* getDefaultString();
|
||||
|
||||
int32_t get() { return _currentValue; }
|
||||
};
|
||||
@@ -263,6 +266,7 @@ public:
|
||||
void addWebui(WebUI::JSONencoder*) {}
|
||||
Error setStringValue(char* value);
|
||||
const char* getStringValue();
|
||||
const char* getDefaultString();
|
||||
|
||||
float get() { return _currentValue; }
|
||||
};
|
||||
@@ -296,6 +300,7 @@ public:
|
||||
void addWebui(WebUI::JSONencoder*);
|
||||
Error setStringValue(char* value);
|
||||
const char* getStringValue();
|
||||
const char* getDefaultString();
|
||||
|
||||
const char* get() { return _currentValue.c_str(); }
|
||||
};
|
||||
@@ -310,6 +315,7 @@ private:
|
||||
int8_t _storedValue;
|
||||
int8_t _currentValue;
|
||||
std::map<const char*, int8_t, cmp_str>* _options;
|
||||
const char* enumToString(int8_t value);
|
||||
|
||||
public:
|
||||
EnumSetting(const char* description,
|
||||
@@ -328,6 +334,7 @@ public:
|
||||
void addWebui(WebUI::JSONencoder*);
|
||||
Error setStringValue(char* value);
|
||||
const char* getStringValue();
|
||||
const char* getDefaultString();
|
||||
|
||||
int8_t get() { return _currentValue; }
|
||||
};
|
||||
@@ -357,6 +364,7 @@ public:
|
||||
Error setStringValue(char* value);
|
||||
const char* getCompatibleValue();
|
||||
const char* getStringValue();
|
||||
const char* getDefaultString();
|
||||
|
||||
bool get() { return _currentValue; }
|
||||
};
|
||||
@@ -388,6 +396,7 @@ public:
|
||||
void addWebui(WebUI::JSONencoder*);
|
||||
Error setStringValue(char* value);
|
||||
const char* getStringValue();
|
||||
const char* getDefaultString();
|
||||
|
||||
uint32_t get() { return _currentValue; }
|
||||
};
|
||||
|
@@ -96,9 +96,6 @@ namespace WebUI {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (_client == CLIENT_WEBUI) {
|
||||
return; //this is sanity check
|
||||
}
|
||||
grbl_send(_client, data);
|
||||
}
|
||||
|
||||
|
@@ -288,7 +288,11 @@ namespace WebUI {
|
||||
return Error::Ok;
|
||||
}
|
||||
|
||||
static Error runFile(char* parameter, AuthenticationLevel auth_level) { // ESP700
|
||||
static Error runLocalFile(char* parameter, AuthenticationLevel auth_level) { // ESP700
|
||||
if (sys.state != State::Idle) {
|
||||
webPrintln("Busy");
|
||||
return Error::IdleError;
|
||||
}
|
||||
String path = trim(parameter);
|
||||
if ((path.length() > 0) && (path[0] != '/')) {
|
||||
path = "/" + path;
|
||||
@@ -304,14 +308,13 @@ namespace WebUI {
|
||||
//until no line in file
|
||||
Error err;
|
||||
Error accumErr = Error::Ok;
|
||||
uint8_t client = (espresponse) ? espresponse->client() : CLIENT_ALL;
|
||||
while (currentfile.available()) {
|
||||
String currentline = currentfile.readStringUntil('\n');
|
||||
if (currentline.length() > 0) {
|
||||
byte line[256];
|
||||
currentline.getBytes(line, 255);
|
||||
// TODO Settings - feed into command interpreter
|
||||
// while accumulating error codes
|
||||
err = execute_line((char*)line, CLIENT_WEBUI, auth_level);
|
||||
err = execute_line((char*)line, client, auth_level);
|
||||
if (err != Error::Ok) {
|
||||
accumErr = err;
|
||||
}
|
||||
@@ -322,6 +325,33 @@ namespace WebUI {
|
||||
return accumErr;
|
||||
}
|
||||
|
||||
static Error showLocalFile(char* parameter, AuthenticationLevel auth_level) { // ESP701
|
||||
if (sys.state != State::Idle && sys.state != State::Alarm) {
|
||||
return Error::IdleError;
|
||||
}
|
||||
String path = trim(parameter);
|
||||
if ((path.length() > 0) && (path[0] != '/')) {
|
||||
path = "/" + path;
|
||||
}
|
||||
if (!SPIFFS.exists(path)) {
|
||||
webPrintln("Error: No such file!");
|
||||
return Error::SdFileNotFound;
|
||||
}
|
||||
File currentfile = SPIFFS.open(path, FILE_READ);
|
||||
if (!currentfile) {
|
||||
return Error::SdFailedOpenFile;
|
||||
}
|
||||
while (currentfile.available()) {
|
||||
// String currentline = currentfile.readStringUntil('\n');
|
||||
// if (currentline.length() > 0) {
|
||||
// webPrintln(currentline);
|
||||
// }
|
||||
webPrintln(currentfile.readStringUntil('\n'));
|
||||
}
|
||||
currentfile.close();
|
||||
return Error::Ok;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_NOTIFICATIONS
|
||||
static Error showSetNotification(char* parameter, AuthenticationLevel auth_level) { // ESP610
|
||||
if (*parameter == '\0') {
|
||||
@@ -642,12 +672,15 @@ namespace WebUI {
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SD_CARD
|
||||
static Error runSDFile(char* parameter, AuthenticationLevel auth_level) { // ESP220
|
||||
parameter = trim(parameter);
|
||||
static Error openSDFile(char* parameter) {
|
||||
if (*parameter == '\0') {
|
||||
webPrintln("Missing file name!");
|
||||
return Error::InvalidValue;
|
||||
}
|
||||
String path = trim(parameter);
|
||||
if (path[0] != '/') {
|
||||
path = "/" + path;
|
||||
}
|
||||
int8_t state = get_sd_state(true);
|
||||
if (state != SDCARD_IDLE) {
|
||||
if (state == SDCARD_NOT_PRESENT) {
|
||||
@@ -658,14 +691,39 @@ namespace WebUI {
|
||||
return Error::SdFailedBusy;
|
||||
}
|
||||
}
|
||||
if (!openFile(SD, path.c_str())) {
|
||||
report_status_message(Error::SdFailedRead, (espresponse) ? espresponse->client() : CLIENT_ALL);
|
||||
webPrintln("");
|
||||
return Error::SdFailedOpenFile;
|
||||
}
|
||||
return Error::Ok;
|
||||
}
|
||||
static Error showSDFile(char* parameter, AuthenticationLevel auth_level) { // ESP221
|
||||
if (sys.state != State::Idle && sys.state != State::Alarm) {
|
||||
return Error::IdleError;
|
||||
}
|
||||
Error err;
|
||||
if ((err = openSDFile(parameter)) != Error::Ok) {
|
||||
return err;
|
||||
}
|
||||
SD_client = (espresponse) ? espresponse->client() : CLIENT_ALL;
|
||||
char fileLine[255];
|
||||
while (readFileLine(fileLine, 255)) {
|
||||
webPrintln(fileLine);
|
||||
}
|
||||
webPrintln("");
|
||||
closeFile();
|
||||
return Error::Ok;
|
||||
}
|
||||
|
||||
static Error runSDFile(char* parameter, AuthenticationLevel auth_level) { // ESP220
|
||||
Error err;
|
||||
if (sys.state != State::Idle) {
|
||||
webPrintln("Busy");
|
||||
return Error::IdleError;
|
||||
}
|
||||
if (!openFile(SD, parameter)) {
|
||||
report_status_message(Error::SdFailedRead, (espresponse) ? espresponse->client() : CLIENT_ALL);
|
||||
webPrintln("");
|
||||
return Error::Ok;
|
||||
if ((err = openSDFile(parameter)) != Error::Ok) {
|
||||
return err;
|
||||
}
|
||||
char fileLine[255];
|
||||
if (!readFileLine(fileLine, 255)) {
|
||||
@@ -675,9 +733,10 @@ namespace WebUI {
|
||||
return Error::Ok;
|
||||
}
|
||||
SD_client = (espresponse) ? espresponse->client() : CLIENT_ALL;
|
||||
report_status_message(gc_execute_line(fileLine, (espresponse) ? espresponse->client() : CLIENT_ALL),
|
||||
(espresponse) ? espresponse->client() : CLIENT_ALL); // execute the first line
|
||||
report_realtime_status((espresponse) ? espresponse->client() : CLIENT_ALL);
|
||||
SD_auth_level = auth_level;
|
||||
// execute the first line now; Protocol.cpp handles later ones when SD_ready_next
|
||||
report_status_message(execute_line(fileLine, SD_client, SD_auth_level), SD_client);
|
||||
report_realtime_status(SD_client);
|
||||
webPrintln("");
|
||||
return Error::Ok;
|
||||
}
|
||||
@@ -962,7 +1021,8 @@ namespace WebUI {
|
||||
new WebCommand(NULL, WEBCMD, WG, "ESP800", "Firmware/Info", showFwInfo);
|
||||
new WebCommand(NULL, WEBCMD, WU, "ESP720", "LocalFS/Size", SPIFFSSize);
|
||||
new WebCommand("FORMAT", WEBCMD, WA, "ESP710", "LocalFS/Format", formatSpiffs);
|
||||
new WebCommand("path", WEBCMD, WU, "ESP700", "LocalFS/Run", runFile);
|
||||
new WebCommand("path", WEBCMD, WU, "ESP701", "LocalFS/Show", showLocalFile);
|
||||
new WebCommand("path", WEBCMD, WU, "ESP700", "LocalFS/Run", runLocalFile);
|
||||
new WebCommand("path", WEBCMD, WU, NULL, "LocalFS/List", listLocalFiles);
|
||||
new WebCommand("path", WEBCMD, WU, NULL, "LocalFS/ListJSON", listLocalFilesJSON);
|
||||
#endif
|
||||
@@ -986,6 +1046,7 @@ namespace WebUI {
|
||||
new WebCommand(NULL, WEBCMD, WU, "ESP400", "WebUI/List", listSettings);
|
||||
#endif
|
||||
#ifdef ENABLE_SD_CARD
|
||||
new WebCommand("path", WEBCMD, WU, "ESP221", "SD/Show", showSDFile);
|
||||
new WebCommand("path", WEBCMD, WU, "ESP220", "SD/Run", runSDFile);
|
||||
new WebCommand("file_or_directory_path", WEBCMD, WU, "ESP215", "SD/Delete", deleteSDObject);
|
||||
new WebCommand(NULL, WEBCMD, WU, "ESP210", "SD/List", listSDFiles);
|
||||
|
Reference in New Issue
Block a user