From 175bdfa07428bd456f5fafeb83ea9fb1e628978e Mon Sep 17 00:00:00 2001 From: TD-er Date: Fri, 25 Sep 2020 22:58:49 +0200 Subject: [PATCH] [Cleanup] Split even more functions from Mist.cpp/.h --- src/ESPEasy-Globals.h | 5 - src/ESPEasy.ino | 4 + src/ESPEasyWifi_ProcessEvent.cpp | 1 + src/ESPEasyWifi_ProcessEvent.h | 2 + src/StringProvider.ino | 3 + src/WebServer.ino | 8 +- src/WebServer_DevicesPage.ino | 1 + src/WebServer_RootPage.ino | 1 + src/WebServer_SysInfoPage.ino | 4 +- src/_CPlugin_Helper.cpp | 1 + src/_N002_Buzzer.ino | 2 + src/_P001_Switch.ino | 1 + src/_P026_Sysinfo.ino | 1 + src/_Plugin_Helper.cpp | 1 + src/src/Commands/Diagnostic.cpp | 1 + src/src/Commands/HTTP.cpp | 1 + src/src/Commands/Settings.cpp | 1 + src/src/Commands/UDP.cpp | 1 + src/src/DataStructs/NodeStruct.cpp | 20 + src/src/DataStructs/NodeStruct.h | 7 +- src/src/Globals/RamTracker.cpp | 5 +- src/src/Helpers/Audio.cpp | 211 +++++ src/src/Helpers/Audio.h | 38 + src/src/Helpers/ESPEasy_FactoryDefault.cpp | 9 + src/src/Helpers/ESPEasy_FactoryDefault.h | 5 + src/src/Helpers/ESPEasy_Storage.cpp | 2 + src/src/Helpers/ESPEasy_Storage.h | 1 + src/src/Helpers/Hardware.cpp | 37 + src/src/Helpers/Hardware.h | 7 + src/src/Helpers/Memory.cpp | 90 ++ src/src/Helpers/Memory.h | 50 ++ src/src/Helpers/Misc.cpp | 921 +-------------------- src/src/Helpers/Misc.h | 235 +----- src/src/Helpers/Network.cpp | 83 ++ src/src/Helpers/Network.h | 15 + src/src/Helpers/OTA.cpp | 99 +++ src/src/Helpers/OTA.h | 20 + src/src/Helpers/PeriodicalActions.cpp | 2 + src/src/Helpers/Scheduler.cpp | 2 + src/src/Helpers/StringGenerator_GPIO.cpp | 151 ++++ src/src/Helpers/StringGenerator_GPIO.h | 65 ++ src/src/Helpers/StringGenerator_System.cpp | 177 ++++ src/src/Helpers/StringGenerator_System.h | 42 + src/src/Helpers/StringParser.cpp | 50 ++ src/src/Helpers/StringParser.h | 19 + src/src/Helpers/SystemVariables.cpp | 1 + 46 files changed, 1248 insertions(+), 1155 deletions(-) create mode 100644 src/src/DataStructs/NodeStruct.cpp create mode 100644 src/src/Helpers/Audio.cpp create mode 100644 src/src/Helpers/Audio.h create mode 100644 src/src/Helpers/Memory.cpp create mode 100644 src/src/Helpers/Memory.h create mode 100644 src/src/Helpers/Network.cpp create mode 100644 src/src/Helpers/Network.h create mode 100644 src/src/Helpers/OTA.cpp create mode 100644 src/src/Helpers/OTA.h create mode 100644 src/src/Helpers/StringGenerator_GPIO.cpp create mode 100644 src/src/Helpers/StringGenerator_GPIO.h create mode 100644 src/src/Helpers/StringGenerator_System.cpp create mode 100644 src/src/Helpers/StringGenerator_System.h diff --git a/src/ESPEasy-Globals.h b/src/ESPEasy-Globals.h index eab33715b..5bb906668 100644 --- a/src/ESPEasy-Globals.h +++ b/src/ESPEasy-Globals.h @@ -212,11 +212,6 @@ using namespace fs; -enum gpio_direction { - gpio_input, - gpio_output, - gpio_bidirectional -}; /*********************************************************************************************\ diff --git a/src/ESPEasy.ino b/src/ESPEasy.ino index e754a7a74..b0e94b7b6 100644 --- a/src/ESPEasy.ino +++ b/src/ESPEasy.ino @@ -129,9 +129,13 @@ #include "src/Helpers/ESPEasy_Storage.h" #include "src/Helpers/ESPEasy_checks.h" #include "src/Helpers/Hardware.h" +#include "src/Helpers/Memory.h" #include "src/Helpers/Misc.h" +#include "src/Helpers/Network.h" +#include "src/Helpers/OTA.h" #include "src/Helpers/PeriodicalActions.h" #include "src/Helpers/Scheduler.h" +#include "src/Helpers/StringGenerator_System.h" #if FEATURE_ADC_VCC ADC_MODE(ADC_VCC); diff --git a/src/ESPEasyWifi_ProcessEvent.cpp b/src/ESPEasyWifi_ProcessEvent.cpp index ed2c7d026..25287bbdb 100644 --- a/src/ESPEasyWifi_ProcessEvent.cpp +++ b/src/ESPEasyWifi_ProcessEvent.cpp @@ -15,6 +15,7 @@ #include "src/Helpers/ESPEasy_Storage.h" #include "src/Helpers/ESPEasy_time_calc.h" #include "src/Helpers/Misc.h" +#include "src/Helpers/Network.h" #include "src/Helpers/Scheduler.h" #include "src/Helpers/StringConverter.h" diff --git a/src/ESPEasyWifi_ProcessEvent.h b/src/ESPEasyWifi_ProcessEvent.h index 78c4a1161..668fc6fa9 100644 --- a/src/ESPEasyWifi_ProcessEvent.h +++ b/src/ESPEasyWifi_ProcessEvent.h @@ -1,6 +1,8 @@ #ifndef ESPEASYWIFI_PROCESSEVENT_H #define ESPEASYWIFI_PROCESSEVENT_H +#include "ESPEasy_common.h" + bool unprocessedWifiEvents(); void handle_unprocessedWiFiEvents(); void processDisconnect(); diff --git a/src/StringProvider.ino b/src/StringProvider.ino index c0016d616..f73e1c14a 100644 --- a/src/StringProvider.ino +++ b/src/StringProvider.ino @@ -1,4 +1,5 @@ #include "StringProviderTypes.h" + #include "ESPEasyNetwork.h" #ifdef HAS_ETHERNET #include "ETH.h" @@ -7,7 +8,9 @@ #include "src/Globals/ESPEasy_Scheduler.h" #include "src/Helpers/CompiletimeDefines.h" +#include "src/Helpers/Memory.h" #include "src/Helpers/Scheduler.h" +#include "src/Helpers/StringGenerator_System.h" String getInternalLabel(LabelType::Enum label, char replaceSpace) { return to_internal_string(getLabel(label), replaceSpace); diff --git a/src/WebServer.ino b/src/WebServer.ino index 27c5f3cb0..d74eea7f1 100644 --- a/src/WebServer.ino +++ b/src/WebServer.ino @@ -5,12 +5,16 @@ #include "ESPEasyNetwork.h" #include "ESPEasy_common.h" + +#include "src/DataStructs/SettingsType.h" + #include "src/Globals/CPlugins.h" #include "src/Globals/Device.h" #include "src/Globals/TXBuffer.h" -#include "src/Static/WebStaticData.h" -#include "src/DataStructs/SettingsType.h" +#include "src/Helpers/OTA.h" + +#include "src/Static/WebStaticData.h" void sendHeadandTail(const String& tmplName, boolean Tail = false, boolean rebooting = false) { diff --git a/src/WebServer_DevicesPage.ino b/src/WebServer_DevicesPage.ino index 05328e6e8..f3fa86dd7 100644 --- a/src/WebServer_DevicesPage.ino +++ b/src/WebServer_DevicesPage.ino @@ -5,6 +5,7 @@ # include "src/Globals/CPlugins.h" # include "src/Globals/Plugins.h" # include "src/Static/WebStaticData.h" +# include "src/Helpers/StringGenerator_GPIO.h" void handle_devices() { diff --git a/src/WebServer_RootPage.ino b/src/WebServer_RootPage.ino index 0126376b5..77f14cc36 100644 --- a/src/WebServer_RootPage.ino +++ b/src/WebServer_RootPage.ino @@ -2,6 +2,7 @@ #include "src/Commands/InternalCommands.h" #include "src/Globals/Nodes.h" +#include "src/Helpers/Memory.h" // ******************************************************************************** // Web Interface root page diff --git a/src/WebServer_SysInfoPage.ino b/src/WebServer_SysInfoPage.ino index 2bc59f565..dccd04e26 100644 --- a/src/WebServer_SysInfoPage.ino +++ b/src/WebServer_SysInfoPage.ino @@ -7,7 +7,9 @@ #include "src/Commands/Diagnostic.h" #include "src/Helpers/Hardware.h" - +#include "src/Helpers/Memory.h" +#include "src/Helpers/OTA.h" +#include "src/Helpers/StringGenerator_System.h" #ifdef WEBSERVER_NEW_UI diff --git a/src/_CPlugin_Helper.cpp b/src/_CPlugin_Helper.cpp index 45829d30a..b0bb05352 100644 --- a/src/_CPlugin_Helper.cpp +++ b/src/_CPlugin_Helper.cpp @@ -18,6 +18,7 @@ #include "src/Helpers/CompiletimeDefines.h" #include "src/Helpers/ESPEasy_time_calc.h" #include "src/Helpers/Misc.h" +#include "src/Helpers/Network.h" #include "src/Helpers/StringConverter.h" #include diff --git a/src/_N002_Buzzer.ino b/src/_N002_Buzzer.ino index 79d9d44af..7a2387fb1 100644 --- a/src/_N002_Buzzer.ino +++ b/src/_N002_Buzzer.ino @@ -7,6 +7,8 @@ #define NPLUGIN_ID_002 2 #define NPLUGIN_NAME_002 "Buzzer" +#include "src/Helpers/Audio.h" + boolean NPlugin_002(NPlugin::Function function, struct EventStruct *event, String& string) { boolean success = false; diff --git a/src/_P001_Switch.ino b/src/_P001_Switch.ino index cd133f7cb..21b1b25f9 100644 --- a/src/_P001_Switch.ino +++ b/src/_P001_Switch.ino @@ -3,6 +3,7 @@ #include "_Plugin_Helper.h" #include "src/DataStructs/PinMode.h" #include "src/Helpers/Scheduler.h" +#include "src/Helpers/Audio.h" // ####################################################################################################### // #################################### Plugin 001: Input Switch ######################################### diff --git a/src/_P026_Sysinfo.ino b/src/_P026_Sysinfo.ino index c58e3c197..f4e41c0bd 100644 --- a/src/_P026_Sysinfo.ino +++ b/src/_P026_Sysinfo.ino @@ -6,6 +6,7 @@ #include "_Plugin_Helper.h" #include "ESPEasy_packed_raw_data.h" +#include "src/Helpers/Memory.h" #define PLUGIN_026 #define PLUGIN_ID_026 26 diff --git a/src/_Plugin_Helper.cpp b/src/_Plugin_Helper.cpp index 1cda733b8..8730fc3c7 100644 --- a/src/_Plugin_Helper.cpp +++ b/src/_Plugin_Helper.cpp @@ -9,6 +9,7 @@ #include "src/Globals/Settings.h" #include "src/Globals/SecuritySettings.h" #include "src/Helpers/Misc.h" +#include "src/Helpers/StringParser.h" PluginTaskData_base *Plugin_task_data[TASKS_MAX] = { nullptr, }; diff --git a/src/src/Commands/Diagnostic.cpp b/src/src/Commands/Diagnostic.cpp index e35f7c93a..c0b2d75cc 100644 --- a/src/src/Commands/Diagnostic.cpp +++ b/src/src/Commands/Diagnostic.cpp @@ -30,6 +30,7 @@ #include "../Helpers/Misc.h" #include "../Helpers/PortStatus.h" #include "../Helpers/StringConverter.h" +#include "../Helpers/StringParser.h" #include #include diff --git a/src/src/Commands/HTTP.cpp b/src/src/Commands/HTTP.cpp index 36b9636d4..d126dbcdb 100644 --- a/src/src/Commands/HTTP.cpp +++ b/src/src/Commands/HTTP.cpp @@ -13,6 +13,7 @@ #include "../Globals/Settings.h" #include "../Helpers/Misc.h" +#include "../Helpers/StringParser.h" String Command_HTTP_SendToHTTP(struct EventStruct *event, const char* Line) diff --git a/src/src/Commands/Settings.cpp b/src/src/Commands/Settings.cpp index f916fb128..9ccb63999 100644 --- a/src/src/Commands/Settings.cpp +++ b/src/src/Commands/Settings.cpp @@ -10,6 +10,7 @@ #include "../Helpers/ESPEasy_FactoryDefault.h" #include "../Helpers/ESPEasy_Storage.h" +#include "../Helpers/Memory.h" #include "../Helpers/Misc.h" #include "../Helpers/StringConverter.h" diff --git a/src/src/Commands/UDP.cpp b/src/src/Commands/UDP.cpp index 04e5edea6..e95a1a547 100644 --- a/src/src/Commands/UDP.cpp +++ b/src/src/Commands/UDP.cpp @@ -8,6 +8,7 @@ #include "../Globals/Settings.h" #include "../Helpers/Misc.h" #include "../Helpers/StringConverter.h" +#include "../Helpers/StringParser.h" String Command_UDP_Test(struct EventStruct *event, const char *Line) { diff --git a/src/src/DataStructs/NodeStruct.cpp b/src/src/DataStructs/NodeStruct.cpp new file mode 100644 index 000000000..d68601332 --- /dev/null +++ b/src/src/DataStructs/NodeStruct.cpp @@ -0,0 +1,20 @@ +#include "NodeStruct.h" + +String getNodeTypeDisplayString(byte nodeType) { + switch (nodeType) + { + case NODE_TYPE_ID_ESP_EASY_STD: return F("ESP Easy"); + case NODE_TYPE_ID_ESP_EASYM_STD: return F("ESP Easy Mega"); + case NODE_TYPE_ID_ESP_EASY32_STD: return F("ESP Easy 32"); + case NODE_TYPE_ID_RPI_EASY_STD: return F("RPI Easy"); + case NODE_TYPE_ID_ARDUINO_EASY_STD: return F("Arduino Easy"); + case NODE_TYPE_ID_NANO_EASY_STD: return F("Nano Easy"); + } + return ""; +} + + NodeStruct::NodeStruct() : + build(0), age(0), nodeType(0), webgui_portnumber(0) + { + for (byte i = 0; i < 4; ++i) { ip[i] = 0; } + } diff --git a/src/src/DataStructs/NodeStruct.h b/src/src/DataStructs/NodeStruct.h index 1a9d9c194..c44f984a7 100644 --- a/src/src/DataStructs/NodeStruct.h +++ b/src/src/DataStructs/NodeStruct.h @@ -13,17 +13,14 @@ #define NODE_TYPE_ID_ARDUINO_EASY_STD 65 #define NODE_TYPE_ID_NANO_EASY_STD 81 +String getNodeTypeDisplayString(byte nodeType); /*********************************************************************************************\ * NodeStruct \*********************************************************************************************/ struct NodeStruct { - NodeStruct() : - build(0), age(0), nodeType(0), webgui_portnumber(0) - { - for (byte i = 0; i < 4; ++i) { ip[i] = 0; } - } + NodeStruct(); String nodeName; IPAddress ip; diff --git a/src/src/Globals/RamTracker.cpp b/src/src/Globals/RamTracker.cpp index 2297891a3..56e4ecb61 100644 --- a/src/src/Globals/RamTracker.cpp +++ b/src/src/Globals/RamTracker.cpp @@ -2,7 +2,10 @@ #include "../../ESPEasy_Log.h" #include "../../ESPEasy_fdwdecl.h" -#include "Statistics.h" + +#include "../Globals/Statistics.h" + +#include "../Helpers/Memory.h" #include "../Helpers/Misc.h" #ifndef BUILD_NO_RAM_TRACKER diff --git a/src/src/Helpers/Audio.cpp b/src/src/Helpers/Audio.cpp new file mode 100644 index 000000000..af5098e2f --- /dev/null +++ b/src/src/Helpers/Audio.cpp @@ -0,0 +1,211 @@ +#include "Audio.h" + +#include "../Globals/RamTracker.h" + +#ifdef ESP32 + +void noToneESP32(uint8_t pin, uint8_t channel) +{ + ledcDetachPin(pin); + ledcWrite(channel, 0); +} + +void toneESP32(uint8_t pin, unsigned int frequency, unsigned long duration, uint8_t channel) +{ + if (ledcRead(channel)) { + log_e("Tone channel %d is already in use", ledcRead(channel)); + return; + } + ledcAttachPin(pin, channel); + ledcWriteTone(channel, frequency); + + if (duration) { + delay(duration); + noToneESP32(pin, channel); + } +} + +#endif // ifdef ESP32 + + +/********************************************************************************************\ + Generate a tone of specified frequency on pin + \*********************************************************************************************/ +void tone_espEasy(uint8_t _pin, unsigned int frequency, unsigned long duration) { + #ifdef ESP32 + toneESP32(_pin, frequency, duration); + #else // ifdef ESP32 + analogWriteFreq(frequency); + + // NOTE: analogwrite reserves IRAM and uninitalized ram. + analogWrite(_pin, 100); + delay(duration); + analogWrite(_pin, 0); + #endif // ifdef ESP32 +} + +/********************************************************************************************\ + Play RTTTL string on specified pin + \*********************************************************************************************/ +void play_rtttl(uint8_t _pin, const char *p) +{ + checkRAM(F("play_rtttl")); + #define OCTAVE_OFFSET 0 + + // FIXME: Absolutely no error checking in here + + const int notes[] = { 0, + 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494, + 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988, + 1047,1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976, + 2093,2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951 + }; + + + byte default_dur = 4; + byte default_oct = 6; + int bpm = 63; + int num; + long wholenote; + long duration; + byte note; + byte scale; + + // format: d=N,o=N,b=NNN: + // find the start (skip name, etc) + + while (*p != ':') { p++; // ignore name + } + p++; // skip ':' + + // get default duration + if (*p == 'd') + { + p++; p++; // skip "d=" + num = 0; + + while (isdigit(*p)) + { + num = (num * 10) + (*p++ - '0'); + } + + if (num > 0) { default_dur = num; } + p++; // skip comma + } + + // get default octave + if (*p == 'o') + { + p++; p++; // skip "o=" + num = *p++ - '0'; + + if ((num >= 3) && (num <= 7)) { default_oct = num; } + p++; // skip comma + } + + // get BPM + if (*p == 'b') + { + p++; p++; // skip "b=" + num = 0; + + while (isdigit(*p)) + { + num = (num * 10) + (*p++ - '0'); + } + bpm = num; + p++; // skip colon + } + + // BPM usually expresses the number of quarter notes per minute + wholenote = (60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds) + + // now begin note loop + while (*p) + { + // first, get note duration, if available + num = 0; + + while (isdigit(*p)) + { + num = (num * 10) + (*p++ - '0'); + } + + if (num) { duration = wholenote / num; } + else { duration = wholenote / default_dur; // we will need to check if we are a dotted note after + } + + // now get the note + switch (*p) + { + case 'c': + note = 1; + break; + case 'd': + note = 3; + break; + case 'e': + note = 5; + break; + case 'f': + note = 6; + break; + case 'g': + note = 8; + break; + case 'a': + note = 10; + break; + case 'b': + note = 12; + break; + case 'p': + default: + note = 0; + } + p++; + + // now, get optional '#' sharp + if (*p == '#') + { + note++; + p++; + } + + // now, get optional '.' dotted note + if (*p == '.') + { + duration += duration / 2; + p++; + } + + // now, get scale + if (isdigit(*p)) + { + scale = *p - '0'; + p++; + } + else + { + scale = default_oct; + } + + scale += OCTAVE_OFFSET; + + if (*p == ',') { + p++; // skip comma for next note (or we may be at the end) + } + + // now play the note + if (note) + { + tone_espEasy(_pin, notes[(scale - 4) * 12 + note], duration); + } + else + { + delay(duration / 10); + } + } + checkRAM(F("play_rtttl2")); +} + diff --git a/src/src/Helpers/Audio.h b/src/src/Helpers/Audio.h new file mode 100644 index 000000000..91dfaadc4 --- /dev/null +++ b/src/src/Helpers/Audio.h @@ -0,0 +1,38 @@ +#ifndef HELPERS_AUDIO_H +#define HELPERS_AUDIO_H + +#include + +#ifdef ESP32 + +// MFD: adding tone support here while waiting for the Arduino Espressif implementation to catch up +// As recomandation is not to use external libraries the following code was taken from: https://github.com/lbernstone/Tone Thanks + # define TONE_CHANNEL 15 + +void noToneESP32(uint8_t pin, + uint8_t channel = TONE_CHANNEL); + +void toneESP32(uint8_t pin, + unsigned int frequency, + unsigned long duration, + uint8_t channel = TONE_CHANNEL); + +#endif // ifdef ESP32 + + + +/********************************************************************************************\ + Generate a tone of specified frequency on pin + \*********************************************************************************************/ +void tone_espEasy(uint8_t _pin, + unsigned int frequency, + unsigned long duration); + +/********************************************************************************************\ + Play RTTTL string on specified pin + \*********************************************************************************************/ +void play_rtttl(uint8_t _pin, + const char *p); + + +#endif \ No newline at end of file diff --git a/src/src/Helpers/ESPEasy_FactoryDefault.cpp b/src/src/Helpers/ESPEasy_FactoryDefault.cpp index 31b808ce7..d3e5d2d41 100644 --- a/src/src/Helpers/ESPEasy_FactoryDefault.cpp +++ b/src/src/Helpers/ESPEasy_FactoryDefault.cpp @@ -263,3 +263,12 @@ void ResetFactory() WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters reboot(); } + + +/*********************************************************************************************\ + Collect the stored preference for factory default +\*********************************************************************************************/ +void applyFactoryDefaultPref() { + // TODO TD-er: Store it in more places to make it more persistent + Settings.ResetFactoryDefaultPreference = ResetFactoryDefaultPreference.getPreference(); +} diff --git a/src/src/Helpers/ESPEasy_FactoryDefault.h b/src/src/Helpers/ESPEasy_FactoryDefault.h index 9a6a7a5b2..88c8accc3 100644 --- a/src/src/Helpers/ESPEasy_FactoryDefault.h +++ b/src/src/Helpers/ESPEasy_FactoryDefault.h @@ -7,5 +7,10 @@ \*********************************************************************************************/ void ResetFactory(); +/*********************************************************************************************\ + Collect the stored preference for factory default +\*********************************************************************************************/ +void applyFactoryDefaultPref(); + #endif \ No newline at end of file diff --git a/src/src/Helpers/ESPEasy_Storage.cpp b/src/src/Helpers/ESPEasy_Storage.cpp index 7359ddc02..7216135fc 100644 --- a/src/src/Helpers/ESPEasy_Storage.cpp +++ b/src/src/Helpers/ESPEasy_Storage.cpp @@ -1,5 +1,6 @@ #include "ESPEasy_Storage.h" +#include "../../ESPEasy_common.h" #include "../../ESPEasyWifi.h" #include "../../ESPEasy_Log.h" @@ -21,6 +22,7 @@ #include "../Helpers/ESPEasyRTC.h" #include "../Helpers/ESPEasy_Storage.h" #include "../Helpers/Hardware.h" +#include "../Helpers/Memory.h" #include "../Helpers/Misc.h" #include "../Helpers/Numerical.h" #include "../Helpers/PeriodicalActions.h" diff --git a/src/src/Helpers/ESPEasy_Storage.h b/src/src/Helpers/ESPEasy_Storage.h index aae747d41..cecb7a8a3 100644 --- a/src/src/Helpers/ESPEasy_Storage.h +++ b/src/src/Helpers/ESPEasy_Storage.h @@ -3,6 +3,7 @@ #include + #include "../DataStructs/SettingsType.h" #include "../Globals/Plugins.h" #include "../Globals/CPlugins.h" diff --git a/src/src/Helpers/Hardware.cpp b/src/src/Helpers/Hardware.cpp index a26c19d1d..2c281c0db 100644 --- a/src/src/Helpers/Hardware.cpp +++ b/src/src/Helpers/Hardware.cpp @@ -392,6 +392,43 @@ uint32_t getFlashRealSizeInBytes() { #endif // if defined(ESP32) } + +bool puyaSupport() { + bool supported = false; + +#ifdef PUYA_SUPPORT + + // New support starting core 2.5.0 + if (PUYA_SUPPORT) { supported = true; } +#endif // ifdef PUYA_SUPPORT +#ifdef PUYASUPPORT + + // Old patch + supported = true; +#endif // ifdef PUYASUPPORT + return supported; +} + +uint8_t getFlashChipVendorId() { +#ifdef PUYA_SUPPORT + return ESP.getFlashChipVendorId(); +#else // ifdef PUYA_SUPPORT + # if defined(ESP8266) + uint32_t flashChipId = ESP.getFlashChipId(); + return flashChipId & 0x000000ff; + # else // if defined(ESP8266) + return 0xFF; // Not an existing function for ESP32 + # endif // if defined(ESP8266) +#endif // ifdef PUYA_SUPPORT +} + +bool flashChipVendorPuya() { + uint8_t vendorId = getFlashChipVendorId(); + + return vendorId == 0x85; // 0x146085 PUYA +} + + /********************************************************************************************\ Hardware specific configurations \*********************************************************************************************/ diff --git a/src/src/Helpers/Hardware.h b/src/src/Helpers/Hardware.h index 42989288a..37236ac53 100644 --- a/src/src/Helpers/Hardware.h +++ b/src/src/Helpers/Hardware.h @@ -49,6 +49,13 @@ int espeasy_analogRead(int pin, bool readAsTouch); \*********************************************************************************************/ uint32_t getFlashRealSizeInBytes(); +bool puyaSupport(); + +uint8_t getFlashChipVendorId(); + +bool flashChipVendorPuya(); + + /********************************************************************************************\ Hardware specific configurations \*********************************************************************************************/ diff --git a/src/src/Helpers/Memory.cpp b/src/src/Helpers/Memory.cpp new file mode 100644 index 000000000..9572cf734 --- /dev/null +++ b/src/src/Helpers/Memory.cpp @@ -0,0 +1,90 @@ +#include "Memory.h" + + +#ifdef ESP8266 +extern "C" { +#include "user_interface.h" +} +#endif + + +/*********************************************************************************************\ + Memory management +\*********************************************************************************************/ + + +// For keeping track of 'cont' stack +// See: https://github.com/esp8266/Arduino/issues/2557 +// https://github.com/esp8266/Arduino/issues/5148#issuecomment-424329183 +// https://github.com/letscontrolit/ESPEasy/issues/1824 +#ifdef ESP32 + +// FIXME TD-er: For ESP32 you need to provide the task number, or NULL to get from the calling task. +uint32_t getCurrentFreeStack() { + register uint8_t *sp asm ("a1"); + + return sp - pxTaskGetStackStart(NULL); +} + +uint32_t getFreeStackWatermark() { + return uxTaskGetStackHighWaterMark(NULL); +} + +// FIXME TD-er: Must check if these functions are also needed for ESP32. +bool canYield() { + return true; +} + +#else // ifdef ESP32 + +uint32_t getCurrentFreeStack() { + // https://github.com/esp8266/Arduino/issues/2557 + register uint32_t *sp asm ("a1"); + + return 4 * (sp - g_pcont->stack); +} + +uint32_t getFreeStackWatermark() { + return cont_get_free_stack(g_pcont); +} + +bool canYield() { + return cont_can_yield(g_pcont); +} + +bool allocatedOnStack(const void *address) { + register uint32_t *sp asm ("a1"); + + if (sp < address) { return false; } + return g_pcont->stack < address; +} + +#endif // ESP32 + + +/********************************************************************************************\ + Get free system mem + \*********************************************************************************************/ +unsigned long FreeMem(void) +{ + #if defined(ESP8266) + return system_get_free_heap_size(); + #endif // if defined(ESP8266) + #if defined(ESP32) + return ESP.getFreeHeap(); + #endif // if defined(ESP32) +} + +unsigned long getMaxFreeBlock() +{ + unsigned long freemem = FreeMem(); + + #ifdef CORE_POST_2_5_0 + + // computing max free block is a rather extensive operation, so only perform when free memory is already low. + if (freemem < 6144) { + return ESP.getMaxFreeBlockSize(); + } + #endif // ifdef CORE_POST_2_5_0 + return freemem; +} diff --git a/src/src/Helpers/Memory.h b/src/src/Helpers/Memory.h new file mode 100644 index 000000000..0dbf26816 --- /dev/null +++ b/src/src/Helpers/Memory.h @@ -0,0 +1,50 @@ +#ifndef HELPERS_MEMORY_H +#define HELPERS_MEMORY_H + +#include + +/*********************************************************************************************\ + Memory management +\*********************************************************************************************/ + + +// For keeping track of 'cont' stack +// See: https://github.com/esp8266/Arduino/issues/2557 +// https://github.com/esp8266/Arduino/issues/5148#issuecomment-424329183 +// https://github.com/letscontrolit/ESPEasy/issues/1824 +#ifdef ESP32 + +// FIXME TD-er: For ESP32 you need to provide the task number, or NULL to get from the calling task. +uint32_t getCurrentFreeStack(); + +uint32_t getFreeStackWatermark(); + +// FIXME TD-er: Must check if these functions are also needed for ESP32. +bool canYield(); + +#else // ifdef ESP32 + +extern "C" { +# include +extern cont_t *g_pcont; +} + +uint32_t getCurrentFreeStack(); + +uint32_t getFreeStackWatermark(); + +bool canYield(); + +bool allocatedOnStack(const void *address); + +#endif // ESP32 + +/********************************************************************************************\ + Get free system mem + \*********************************************************************************************/ +unsigned long FreeMem(void); + +unsigned long getMaxFreeBlock(); + + +#endif \ No newline at end of file diff --git a/src/src/Helpers/Misc.cpp b/src/src/Helpers/Misc.cpp index e2c342502..e74c95cea 100644 --- a/src/src/Helpers/Misc.cpp +++ b/src/src/Helpers/Misc.cpp @@ -1,338 +1,15 @@ #include "Misc.h" -#include "../DataStructs/Caches.h" -#include "../DataStructs/ControllerSettingsStruct.h" -#include "../DataStructs/ExtendedControllerCredentialsStruct.h" -#include "../DataStructs/NodeStruct.h" -#include "../DataStructs/PinMode.h" -#include "../DataStructs/RTCStruct.h" -#include "../DataStructs/StorageLayout.h" - - -#include "../Globals/CPlugins.h" -#include "../Globals/CRCValues.h" -#include "../Globals/Cache.h" -#include "../Globals/Device.h" -#include "../Globals/ESPEasy_Scheduler.h" -#include "../Globals/ExtraTaskSettings.h" -#include "../Globals/GlobalMapPortStatus.h" -#include "../Globals/MQTT.h" -#include "../Globals/Plugins.h" -#include "../Globals/Plugins_other.h" -#include "../Globals/RTC.h" -#include "../Globals/ResetFactoryDefaultPref.h" -#include "../Globals/SecuritySettings.h" -#include "../Globals/Services.h" -#include "../Globals/Settings.h" -#include "../Globals/Statistics.h" - -#include "../Helpers/Convert.h" -#include "../Helpers/ESPEasy_FactoryDefault.h" -#include "../Helpers/ESPEasy_Storage.h" -#include "../Helpers/ESPEasy_time_calc.h" -#include "../Helpers/ESPEasyRTC.h" -#include "../Helpers/Hardware.h" -#include "../Helpers/PeriodicalActions.h" -#include "../Helpers/PortStatus.h" -#include "../Helpers/Rules_calculate.h" -#include "../Helpers/StringConverter.h" -#include "../Helpers/StringParser.h" #include "../../ESPEasy_common.h" -#include "../../ESPEasyWifi.h" -#include "../../_CPlugin_Helper.h" #include "../../_Plugin_Helper.h" - -#ifdef ESP32 - -void noToneESP32(uint8_t pin, uint8_t channel) -{ - ledcDetachPin(pin); - ledcWrite(channel, 0); -} - -void toneESP32(uint8_t pin, unsigned int frequency, unsigned long duration, uint8_t channel) -{ - if (ledcRead(channel)) { - log_e("Tone channel %d is already in use", ledcRead(channel)); - return; - } - ledcAttachPin(pin, channel); - ledcWriteTone(channel, frequency); - - if (duration) { - delay(duration); - noToneESP32(pin, channel); - } -} - -#endif // ifdef ESP32 - -/*********************************************************************************************\ - ESPEasy specific strings -\*********************************************************************************************/ -String getNodeTypeDisplayString(byte nodeType) { - switch (nodeType) - { - case NODE_TYPE_ID_ESP_EASY_STD: return F("ESP Easy"); - case NODE_TYPE_ID_ESP_EASYM_STD: return F("ESP Easy Mega"); - case NODE_TYPE_ID_ESP_EASY32_STD: return F("ESP Easy 32"); - case NODE_TYPE_ID_RPI_EASY_STD: return F("RPI Easy"); - case NODE_TYPE_ID_ARDUINO_EASY_STD: return F("Arduino Easy"); - case NODE_TYPE_ID_NANO_EASY_STD: return F("Nano Easy"); - } - return ""; -} - -#ifdef USES_MQTT -String getMQTT_state() { - switch (MQTTclient.state()) { - case MQTT_CONNECTION_TIMEOUT: return F("Connection timeout"); - case MQTT_CONNECTION_LOST: return F("Connection lost"); - case MQTT_CONNECT_FAILED: return F("Connect failed"); - case MQTT_DISCONNECTED: return F("Disconnected"); - case MQTT_CONNECTED: return F("Connected"); - case MQTT_CONNECT_BAD_PROTOCOL: return F("Connect bad protocol"); - case MQTT_CONNECT_BAD_CLIENT_ID: return F("Connect bad client_id"); - case MQTT_CONNECT_UNAVAILABLE: return F("Connect unavailable"); - case MQTT_CONNECT_BAD_CREDENTIALS: return F("Connect bad credentials"); - case MQTT_CONNECT_UNAUTHORIZED: return F("Connect unauthorized"); - default: break; - } - return ""; -} - -#endif // USES_MQTT - -/********************************************************************************************\ - Get system information - \*********************************************************************************************/ -String getLastBootCauseString() { - switch (lastBootCause) - { - case BOOT_CAUSE_MANUAL_REBOOT: return F("Manual reboot"); - case BOOT_CAUSE_DEEP_SLEEP: // nobody should ever see this, since it should sleep again right away. - return F("Deep sleep"); - case BOOT_CAUSE_COLD_BOOT: - return F("Cold boot"); - case BOOT_CAUSE_EXT_WD: - return F("External Watchdog"); - } - return getUnknownString(); -} - -#ifdef ESP32 - -// See https://github.com/espressif/esp-idf/blob/master/components/esp32/include/rom/rtc.h -String getResetReasonString(byte icore) { - bool isDEEPSLEEP_RESET(false); - - switch (rtc_get_reset_reason((RESET_REASON)icore)) { - case NO_MEAN: return F("NO_MEAN"); - case POWERON_RESET: return F("Vbat power on reset"); - case SW_RESET: return F("Software reset digital core"); - case OWDT_RESET: return F("Legacy watch dog reset digital core"); - case DEEPSLEEP_RESET: isDEEPSLEEP_RESET = true; break; - case SDIO_RESET: return F("Reset by SLC module, reset digital core"); - case TG0WDT_SYS_RESET: return F("Timer Group0 Watch dog reset digital core"); - case TG1WDT_SYS_RESET: return F("Timer Group1 Watch dog reset digital core"); - case RTCWDT_SYS_RESET: return F("RTC Watch dog Reset digital core"); - case INTRUSION_RESET: return F("Instrusion tested to reset CPU"); - case TGWDT_CPU_RESET: return F("Time Group reset CPU"); - case SW_CPU_RESET: return F("Software reset CPU"); - case RTCWDT_CPU_RESET: return F("RTC Watch dog Reset CPU"); - case EXT_CPU_RESET: return F("for APP CPU, reseted by PRO CPU"); - case RTCWDT_BROWN_OUT_RESET: return F("Reset when the vdd voltage is not stable"); - case RTCWDT_RTC_RESET: return F("RTC Watch dog reset digital core and rtc module"); - default: break; - } - - if (isDEEPSLEEP_RESET) { - String reason = F("Deep Sleep, Wakeup reason ("); - reason += rtc_get_wakeup_cause(); - reason += ')'; - return reason; - } - return getUnknownString(); -} - -#endif // ifdef ESP32 - -String getResetReasonString() { - #ifdef ESP32 - String reason = F("CPU0: "); - reason += getResetReasonString(0); - reason += F(" CPU1: "); - reason += getResetReasonString(1); - return reason; - #else // ifdef ESP32 - return ESP.getResetReason(); - #endif // ifdef ESP32 -} - -String getSystemBuildString() { - String result; - - result += BUILD; - result += ' '; - result += F(BUILD_NOTES); - return result; -} - -String getPluginDescriptionString() { - String result; - - #ifdef PLUGIN_BUILD_NORMAL - result += F(" [Normal]"); - #endif // ifdef PLUGIN_BUILD_NORMAL - #ifdef PLUGIN_BUILD_TESTING - result += F(" [Testing]"); - #endif // ifdef PLUGIN_BUILD_TESTING - #ifdef PLUGIN_BUILD_DEV - result += F(" [Development]"); - #endif // ifdef PLUGIN_BUILD_DEV - #ifdef PLUGIN_DESCR - result += " ["; - result += F(PLUGIN_DESCR); - result += ']'; - #endif // ifdef PLUGIN_DESCR - #ifdef USE_NON_STANDARD_24_TASKS - result += F(" 24tasks"); - #endif // ifdef USE_NON_STANDARD_24_TASKS - result.trim(); - return result; -} - -String getSystemLibraryString() { - String result; - - #if defined(ESP32) - result += F("ESP32 SDK "); - result += ESP.getSdkVersion(); - #else // if defined(ESP32) - result += F("ESP82xx Core "); - result += ESP.getCoreVersion(); - result += F(", NONOS SDK "); - result += system_get_sdk_version(); - result += F(", LWIP: "); - result += getLWIPversion(); - #endif // if defined(ESP32) - - if (puyaSupport()) { - result += F(" PUYA support"); - } - return result; -} - -#ifdef ESP8266 -String getLWIPversion() { - String result; - - result += LWIP_VERSION_MAJOR; - result += '.'; - result += LWIP_VERSION_MINOR; - result += '.'; - result += LWIP_VERSION_REVISION; - - if (LWIP_VERSION_IS_RC) { - result += F("-RC"); - result += LWIP_VERSION_RC; - } else if (LWIP_VERSION_IS_DEVELOPMENT) { - result += F("-dev"); - } - return result; -} - -#endif // ifdef ESP8266 - -bool puyaSupport() { - bool supported = false; - -#ifdef PUYA_SUPPORT - - // New support starting core 2.5.0 - if (PUYA_SUPPORT) { supported = true; } -#endif // ifdef PUYA_SUPPORT -#ifdef PUYASUPPORT - - // Old patch - supported = true; -#endif // ifdef PUYASUPPORT - return supported; -} - -uint8_t getFlashChipVendorId() { -#ifdef PUYA_SUPPORT - return ESP.getFlashChipVendorId(); -#else // ifdef PUYA_SUPPORT - # if defined(ESP8266) - uint32_t flashChipId = ESP.getFlashChipId(); - return flashChipId & 0x000000ff; - # else // if defined(ESP8266) - return 0xFF; // Not an existing function for ESP32 - # endif // if defined(ESP8266) -#endif // ifdef PUYA_SUPPORT -} - -bool flashChipVendorPuya() { - uint8_t vendorId = getFlashChipVendorId(); - - return vendorId == 0x85; // 0x146085 PUYA -} - -/*********************************************************************************************\ - Memory management -\*********************************************************************************************/ - - -// For keeping track of 'cont' stack -// See: https://github.com/esp8266/Arduino/issues/2557 -// https://github.com/esp8266/Arduino/issues/5148#issuecomment-424329183 -// https://github.com/letscontrolit/ESPEasy/issues/1824 -#ifdef ESP32 - -// FIXME TD-er: For ESP32 you need to provide the task number, or NULL to get from the calling task. -uint32_t getCurrentFreeStack() { - register uint8_t *sp asm ("a1"); - - return sp - pxTaskGetStackStart(NULL); -} - -uint32_t getFreeStackWatermark() { - return uxTaskGetStackHighWaterMark(NULL); -} - -// FIXME TD-er: Must check if these functions are also needed for ESP32. -bool canYield() { - return true; -} - -#else // ifdef ESP32 - -uint32_t getCurrentFreeStack() { - // https://github.com/esp8266/Arduino/issues/2557 - register uint32_t *sp asm ("a1"); - - return 4 * (sp - g_pcont->stack); -} - -uint32_t getFreeStackWatermark() { - return cont_get_free_stack(g_pcont); -} - -bool canYield() { - return cont_can_yield(g_pcont); -} - -bool allocatedOnStack(const void *address) { - register uint32_t *sp asm ("a1"); - - if (sp < address) { return false; } - return g_pcont->stack < address; -} - -#endif // ESP32 +#include "../Helpers/ESPEasy_FactoryDefault.h" +#include "../Helpers/ESPEasy_Storage.h" +#include "../Helpers/Numerical.h" +#include "../Helpers/PeriodicalActions.h" +#include "../Helpers/StringConverter.h" +#include "../Helpers/StringParser.h" bool remoteConfig(struct EventStruct *event, const String& string) @@ -368,162 +45,6 @@ bool remoteConfig(struct EventStruct *event, const String& string) return success; } -/*********************************************************************************************\ - Collect the stored preference for factory default -\*********************************************************************************************/ -void applyFactoryDefaultPref() { - // TODO TD-er: Store it in more places to make it more persistent - Settings.ResetFactoryDefaultPreference = ResetFactoryDefaultPreference.getPreference(); -} - -/*********************************************************************************************\ - Device GPIO name functions to share flash strings -\*********************************************************************************************/ -String formatGpioDirection(gpio_direction direction) { - switch (direction) { - case gpio_input: return F("← "); - case gpio_output: return F("→ "); - case gpio_bidirectional: return F("⇄ "); - } - return ""; -} - -String formatGpioLabel(int gpio, bool includeWarning) { - int pinnr = -1; - bool input, output, warning; - - if (getGpioInfo(gpio, pinnr, input, output, warning)) { - if (!includeWarning) { - return createGPIO_label(gpio, pinnr, true, true, false); - } - return createGPIO_label(gpio, pinnr, input, output, warning); - } - return "-"; -} - -String formatGpioName(const String& label, gpio_direction direction, bool optional) { - int reserveLength = 5 /* "GPIO " */ + 8 /* "⇄ " */ + label.length(); - - if (optional) { - reserveLength += 11; - } - String result; - - result.reserve(reserveLength); - result += F("GPIO "); - result += formatGpioDirection(direction); - result += label; - - if (optional) { - result += F("(optional)"); - } - return result; -} - -String formatGpioName(const String& label, gpio_direction direction) { - return formatGpioName(label, direction, false); -} - -String formatGpioName_input(const String& label) { - return formatGpioName(label, gpio_input, false); -} - -String formatGpioName_output(const String& label) { - return formatGpioName(label, gpio_output, false); -} - -String formatGpioName_bidirectional(const String& label) { - return formatGpioName(label, gpio_bidirectional, false); -} - -String formatGpioName_input_optional(const String& label) { - return formatGpioName(label, gpio_input, true); -} - -String formatGpioName_output_optional(const String& label) { - return formatGpioName(label, gpio_output, true); -} - -// RX/TX are the only signals which are crossed, so they must be labelled like this: -// "GPIO <-- TX" and "GPIO --> RX" -String formatGpioName_TX(bool optional) { - return formatGpioName(F("RX"), gpio_output, optional); -} - -String formatGpioName_RX(bool optional) { - return formatGpioName(F("TX"), gpio_input, optional); -} - -String formatGpioName_TX_HW(bool optional) { - return formatGpioName(F("RX (HW)"), gpio_output, optional); -} - -String formatGpioName_RX_HW(bool optional) { - return formatGpioName(F("TX (HW)"), gpio_input, optional); -} - -#ifdef ESP32 - -String formatGpioName_ADC(int gpio_pin) { - int adc, ch, t; - - if (getADC_gpio_info(gpio_pin, adc, ch, t)) { - if (adc == 0) { - return F("Hall Effect"); - } - String res = F("ADC# ch?"); - res.replace("#", String(adc)); - res.replace("?", String(ch)); - - if (t >= 0) { - res += F(" (T"); - res += t; - res += ')'; - } - return res; - } - return ""; -} - -#endif // ifdef ESP32 - -// ******************************************************************************** -// Add a GPIO pin select dropdown list for 8266, 8285 or ESP32 -// ******************************************************************************** -String createGPIO_label(int gpio, int pinnr, bool input, bool output, bool warning) { - if (gpio < 0) { return F("- None -"); } - String result; - - result.reserve(24); - result = F("GPIO-"); - result += gpio; - - if (pinnr >= 0) { - result += F(" (D"); - result += pinnr; - result += ')'; - } - - if (input != output) { - result += ' '; - result += input ? F(HTML_SYMBOL_INPUT) : F(HTML_SYMBOL_OUTPUT); - } - - if (warning) { - result += ' '; - result += F(HTML_SYMBOL_WARNING); - } - bool serialPinConflict = (Settings.UseSerial && (gpio == 1 || gpio == 3)); - - if (serialPinConflict) { - if (gpio == 1) { result += F(" TX0"); } - - if (gpio == 3) { result += F(" RX0"); } - } - return result; -} - - #if defined(ESP32) void analogWriteESP32(int pin, int value) { @@ -556,77 +77,6 @@ void analogWriteESP32(int pin, int value) #endif // if defined(ESP32) -/********************************************************************************************\ - Status LED - \*********************************************************************************************/ -void statusLED(bool traffic) -{ - static int gnStatusValueCurrent = -1; - static long int gnLastUpdate = millis(); - - if (Settings.Pin_status_led == -1) { - return; - } - - if (gnStatusValueCurrent < 0) { - pinMode(Settings.Pin_status_led, OUTPUT); - } - - int nStatusValue = gnStatusValueCurrent; - - if (traffic) - { - nStatusValue += STATUS_PWM_TRAFFICRISE; // ramp up fast - } - else - { - if (NetworkConnected()) - { - long int delta = timePassedSince(gnLastUpdate); - - if ((delta > 0) || (delta < 0)) - { - nStatusValue -= STATUS_PWM_NORMALFADE; // ramp down slowly - nStatusValue = std::max(nStatusValue, STATUS_PWM_NORMALVALUE); - gnLastUpdate = millis(); - } - } - - // AP mode is active - else if (WifiIsAP(WiFi.getMode())) - { - nStatusValue = ((millis() >> 1) & PWMRANGE_FULL) - (PWMRANGE_FULL >> 2); // ramp up for 2 sec, 3/4 luminosity - } - - // Disconnected - else - { - nStatusValue = (millis() >> 1) & (PWMRANGE_FULL >> 2); // ramp up for 1/2 sec, 1/4 luminosity - } - } - - nStatusValue = constrain(nStatusValue, 0, PWMRANGE_FULL); - - if (gnStatusValueCurrent != nStatusValue) - { - gnStatusValueCurrent = nStatusValue; - - long pwm = nStatusValue * nStatusValue; // simple gamma correction - pwm >>= 10; - - if (Settings.Pin_status_led_Inversed) { - pwm = PWMRANGE_FULL - pwm; - } - - #if defined(ESP8266) - analogWrite(Settings.Pin_status_led, pwm); - #endif // if defined(ESP8266) - #if defined(ESP32) - analogWriteESP32(Settings.Pin_status_led, pwm); - #endif // if defined(ESP32) - } -} - /********************************************************************************************\ delay in milliseconds with background processing \*********************************************************************************************/ @@ -639,52 +89,6 @@ void delayBackground(unsigned long dsdelay) } } -/********************************************************************************************\ - Check to see if a given argument is a valid taskIndex (argc = 0 => command) - \*********************************************************************************************/ -taskIndex_t parseCommandArgumentTaskIndex(const String& string, unsigned int argc) -{ - taskIndex_t taskIndex = INVALID_TASK_INDEX; - const int ti = parseCommandArgumentInt(string, argc); - - if (ti > 0) { - // Task Index used as argument in commands start at 1. - taskIndex = static_cast(ti - 1); - } - return taskIndex; -} - -/********************************************************************************************\ - Get int from command argument (argc = 0 => command) - \*********************************************************************************************/ -int parseCommandArgumentInt(const String& string, unsigned int argc) -{ - int value = 0; - - if (argc > 0) { - // No need to check for the command (argc == 0) - String TmpStr; - - if (GetArgv(string.c_str(), TmpStr, argc + 1)) { - value = CalculateParam(TmpStr.c_str()); - } - } - return value; -} - -/********************************************************************************************\ - Parse a command string to event struct - \*********************************************************************************************/ -void parseCommandString(struct EventStruct *event, const String& string) -{ - checkRAM(F("parseCommandString")); - event->Par1 = parseCommandArgumentInt(string, 1); - event->Par2 = parseCommandArgumentInt(string, 2); - event->Par3 = parseCommandArgumentInt(string, 3); - event->Par4 = parseCommandArgumentInt(string, 4); - event->Par5 = parseCommandArgumentInt(string, 5); -} - /********************************************************************************************\ Toggle controller enabled state \*********************************************************************************************/ @@ -814,7 +218,6 @@ String getTaskDeviceName(taskIndex_t TaskIndex) { return ExtraTaskSettings.TaskDeviceName; } - /********************************************************************************************\ If RX and TX tied together, perform emergency reset to get the system out of boot loops \*********************************************************************************************/ @@ -836,33 +239,6 @@ void emergencyReset() } } -/********************************************************************************************\ - Get free system mem - \*********************************************************************************************/ -unsigned long FreeMem(void) -{ - #if defined(ESP8266) - return system_get_free_heap_size(); - #endif // if defined(ESP8266) - #if defined(ESP32) - return ESP.getFreeHeap(); - #endif // if defined(ESP32) -} - -unsigned long getMaxFreeBlock() -{ - unsigned long freemem = FreeMem(); - - #ifdef CORE_POST_2_5_0 - - // computing max free block is a rather extensive operation, so only perform when free memory is already low. - if (freemem < 6144) { - return ESP.getMaxFreeBlockSize(); - } - #endif // ifdef CORE_POST_2_5_0 - return freemem; -} - void logtimeStringToSeconds(const String& tBuf, int hours, int minutes, int seconds) { #ifndef BUILD_NO_DEBUG @@ -961,10 +337,6 @@ void reboot() { #endif // if defined(ESP32) } - - - - void SendValueLogger(taskIndex_t TaskIndex) { #if !defined(BUILD_NO_DEBUG) || defined(FEATURE_SD) @@ -1012,287 +384,6 @@ void SendValueLogger(taskIndex_t TaskIndex) #endif // ifdef FEATURE_SD } -// #ifdef PLUGIN_BUILD_TESTING - -// #define isdigit(n) (n >= '0' && n <= '9') //Conflicts with ArduJson 6+, when this lib is used there is no need for this macro - -/********************************************************************************************\ - Generate a tone of specified frequency on pin - \*********************************************************************************************/ -void tone_espEasy(uint8_t _pin, unsigned int frequency, unsigned long duration) { - #ifdef ESP32 - toneESP32(_pin, frequency, duration); - #else // ifdef ESP32 - analogWriteFreq(frequency); - - // NOTE: analogwrite reserves IRAM and uninitalized ram. - analogWrite(_pin, 100); - delay(duration); - analogWrite(_pin, 0); - #endif // ifdef ESP32 -} - -/********************************************************************************************\ - Play RTTTL string on specified pin - \*********************************************************************************************/ -void play_rtttl(uint8_t _pin, const char *p) -{ - checkRAM(F("play_rtttl")); - #define OCTAVE_OFFSET 0 - - // FIXME: Absolutely no error checking in here - - const int notes[] = { 0, - 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494, - 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988, - 1047,1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976, - 2093,2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951 - }; - - - byte default_dur = 4; - byte default_oct = 6; - int bpm = 63; - int num; - long wholenote; - long duration; - byte note; - byte scale; - - // format: d=N,o=N,b=NNN: - // find the start (skip name, etc) - - while (*p != ':') { p++; // ignore name - } - p++; // skip ':' - - // get default duration - if (*p == 'd') - { - p++; p++; // skip "d=" - num = 0; - - while (isdigit(*p)) - { - num = (num * 10) + (*p++ - '0'); - } - - if (num > 0) { default_dur = num; } - p++; // skip comma - } - - // get default octave - if (*p == 'o') - { - p++; p++; // skip "o=" - num = *p++ - '0'; - - if ((num >= 3) && (num <= 7)) { default_oct = num; } - p++; // skip comma - } - - // get BPM - if (*p == 'b') - { - p++; p++; // skip "b=" - num = 0; - - while (isdigit(*p)) - { - num = (num * 10) + (*p++ - '0'); - } - bpm = num; - p++; // skip colon - } - - // BPM usually expresses the number of quarter notes per minute - wholenote = (60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds) - - // now begin note loop - while (*p) - { - // first, get note duration, if available - num = 0; - - while (isdigit(*p)) - { - num = (num * 10) + (*p++ - '0'); - } - - if (num) { duration = wholenote / num; } - else { duration = wholenote / default_dur; // we will need to check if we are a dotted note after - } - - // now get the note - switch (*p) - { - case 'c': - note = 1; - break; - case 'd': - note = 3; - break; - case 'e': - note = 5; - break; - case 'f': - note = 6; - break; - case 'g': - note = 8; - break; - case 'a': - note = 10; - break; - case 'b': - note = 12; - break; - case 'p': - default: - note = 0; - } - p++; - - // now, get optional '#' sharp - if (*p == '#') - { - note++; - p++; - } - - // now, get optional '.' dotted note - if (*p == '.') - { - duration += duration / 2; - p++; - } - - // now, get scale - if (isdigit(*p)) - { - scale = *p - '0'; - p++; - } - else - { - scale = default_oct; - } - - scale += OCTAVE_OFFSET; - - if (*p == ',') { - p++; // skip comma for next note (or we may be at the end) - } - - // now play the note - if (note) - { - tone_espEasy(_pin, notes[(scale - 4) * 12 + note], duration); - } - else - { - delay(duration / 10); - } - } - checkRAM(F("play_rtttl2")); -} - -// #endif - -bool OTA_possible(uint32_t& maxSketchSize, bool& use2step) { -#if defined(ESP8266) - - // Compute the current free space and sketch size, rounded to 4k blocks. - // These block bounaries are needed for erasing a full block on flash. - const uint32_t freeSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; - const uint32_t currentSketchSize = (ESP.getSketchSize() + 0x1000) & 0xFFFFF000; - const uint32_t smallestOtaImageSizeNeeded = (((SMALLEST_OTA_IMAGE + 16) + 0x1000) & 0xFFFFF000); - const bool otaPossible = freeSketchSpace >= smallestOtaImageSizeNeeded; - use2step = freeSketchSpace < currentSketchSize; // Assume the new image has the same size. - - if (use2step) { - const uint32_t totalSketchSpace = freeSketchSpace + currentSketchSize; - maxSketchSize = totalSketchSpace - smallestOtaImageSizeNeeded; - } else { - maxSketchSize = freeSketchSpace; - } - maxSketchSize -= 16; // Must leave 16 bytes at the end. - - if (maxSketchSize > MAX_SKETCH_SIZE) { maxSketchSize = MAX_SKETCH_SIZE; } - return otaPossible; -#elif defined(ESP32) - maxSketchSize = MAX_SKETCH_SIZE; - use2step = false; - return true; -#else // if defined(ESP8266) - return false; -#endif // if defined(ESP8266) -} - -#ifdef FEATURE_ARDUINO_OTA - -/********************************************************************************************\ - Allow updating via the Arduino OTA-protocol. (this allows you to upload directly from platformio) - \*********************************************************************************************/ -void ArduinoOTAInit() -{ - checkRAM(F("ArduinoOTAInit")); - - ArduinoOTA.setPort(ARDUINO_OTA_PORT); - ArduinoOTA.setHostname(Settings.getHostname().c_str()); - - if (SecuritySettings.Password[0] != 0) { - ArduinoOTA.setPassword(SecuritySettings.Password); - } - - ArduinoOTA.onStart([]() { - serialPrintln(F("OTA : Start upload")); - ArduinoOTAtriggered = true; - ESPEASY_FS.end(); // important, otherwise it fails - }); - - ArduinoOTA.onEnd([]() { - serialPrintln(F("\nOTA : End")); - - // "dangerous": if you reset during flash you have to reflash via serial - // so dont touch device until restart is complete - serialPrintln(F("\nOTA : DO NOT RESET OR POWER OFF UNTIL BOOT+FLASH IS COMPLETE.")); - - // delay(100); - // reboot(); //Not needed, node reboots automaticall after calling onEnd and succesfully flashing - }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - if (Settings.UseSerial) { - Serial.printf("OTA : Progress %u%%\r", (progress / (total / 100))); - } - }); - - ArduinoOTA.onError([](ota_error_t error) { - serialPrint(F("\nOTA : Error (will reboot): ")); - - if (error == OTA_AUTH_ERROR) { serialPrintln(F("Auth Failed")); } - else if (error == OTA_BEGIN_ERROR) { serialPrintln(F("Begin Failed")); } - else if (error == OTA_CONNECT_ERROR) { serialPrintln(F("Connect Failed")); } - else if (error == OTA_RECEIVE_ERROR) { serialPrintln(F("Receive Failed")); } - else if (error == OTA_END_ERROR) { serialPrintln(F("End Failed")); } - - delay(100); - reboot(); - }); - ArduinoOTA.begin(); - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("OTA : Arduino OTA enabled on port "); - log += ARDUINO_OTA_PORT; - addLog(LOG_LEVEL_INFO, log); - } -} - -#endif // ifdef FEATURE_ARDUINO_OTA - - - - // ####################################################################################################### // ############################ quite acurate but slow color converter#################################### // ####################################################################################################### diff --git a/src/src/Helpers/Misc.h b/src/src/Helpers/Misc.h index 742993701..a3e3ab717 100644 --- a/src/src/Helpers/Misc.h +++ b/src/src/Helpers/Misc.h @@ -7,176 +7,19 @@ #include "../../ESPEasy-Globals.h" -#define HTML_SYMBOL_WARNING "⚠" -#define HTML_SYMBOL_INPUT "⇐" -#define HTML_SYMBOL_OUTPUT "⇒" -#define HTML_SYMBOL_I_O "⇔" - - -#ifdef ESP32 - -// MFD: adding tone support here while waiting for the Arduino Espressif implementation to catch up -// As recomandation is not to use external libraries the following code was taken from: https://github.com/lbernstone/Tone Thanks - # define TONE_CHANNEL 15 - -void noToneESP32(uint8_t pin, - uint8_t channel = TONE_CHANNEL); - -void toneESP32(uint8_t pin, - unsigned int frequency, - unsigned long duration, - uint8_t channel = TONE_CHANNEL); - -#endif // ifdef ESP32 - -/*********************************************************************************************\ - ESPEasy specific strings -\*********************************************************************************************/ - - -String getNodeTypeDisplayString(byte nodeType); - - -#ifdef USES_MQTT -String getMQTT_state(); -#endif // USES_MQTT - -/********************************************************************************************\ - Get system information - \*********************************************************************************************/ -String getLastBootCauseString(); - -#ifdef ESP32 - -// See https://github.com/espressif/esp-idf/blob/master/components/esp32/include/rom/rtc.h -String getResetReasonString(byte icore); -#endif // ifdef ESP32 - -String getResetReasonString(); - -String getSystemBuildString(); - -String getPluginDescriptionString(); - -String getSystemLibraryString(); - -#ifdef ESP8266 -String getLWIPversion(); -#endif // ifdef ESP8266 - -bool puyaSupport(); - -uint8_t getFlashChipVendorId(); - -bool flashChipVendorPuya(); - - -/*********************************************************************************************\ - Memory management -\*********************************************************************************************/ - - -// For keeping track of 'cont' stack -// See: https://github.com/esp8266/Arduino/issues/2557 -// https://github.com/esp8266/Arduino/issues/5148#issuecomment-424329183 -// https://github.com/letscontrolit/ESPEasy/issues/1824 -#ifdef ESP32 - -// FIXME TD-er: For ESP32 you need to provide the task number, or NULL to get from the calling task. -uint32_t getCurrentFreeStack(); - -uint32_t getFreeStackWatermark(); - -// FIXME TD-er: Must check if these functions are also needed for ESP32. -bool canYield(); - -#else // ifdef ESP32 - -extern "C" { -# include -extern cont_t *g_pcont; -} - -uint32_t getCurrentFreeStack(); - -uint32_t getFreeStackWatermark(); - -bool canYield(); - -bool allocatedOnStack(const void *address); - -#endif // ESP32 bool remoteConfig(struct EventStruct *event, const String & string); -/*********************************************************************************************\ - Collect the stored preference for factory default -\*********************************************************************************************/ -void applyFactoryDefaultPref(); - - -/*********************************************************************************************\ - Device GPIO name functions to share flash strings -\*********************************************************************************************/ -String formatGpioDirection(gpio_direction direction); - -String formatGpioLabel(int gpio, - bool includeWarning); - -String formatGpioName(const String & label, - gpio_direction direction, - bool optional); - -String formatGpioName(const String & label, - gpio_direction direction); - -String formatGpioName_input(const String& label); -String formatGpioName_output(const String& label); -String formatGpioName_bidirectional(const String& label); -String formatGpioName_input_optional(const String& label); - -String formatGpioName_output_optional(const String& label); - -// RX/TX are the only signals which are crossed, so they must be labelled like this: -// "GPIO <-- TX" and "GPIO --> RX" -String formatGpioName_TX(bool optional); - -String formatGpioName_RX(bool optional); - -String formatGpioName_TX_HW(bool optional); - -String formatGpioName_RX_HW(bool optional); - -#ifdef ESP32 - -String formatGpioName_ADC(int gpio_pin); - -#endif // ifdef ESP32 - -String createGPIO_label(int gpio, - int pinnr, - bool input, - bool output, - bool warning); #if defined(ESP32) -void analogWriteESP32(int pin, - int value); +void analogWriteESP32(int pin, + int value); #endif // if defined(ESP32) -/********************************************************************************************\ - Status LED - \*********************************************************************************************/ -#define PWMRANGE_FULL 1023 -#define STATUS_PWM_NORMALVALUE (PWMRANGE_FULL >> 2) -#define STATUS_PWM_NORMALFADE (PWMRANGE_FULL >> 8) -#define STATUS_PWM_TRAFFICRISE (PWMRANGE_FULL >> 1) - -void statusLED(bool traffic); /********************************************************************************************\ delay in milliseconds with background processing @@ -184,26 +27,6 @@ void statusLED(bool traffic); void delayBackground(unsigned long dsdelay); -/********************************************************************************************\ - Check to see if a given argument is a valid taskIndex (argc = 0 => command) - \*********************************************************************************************/ -taskIndex_t parseCommandArgumentTaskIndex(const String& string, - unsigned int argc); - - -/********************************************************************************************\ - Get int from command argument (argc = 0 => command) - \*********************************************************************************************/ -int parseCommandArgumentInt(const String& string, - unsigned int argc); - -/********************************************************************************************\ - Parse a command string to event struct - \*********************************************************************************************/ -void parseCommandString(struct EventStruct *event, - const String & string); - - /********************************************************************************************\ Toggle controller enabled state \*********************************************************************************************/ @@ -294,17 +117,10 @@ String getTaskDeviceName(taskIndex_t TaskIndex); void emergencyReset(); -/********************************************************************************************\ - Get free system mem - \*********************************************************************************************/ -unsigned long FreeMem(void); - -unsigned long getMaxFreeBlock(); - -void logtimeStringToSeconds(const String& tBuf, - int hours, - int minutes, - int seconds); +void logtimeStringToSeconds(const String& tBuf, + int hours, + int minutes, + int seconds); // convert old and new time string to nr of seconds // return whether it should be considered a time string. @@ -315,46 +131,13 @@ bool timeStringToSeconds(const String& tBuf, /********************************************************************************************\ Delayed reboot, in case of issues, do not reboot with high frequency as it might not help... \*********************************************************************************************/ -void delayedReboot(int rebootDelay); +void delayedReboot(int rebootDelay); -void reboot(); +void reboot(); +void SendValueLogger(taskIndex_t TaskIndex); -void SendValueLogger(taskIndex_t TaskIndex); - - -// #ifdef PLUGIN_BUILD_TESTING - -// #define isdigit(n) (n >= '0' && n <= '9') //Conflicts with ArduJson 6+, when this lib is used there is no need for this macro - -/********************************************************************************************\ - Generate a tone of specified frequency on pin - \*********************************************************************************************/ -void tone_espEasy(uint8_t _pin, - unsigned int frequency, - unsigned long duration); - -/********************************************************************************************\ - Play RTTTL string on specified pin - \*********************************************************************************************/ -void play_rtttl(uint8_t _pin, - const char *p); - -// #endif - -bool OTA_possible(uint32_t& maxSketchSize, - bool & use2step); - -#ifdef FEATURE_ARDUINO_OTA - -/********************************************************************************************\ - Allow updating via the Arduino OTA-protocol. (this allows you to upload directly from platformio) - \*********************************************************************************************/ - -void ArduinoOTAInit(); - -#endif // ifdef FEATURE_ARDUINO_OTA diff --git a/src/src/Helpers/Network.cpp b/src/src/Helpers/Network.cpp new file mode 100644 index 000000000..68e957edb --- /dev/null +++ b/src/src/Helpers/Network.cpp @@ -0,0 +1,83 @@ +#include "../Helpers/Network.h" + +#include + +#include "../../ESPEasyWifi.h" +#include "../../ESPEasyNetwork.h" +#include "../../ESPEasy_common.h" + +#include "../Globals/Settings.h" + +#include "../Helpers/ESPEasy_time_calc.h" +#include "../Helpers/Misc.h" + +/********************************************************************************************\ + Status LED + \*********************************************************************************************/ +void statusLED(bool traffic) +{ + static int gnStatusValueCurrent = -1; + static long int gnLastUpdate = millis(); + + if (Settings.Pin_status_led == -1) { + return; + } + + if (gnStatusValueCurrent < 0) { + pinMode(Settings.Pin_status_led, OUTPUT); + } + + int nStatusValue = gnStatusValueCurrent; + + if (traffic) + { + nStatusValue += STATUS_PWM_TRAFFICRISE; // ramp up fast + } + else + { + if (NetworkConnected()) + { + long int delta = timePassedSince(gnLastUpdate); + + if ((delta > 0) || (delta < 0)) + { + nStatusValue -= STATUS_PWM_NORMALFADE; // ramp down slowly + nStatusValue = std::max(nStatusValue, STATUS_PWM_NORMALVALUE); + gnLastUpdate = millis(); + } + } + + // AP mode is active + else if (WifiIsAP(WiFi.getMode())) + { + nStatusValue = ((millis() >> 1) & PWMRANGE_FULL) - (PWMRANGE_FULL >> 2); // ramp up for 2 sec, 3/4 luminosity + } + + // Disconnected + else + { + nStatusValue = (millis() >> 1) & (PWMRANGE_FULL >> 2); // ramp up for 1/2 sec, 1/4 luminosity + } + } + + nStatusValue = constrain(nStatusValue, 0, PWMRANGE_FULL); + + if (gnStatusValueCurrent != nStatusValue) + { + gnStatusValueCurrent = nStatusValue; + + long pwm = nStatusValue * nStatusValue; // simple gamma correction + pwm >>= 10; + + if (Settings.Pin_status_led_Inversed) { + pwm = PWMRANGE_FULL - pwm; + } + + #if defined(ESP8266) + analogWrite(Settings.Pin_status_led, pwm); + #endif // if defined(ESP8266) + #if defined(ESP32) + analogWriteESP32(Settings.Pin_status_led, pwm); + #endif // if defined(ESP32) + } +} \ No newline at end of file diff --git a/src/src/Helpers/Network.h b/src/src/Helpers/Network.h new file mode 100644 index 000000000..c2b859848 --- /dev/null +++ b/src/src/Helpers/Network.h @@ -0,0 +1,15 @@ +#ifndef HELPERS_NETWORK_H +#define HELPERS_NETWORK_H + +/********************************************************************************************\ + Status LED + \*********************************************************************************************/ +#define PWMRANGE_FULL 1023 +#define STATUS_PWM_NORMALVALUE (PWMRANGE_FULL >> 2) +#define STATUS_PWM_NORMALFADE (PWMRANGE_FULL >> 8) +#define STATUS_PWM_TRAFFICRISE (PWMRANGE_FULL >> 1) + +void statusLED(bool traffic); + + +#endif \ No newline at end of file diff --git a/src/src/Helpers/OTA.cpp b/src/src/Helpers/OTA.cpp new file mode 100644 index 000000000..b903c367e --- /dev/null +++ b/src/src/Helpers/OTA.cpp @@ -0,0 +1,99 @@ +#include "OTA.h" + +#include + +#include "../../ESPEasy-Globals.h" +#include "../Globals/SecuritySettings.h" +#include "../Globals/Services.h" +#include "../Helpers/Misc.h" + +bool OTA_possible(uint32_t& maxSketchSize, bool& use2step) { +#if defined(ESP8266) + + // Compute the current free space and sketch size, rounded to 4k blocks. + // These block bounaries are needed for erasing a full block on flash. + const uint32_t freeSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; + const uint32_t currentSketchSize = (ESP.getSketchSize() + 0x1000) & 0xFFFFF000; + const uint32_t smallestOtaImageSizeNeeded = (((SMALLEST_OTA_IMAGE + 16) + 0x1000) & 0xFFFFF000); + const bool otaPossible = freeSketchSpace >= smallestOtaImageSizeNeeded; + use2step = freeSketchSpace < currentSketchSize; // Assume the new image has the same size. + + if (use2step) { + const uint32_t totalSketchSpace = freeSketchSpace + currentSketchSize; + maxSketchSize = totalSketchSpace - smallestOtaImageSizeNeeded; + } else { + maxSketchSize = freeSketchSpace; + } + maxSketchSize -= 16; // Must leave 16 bytes at the end. + + if (maxSketchSize > MAX_SKETCH_SIZE) { maxSketchSize = MAX_SKETCH_SIZE; } + return otaPossible; +#elif defined(ESP32) + maxSketchSize = MAX_SKETCH_SIZE; + use2step = false; + return true; +#else // if defined(ESP8266) + return false; +#endif // if defined(ESP8266) +} + +#ifdef FEATURE_ARDUINO_OTA + +/********************************************************************************************\ + Allow updating via the Arduino OTA-protocol. (this allows you to upload directly from platformio) + \*********************************************************************************************/ +void ArduinoOTAInit() +{ + checkRAM(F("ArduinoOTAInit")); + + ArduinoOTA.setPort(ARDUINO_OTA_PORT); + ArduinoOTA.setHostname(Settings.getHostname().c_str()); + + if (SecuritySettings.Password[0] != 0) { + ArduinoOTA.setPassword(SecuritySettings.Password); + } + + ArduinoOTA.onStart([]() { + serialPrintln(F("OTA : Start upload")); + ArduinoOTAtriggered = true; + ESPEASY_FS.end(); // important, otherwise it fails + }); + + ArduinoOTA.onEnd([]() { + serialPrintln(F("\nOTA : End")); + + // "dangerous": if you reset during flash you have to reflash via serial + // so dont touch device until restart is complete + serialPrintln(F("\nOTA : DO NOT RESET OR POWER OFF UNTIL BOOT+FLASH IS COMPLETE.")); + + // delay(100); + // reboot(); //Not needed, node reboots automaticall after calling onEnd and succesfully flashing + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + if (Settings.UseSerial) { + Serial.printf("OTA : Progress %u%%\r", (progress / (total / 100))); + } + }); + + ArduinoOTA.onError([](ota_error_t error) { + serialPrint(F("\nOTA : Error (will reboot): ")); + + if (error == OTA_AUTH_ERROR) { serialPrintln(F("Auth Failed")); } + else if (error == OTA_BEGIN_ERROR) { serialPrintln(F("Begin Failed")); } + else if (error == OTA_CONNECT_ERROR) { serialPrintln(F("Connect Failed")); } + else if (error == OTA_RECEIVE_ERROR) { serialPrintln(F("Receive Failed")); } + else if (error == OTA_END_ERROR) { serialPrintln(F("End Failed")); } + + delay(100); + reboot(); + }); + ArduinoOTA.begin(); + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + String log = F("OTA : Arduino OTA enabled on port "); + log += ARDUINO_OTA_PORT; + addLog(LOG_LEVEL_INFO, log); + } +} + +#endif // ifdef FEATURE_ARDUINO_OTA \ No newline at end of file diff --git a/src/src/Helpers/OTA.h b/src/src/Helpers/OTA.h new file mode 100644 index 000000000..6485ea2ba --- /dev/null +++ b/src/src/Helpers/OTA.h @@ -0,0 +1,20 @@ +#ifndef HELPERS_OTA_H +#define HELPERS_OTA_H + +#include "../../ESPEasy_common.h" + +bool OTA_possible(uint32_t& maxSketchSize, + bool & use2step); + +#ifdef FEATURE_ARDUINO_OTA + +/********************************************************************************************\ + Allow updating via the Arduino OTA-protocol. (this allows you to upload directly from platformio) + \*********************************************************************************************/ + +void ArduinoOTAInit(); + +#endif // ifdef FEATURE_ARDUINO_OTA + + +#endif \ No newline at end of file diff --git a/src/src/Helpers/PeriodicalActions.cpp b/src/src/Helpers/PeriodicalActions.cpp index b493f5f32..eac9edfa7 100644 --- a/src/src/Helpers/PeriodicalActions.cpp +++ b/src/src/Helpers/PeriodicalActions.cpp @@ -18,7 +18,9 @@ #include "../Globals/Statistics.h" #include "../Helpers/ESPEasyRTC.h" #include "../Helpers/Hardware.h" +#include "../Helpers/Memory.h" #include "../Helpers/Misc.h" +#include "../Helpers/StringGenerator_System.h" /*********************************************************************************************\ diff --git a/src/src/Helpers/Scheduler.cpp b/src/src/Helpers/Scheduler.cpp index e5a081621..8346e5268 100644 --- a/src/src/Helpers/Scheduler.cpp +++ b/src/src/Helpers/Scheduler.cpp @@ -1,5 +1,7 @@ #include "Scheduler.h" +#include "../../ESPEasy_common.h" + #include "../ControllerQueue/DelayQueueElements.h" #include "../Globals/RTC.h" #include "../Helpers/DeepSleep.h" diff --git a/src/src/Helpers/StringGenerator_GPIO.cpp b/src/src/Helpers/StringGenerator_GPIO.cpp new file mode 100644 index 000000000..2957917e6 --- /dev/null +++ b/src/src/Helpers/StringGenerator_GPIO.cpp @@ -0,0 +1,151 @@ +#include "StringGenerator_GPIO.h" + +#include "../Globals/Settings.h" +#include "../Helpers/Hardware.h" + +/*********************************************************************************************\ + Device GPIO name functions to share flash strings +\*********************************************************************************************/ +String formatGpioDirection(gpio_direction direction) { + switch (direction) { + case gpio_input: return F("← "); + case gpio_output: return F("→ "); + case gpio_bidirectional: return F("⇄ "); + } + return ""; +} + +String formatGpioLabel(int gpio, bool includeWarning) { + int pinnr = -1; + bool input, output, warning; + + if (getGpioInfo(gpio, pinnr, input, output, warning)) { + if (!includeWarning) { + return createGPIO_label(gpio, pinnr, true, true, false); + } + return createGPIO_label(gpio, pinnr, input, output, warning); + } + return "-"; +} + +String formatGpioName(const String& label, gpio_direction direction, bool optional) { + int reserveLength = 5 /* "GPIO " */ + 8 /* "⇄ " */ + label.length(); + + if (optional) { + reserveLength += 11; + } + String result; + + result.reserve(reserveLength); + result += F("GPIO "); + result += formatGpioDirection(direction); + result += label; + + if (optional) { + result += F("(optional)"); + } + return result; +} + +String formatGpioName(const String& label, gpio_direction direction) { + return formatGpioName(label, direction, false); +} + +String formatGpioName_input(const String& label) { + return formatGpioName(label, gpio_input, false); +} + +String formatGpioName_output(const String& label) { + return formatGpioName(label, gpio_output, false); +} + +String formatGpioName_bidirectional(const String& label) { + return formatGpioName(label, gpio_bidirectional, false); +} + +String formatGpioName_input_optional(const String& label) { + return formatGpioName(label, gpio_input, true); +} + +String formatGpioName_output_optional(const String& label) { + return formatGpioName(label, gpio_output, true); +} + +// RX/TX are the only signals which are crossed, so they must be labelled like this: +// "GPIO <-- TX" and "GPIO --> RX" +String formatGpioName_TX(bool optional) { + return formatGpioName(F("RX"), gpio_output, optional); +} + +String formatGpioName_RX(bool optional) { + return formatGpioName(F("TX"), gpio_input, optional); +} + +String formatGpioName_TX_HW(bool optional) { + return formatGpioName(F("RX (HW)"), gpio_output, optional); +} + +String formatGpioName_RX_HW(bool optional) { + return formatGpioName(F("TX (HW)"), gpio_input, optional); +} + +#ifdef ESP32 + +String formatGpioName_ADC(int gpio_pin) { + int adc, ch, t; + + if (getADC_gpio_info(gpio_pin, adc, ch, t)) { + if (adc == 0) { + return F("Hall Effect"); + } + String res = F("ADC# ch?"); + res.replace("#", String(adc)); + res.replace("?", String(ch)); + + if (t >= 0) { + res += F(" (T"); + res += t; + res += ')'; + } + return res; + } + return ""; +} + +#endif // ifdef ESP32 + +// ******************************************************************************** +// Add a GPIO pin select dropdown list for 8266, 8285 or ESP32 +// ******************************************************************************** +String createGPIO_label(int gpio, int pinnr, bool input, bool output, bool warning) { + if (gpio < 0) { return F("- None -"); } + String result; + + result.reserve(24); + result = F("GPIO-"); + result += gpio; + + if (pinnr >= 0) { + result += F(" (D"); + result += pinnr; + result += ')'; + } + + if (input != output) { + result += ' '; + result += input ? F(HTML_SYMBOL_INPUT) : F(HTML_SYMBOL_OUTPUT); + } + + if (warning) { + result += ' '; + result += F(HTML_SYMBOL_WARNING); + } + bool serialPinConflict = (Settings.UseSerial && (gpio == 1 || gpio == 3)); + + if (serialPinConflict) { + if (gpio == 1) { result += F(" TX0"); } + + if (gpio == 3) { result += F(" RX0"); } + } + return result; +} diff --git a/src/src/Helpers/StringGenerator_GPIO.h b/src/src/Helpers/StringGenerator_GPIO.h new file mode 100644 index 000000000..5052d9168 --- /dev/null +++ b/src/src/Helpers/StringGenerator_GPIO.h @@ -0,0 +1,65 @@ +#ifndef HELPERS_STRINGGENERATOR_GPIO_H +#define HELPERS_STRINGGENERATOR_GPIO_H + +#include + +#define HTML_SYMBOL_WARNING "⚠" +#define HTML_SYMBOL_INPUT "⇐" +#define HTML_SYMBOL_OUTPUT "⇒" +#define HTML_SYMBOL_I_O "⇔" + + +enum gpio_direction { + gpio_input, + gpio_output, + gpio_bidirectional +}; + + +/*********************************************************************************************\ + Device GPIO name functions to share flash strings +\*********************************************************************************************/ +String formatGpioDirection(gpio_direction direction); + +String formatGpioLabel(int gpio, + bool includeWarning); + +String formatGpioName(const String & label, + gpio_direction direction, + bool optional); + +String formatGpioName(const String & label, + gpio_direction direction); + +String formatGpioName_input(const String& label); +String formatGpioName_output(const String& label); +String formatGpioName_bidirectional(const String& label); +String formatGpioName_input_optional(const String& label); + +String formatGpioName_output_optional(const String& label); + +// RX/TX are the only signals which are crossed, so they must be labelled like this: +// "GPIO <-- TX" and "GPIO --> RX" +String formatGpioName_TX(bool optional); + +String formatGpioName_RX(bool optional); + +String formatGpioName_TX_HW(bool optional); + +String formatGpioName_RX_HW(bool optional); + +#ifdef ESP32 + +String formatGpioName_ADC(int gpio_pin); + +#endif // ifdef ESP32 + +String createGPIO_label(int gpio, + int pinnr, + bool input, + bool output, + bool warning); + + + +#endif \ No newline at end of file diff --git a/src/src/Helpers/StringGenerator_System.cpp b/src/src/Helpers/StringGenerator_System.cpp new file mode 100644 index 000000000..1ea7ac3c4 --- /dev/null +++ b/src/src/Helpers/StringGenerator_System.cpp @@ -0,0 +1,177 @@ +#include "StringGenerator_System.h" + + +#include + + +/*********************************************************************************************\ + ESPEasy specific strings +\*********************************************************************************************/ + + +#ifdef USES_MQTT + +#include +#include "../Globals/MQTT.h" + +String getMQTT_state() { + switch (MQTTclient.state()) { + case MQTT_CONNECTION_TIMEOUT: return F("Connection timeout"); + case MQTT_CONNECTION_LOST: return F("Connection lost"); + case MQTT_CONNECT_FAILED: return F("Connect failed"); + case MQTT_DISCONNECTED: return F("Disconnected"); + case MQTT_CONNECTED: return F("Connected"); + case MQTT_CONNECT_BAD_PROTOCOL: return F("Connect bad protocol"); + case MQTT_CONNECT_BAD_CLIENT_ID: return F("Connect bad client_id"); + case MQTT_CONNECT_UNAVAILABLE: return F("Connect unavailable"); + case MQTT_CONNECT_BAD_CREDENTIALS: return F("Connect bad credentials"); + case MQTT_CONNECT_UNAUTHORIZED: return F("Connect unauthorized"); + default: break; + } + return ""; +} + +#endif // USES_MQTT + +/********************************************************************************************\ + Get system information + \*********************************************************************************************/ +String getLastBootCauseString() { + switch (lastBootCause) + { + case BOOT_CAUSE_MANUAL_REBOOT: return F("Manual reboot"); + case BOOT_CAUSE_DEEP_SLEEP: // nobody should ever see this, since it should sleep again right away. + return F("Deep sleep"); + case BOOT_CAUSE_COLD_BOOT: + return F("Cold boot"); + case BOOT_CAUSE_EXT_WD: + return F("External Watchdog"); + } + return getUnknownString(); +} + +#ifdef ESP32 + +#include + +// See https://github.com/espressif/esp-idf/blob/master/components/esp32/include/rom/rtc.h +String getResetReasonString(byte icore) { + bool isDEEPSLEEP_RESET(false); + + switch (rtc_get_reset_reason((RESET_REASON)icore)) { + case NO_MEAN: return F("NO_MEAN"); + case POWERON_RESET: return F("Vbat power on reset"); + case SW_RESET: return F("Software reset digital core"); + case OWDT_RESET: return F("Legacy watch dog reset digital core"); + case DEEPSLEEP_RESET: isDEEPSLEEP_RESET = true; break; + case SDIO_RESET: return F("Reset by SLC module, reset digital core"); + case TG0WDT_SYS_RESET: return F("Timer Group0 Watch dog reset digital core"); + case TG1WDT_SYS_RESET: return F("Timer Group1 Watch dog reset digital core"); + case RTCWDT_SYS_RESET: return F("RTC Watch dog Reset digital core"); + case INTRUSION_RESET: return F("Instrusion tested to reset CPU"); + case TGWDT_CPU_RESET: return F("Time Group reset CPU"); + case SW_CPU_RESET: return F("Software reset CPU"); + case RTCWDT_CPU_RESET: return F("RTC Watch dog Reset CPU"); + case EXT_CPU_RESET: return F("for APP CPU, reseted by PRO CPU"); + case RTCWDT_BROWN_OUT_RESET: return F("Reset when the vdd voltage is not stable"); + case RTCWDT_RTC_RESET: return F("RTC Watch dog reset digital core and rtc module"); + default: break; + } + + if (isDEEPSLEEP_RESET) { + String reason = F("Deep Sleep, Wakeup reason ("); + reason += rtc_get_wakeup_cause(); + reason += ')'; + return reason; + } + return getUnknownString(); +} + +#endif // ifdef ESP32 + +String getResetReasonString() { + #ifdef ESP32 + String reason = F("CPU0: "); + reason += getResetReasonString(0); + reason += F(" CPU1: "); + reason += getResetReasonString(1); + return reason; + #else // ifdef ESP32 + return ESP.getResetReason(); + #endif // ifdef ESP32 +} + +String getSystemBuildString() { + String result; + + result += BUILD; + result += ' '; + result += F(BUILD_NOTES); + return result; +} + +String getPluginDescriptionString() { + String result; + + #ifdef PLUGIN_BUILD_NORMAL + result += F(" [Normal]"); + #endif // ifdef PLUGIN_BUILD_NORMAL + #ifdef PLUGIN_BUILD_TESTING + result += F(" [Testing]"); + #endif // ifdef PLUGIN_BUILD_TESTING + #ifdef PLUGIN_BUILD_DEV + result += F(" [Development]"); + #endif // ifdef PLUGIN_BUILD_DEV + #ifdef PLUGIN_DESCR + result += " ["; + result += F(PLUGIN_DESCR); + result += ']'; + #endif // ifdef PLUGIN_DESCR + #ifdef USE_NON_STANDARD_24_TASKS + result += F(" 24tasks"); + #endif // ifdef USE_NON_STANDARD_24_TASKS + result.trim(); + return result; +} + +String getSystemLibraryString() { + String result; + + #if defined(ESP32) + result += F("ESP32 SDK "); + result += ESP.getSdkVersion(); + #else // if defined(ESP32) + result += F("ESP82xx Core "); + result += ESP.getCoreVersion(); + result += F(", NONOS SDK "); + result += system_get_sdk_version(); + result += F(", LWIP: "); + result += getLWIPversion(); + #endif // if defined(ESP32) + + if (puyaSupport()) { + result += F(" PUYA support"); + } + return result; +} + +#ifdef ESP8266 +String getLWIPversion() { + String result; + + result += LWIP_VERSION_MAJOR; + result += '.'; + result += LWIP_VERSION_MINOR; + result += '.'; + result += LWIP_VERSION_REVISION; + + if (LWIP_VERSION_IS_RC) { + result += F("-RC"); + result += LWIP_VERSION_RC; + } else if (LWIP_VERSION_IS_DEVELOPMENT) { + result += F("-dev"); + } + return result; +} + +#endif // ifdef ESP8266 diff --git a/src/src/Helpers/StringGenerator_System.h b/src/src/Helpers/StringGenerator_System.h new file mode 100644 index 000000000..11ccd5f43 --- /dev/null +++ b/src/src/Helpers/StringGenerator_System.h @@ -0,0 +1,42 @@ +#ifndef HELPERS_STRINGGENERATOR_SYSTEM_H +#define HELPERS_STRINGGENERATOR_SYSTEM_H + +#include + +#include "../../ESPEasy_common.h" +#include "../Globals/Statistics.h" +#include "../Helpers/Hardware.h" + +/*********************************************************************************************\ + ESPEasy specific strings +\*********************************************************************************************/ + +#ifdef USES_MQTT +String getMQTT_state(); +#endif // USES_MQTT + +/********************************************************************************************\ + Get system information + \*********************************************************************************************/ +String getLastBootCauseString(); + +#ifdef ESP32 + +// See https://github.com/espressif/esp-idf/blob/master/components/esp32/include/rom/rtc.h +String getResetReasonString(byte icore); +#endif // ifdef ESP32 + +String getResetReasonString(); + +String getSystemBuildString(); + +String getPluginDescriptionString(); + +String getSystemLibraryString(); + +#ifdef ESP8266 +String getLWIPversion(); +#endif // ifdef ESP8266 + + +#endif \ No newline at end of file diff --git a/src/src/Helpers/StringParser.cpp b/src/src/Helpers/StringParser.cpp index 42f427c06..493baa409 100644 --- a/src/src/Helpers/StringParser.cpp +++ b/src/src/Helpers/StringParser.cpp @@ -11,7 +11,10 @@ #include "../Helpers/ESPEasy_Storage.h" #include "../Helpers/Misc.h" #include "../Helpers/Numerical.h" +#include "../Helpers/Rules_calculate.h" #include "../Helpers/StringConverter.h" +#include "../Helpers/StringGenerator_GPIO.h" +#include "../Helpers/StringParser.h" /********************************************************************************************\ Parse string template @@ -634,3 +637,50 @@ bool findNextDevValNameInString(const String& input, int& startpos, int& endpos, valueName.toLowerCase(); return true; } + + +/********************************************************************************************\ + Check to see if a given argument is a valid taskIndex (argc = 0 => command) + \*********************************************************************************************/ +taskIndex_t parseCommandArgumentTaskIndex(const String& string, unsigned int argc) +{ + taskIndex_t taskIndex = INVALID_TASK_INDEX; + const int ti = parseCommandArgumentInt(string, argc); + + if (ti > 0) { + // Task Index used as argument in commands start at 1. + taskIndex = static_cast(ti - 1); + } + return taskIndex; +} + +/********************************************************************************************\ + Get int from command argument (argc = 0 => command) + \*********************************************************************************************/ +int parseCommandArgumentInt(const String& string, unsigned int argc) +{ + int value = 0; + + if (argc > 0) { + // No need to check for the command (argc == 0) + String TmpStr; + + if (GetArgv(string.c_str(), TmpStr, argc + 1)) { + value = CalculateParam(TmpStr.c_str()); + } + } + return value; +} + +/********************************************************************************************\ + Parse a command string to event struct + \*********************************************************************************************/ +void parseCommandString(struct EventStruct *event, const String& string) +{ + checkRAM(F("parseCommandString")); + event->Par1 = parseCommandArgumentInt(string, 1); + event->Par2 = parseCommandArgumentInt(string, 2); + event->Par3 = parseCommandArgumentInt(string, 3); + event->Par4 = parseCommandArgumentInt(string, 4); + event->Par5 = parseCommandArgumentInt(string, 5); +} diff --git a/src/src/Helpers/StringParser.h b/src/src/Helpers/StringParser.h index da77b54b1..075f40cd8 100644 --- a/src/src/Helpers/StringParser.h +++ b/src/src/Helpers/StringParser.h @@ -64,5 +64,24 @@ bool findNextDevValNameInString(const String& input, String & format); +/********************************************************************************************\ + Check to see if a given argument is a valid taskIndex (argc = 0 => command) + \*********************************************************************************************/ +taskIndex_t parseCommandArgumentTaskIndex(const String& string, + unsigned int argc); + + +/********************************************************************************************\ + Get int from command argument (argc = 0 => command) + \*********************************************************************************************/ +int parseCommandArgumentInt(const String& string, + unsigned int argc); + +/********************************************************************************************\ + Parse a command string to event struct + \*********************************************************************************************/ +void parseCommandString(struct EventStruct *event, + const String & string); + #endif \ No newline at end of file diff --git a/src/src/Helpers/SystemVariables.cpp b/src/src/Helpers/SystemVariables.cpp index 4f13646cb..278e120b1 100644 --- a/src/src/Helpers/SystemVariables.cpp +++ b/src/src/Helpers/SystemVariables.cpp @@ -1,5 +1,6 @@ #include "SystemVariables.h" +#include "../../ESPEasy_common.h" #include "../../ESPEasy-Globals.h" #include "../DataStructs/TimingStats.h"