From 68baafc6858cb78353157bb367efc96bb5672833 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 15 Feb 2021 16:37:09 +0100 Subject: [PATCH] Initial support for autoexec.bat using filesystem --- tasmota/tasmota.h | 4 +-- tasmota/tasmota_globals.h | 2 ++ tasmota/xdrv_03_energy.ino | 2 +- tasmota/xdrv_50_filesystem.ino | 63 +++++++++++++++++++++++++++++++--- 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 34e2a562a..613fd019f 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -370,10 +370,10 @@ enum DevGroupShareItem { DGR_SHARE_POWER = 1, DGR_SHARE_LIGHT_BRI = 2, DGR_SHARE enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER, SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER, - SRC_THERMOSTAT, SRC_CHAT, SRC_TCL, SRC_BERRY, SRC_MAX }; + SRC_THERMOSTAT, SRC_CHAT, SRC_TCL, SRC_BERRY, SRC_AUTOEXEC, SRC_MAX }; const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Serial|WebGui|WebCommand|WebConsole|PulseTimer|" "Timer|Rule|MaxPower|MaxEnergy|Overtemp|Light|Knx|Display|Wemo|Hue|Retry|Remote|Shutter|" - "Thermostat|Chat|TCL|Berry"; + "Thermostat|Chat|TCL|Berry|Autoexec"; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/tasmota/tasmota_globals.h b/tasmota/tasmota_globals.h index 2ac6a2343..9c05574d7 100644 --- a/tasmota/tasmota_globals.h +++ b/tasmota/tasmota_globals.h @@ -261,6 +261,8 @@ const uint16_t LOG_BUFFER_SIZE = 4000; // Max number of characters in lo #define TASM_FILE_DRIVER "/.drvset%03d" #define TASM_FILE_SENSOR "/.snsset%03d" #define TASM_FILE_ZIGBEE "/zb" // Zigbee settings blob as used by CC2530 on ESP32 +#define TASM_FILE_AUTOEXEC "/autoexec.bat" // Commands executed after restart +#define TASM_FILE_CONFIG "/config.sys" // Settings executed after restart #ifndef MQTT_MAX_PACKET_SIZE #define MQTT_MAX_PACKET_SIZE 1200 // Bytes diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino index d63472a9d..822bb6401 100644 --- a/tasmota/xdrv_03_energy.ino +++ b/tasmota/xdrv_03_energy.ino @@ -501,7 +501,7 @@ void EnergyEverySecond(void) { // Overtemp check if (TasmotaGlobal.global_update) { - if (TasmotaGlobal.power && !isnan(TasmotaGlobal.temperature_celsius) && (TasmotaGlobal.temperature_celsius > (float)Settings.param[P_OVER_TEMP])) { // Device overtemp, turn off relays + if (TasmotaGlobal.power && !isnan(TasmotaGlobal.temperature_celsius) && (TasmotaGlobal.temperature_celsius > (float)Settings.param[P_OVER_TEMP])) { // SetOption42 Device overtemp, turn off relays AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: GlobTemp %1_f"), &TasmotaGlobal.temperature_celsius); diff --git a/tasmota/xdrv_50_filesystem.ino b/tasmota/xdrv_50_filesystem.ino index f748ed16a..fddccb214 100644 --- a/tasmota/xdrv_50_filesystem.ino +++ b/tasmota/xdrv_50_filesystem.ino @@ -83,7 +83,11 @@ uint8_t ufs_dir; // 0 = None, 1 = SD, 2 = ffat, 3 = littlefs uint8_t ufs_type; uint8_t ffs_type; -bool download_busy; + +struct { + bool download_busy; + bool autoexec = false; +} UfsData; /*********************************************************************************************/ @@ -332,6 +336,45 @@ bool TfsDeleteFile(const char *fname) { return true; } +/*********************************************************************************************\ + * Autoexec support +\*********************************************************************************************/ + +void UfsAutoexec(void) { + if (!ffs_type) { return; } + File file = ffsp->open(TASM_FILE_AUTOEXEC, "r"); + if (!file) { return; } + + char cmd_line[512]; + while (file.available()) { + uint16_t index = 0; + while (file.available()) { + uint8_t buf[1]; + file.read(buf, 1); + if ((buf[0] == '\n') || (buf[0] == '\r')) { + // Line terminated with linefeed or carriage return + break; + } + else if ((0 == index) && isspace(buf[0])) { + // Skip leading spaces (' ','\t','\n','\v','\f','\r') + } else { + cmd_line[index] = buf[0]; + index++; + if (index >= sizeof(cmd_line) - 1) { + break; + } + } + } + if ((index > 0) && (cmd_line[0] != ';')) { // Information but no comment + cmd_line[index] = 0; + ExecuteCommand(cmd_line, SRC_AUTOEXEC); + } + delay(0); + } + + file.close(); +} + /*********************************************************************************************\ * Commands \*********************************************************************************************/ @@ -396,7 +439,6 @@ void UFSDelete(void) { * Web support \*********************************************************************************************/ - #ifdef USE_WEBSERVER const char UFS_WEB_DIR[] PROGMEM = @@ -654,12 +696,12 @@ uint8_t UfsDownloadFile(char *file) { #ifdef ESP32_DOWNLOAD_TASK download_file.close(); - if (download_busy == true) { + if (UfsData.download_busy == true) { AddLog(LOG_LEVEL_INFO, PSTR("UFS: Download is busy")); return 0; } - download_busy = true; + UfsData.download_busy = true; char *path = (char*)malloc(128); strcpy(path,file); xTaskCreatePinnedToCore(donload_task, "DT", 6000, (void*)path, 3, NULL, 1); @@ -710,7 +752,7 @@ void donload_task(void *path) { } download_file.close(); download_Client.stop(); - download_busy = false; + UfsData.download_busy = false; vTaskDelete( NULL ); } #endif // ESP32_DOWNLOAD_TASK @@ -752,6 +794,17 @@ bool Xdrv50(uint8_t function) { UfsCheckSDCardInit(); break; #endif // USE_SDCARD + case FUNC_EVERY_SECOND: + if (UfsData.autoexec) { + // Safe to execute autoexec commands here + UfsData.autoexec = false; + UfsAutoexec(); + } + break; + case FUNC_MQTT_INIT: + // Do not execute autoexec commands here + UfsData.autoexec = true; + break; case FUNC_COMMAND: result = DecodeCommand(kUFSCommands, kUFSCommand); break;