mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 04:07:47 +00:00
Compare commits
28
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
545117ddf7 | ||
|
|
8eb479c411 | ||
|
|
b39f51ca3c | ||
|
|
4511e08d3c | ||
|
|
086e836956 | ||
|
|
3e20f617ea | ||
|
|
8d9aacb6a4 | ||
|
|
0670fa98a6 | ||
|
|
2b3d1517c9 | ||
|
|
0be79759d1 | ||
|
|
d47bede215 | ||
|
|
2988a244b2 | ||
|
|
8d87dc0175 | ||
|
|
21c86e666a | ||
|
|
e04f71ab47 | ||
|
|
90ae0720cf | ||
|
|
c8ecd8d374 | ||
|
|
7a451dd672 | ||
|
|
b06f6aa360 | ||
|
|
6b67415c71 | ||
|
|
b095465d3a | ||
|
|
81a5d911ba | ||
|
|
48060d8d99 | ||
|
|
d303fa023f | ||
|
|
29b0cc1b32 | ||
|
|
584abd1e75 | ||
|
|
b4d8be0e59 | ||
|
|
6e7286c6fb |
Vendored
+47
@@ -1,3 +1,50 @@
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181002 (since mega-20181001)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Tue Oct 2 04:00:29 CEST 2018
|
||||
|
||||
Plebs (1):
|
||||
split parseTemplate function
|
||||
|
||||
TD-er (4):
|
||||
[#1798] Bugfix Sonoff Si7021 stability
|
||||
[ESP32] Add default partition table for reference
|
||||
[ESP32] Update to PIO espressif32@1.4.0
|
||||
[Stack] Report stack usage on ESP32 and increase stack for ESP8266normal
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181001 (since mega-20180930)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Mon Oct 1 13:13:13 CEST 2018
|
||||
|
||||
TD-er (4):
|
||||
[#1824] Show stack size on main page
|
||||
[Heap] Use NO_EXTRA_4K_HEAP to get old stack address space
|
||||
[Stack] Check if a block sent to save on SPIFFS is stack allocated
|
||||
[Stack] Revert move Settings from stack to heap
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180930 (since mega-20180927)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Sun Sep 30 04:00:24 CEST 2018
|
||||
|
||||
JojoS (5):
|
||||
fixed distance reading
|
||||
on INIT, delete sensordef before adding new
|
||||
removed sensordefs helper structure
|
||||
changed implementation to use shared_ptr instead of helper structure
|
||||
minor change: unit was missing for threshold in 'state' mode
|
||||
|
||||
TD-er (2):
|
||||
[Default Settings] Properly clear settings when reset to default
|
||||
[Defaults] Other default initializations
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180927 (since mega-20180924)
|
||||
-------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x5000,
|
||||
otadata, data, ota, 0xe000, 0x2000,
|
||||
app0, app, ota_0, 0x10000, 0x140000,
|
||||
app1, app, ota_1, 0x150000,0x140000,
|
||||
eeprom, data, 0x99, 0x290000,0x1000,
|
||||
spiffs, data, spiffs, 0x291000,0x16F000,
|
||||
|
+27
-19
@@ -73,11 +73,14 @@ platform = espressif32@1.2.0
|
||||
[core_esp32_1_3_0]
|
||||
platform = espressif32@1.3.0
|
||||
|
||||
[core_esp32_1_4_0]
|
||||
platform = espressif32@1.4.0
|
||||
|
||||
[core_esp32_stage]
|
||||
platform = https://github.com/platformio/platform-espressif32.git#feature/stage
|
||||
|
||||
[core_esp32]
|
||||
platform = ${core_esp32_1_3_0.platform}
|
||||
platform = ${core_esp32_1_4_0.platform}
|
||||
build_unflags = -Wall
|
||||
build_flags = -D BUILD_GIT='"${sysenv.TRAVIS_TAG}"'
|
||||
lib_ignore = AS_BH1750, ESP8266WiFi, ESP8266Ping, ESP8266WebServer, ESP8266HTTPUpdateServer, ESP8266mDNS, IRremoteESP8266, ESPEasy_ESP8266Ping, SerialSensors, SDM
|
||||
@@ -101,7 +104,10 @@ monitor_speed = 115200
|
||||
; -DVTABLES_IN_DRAM
|
||||
; VTABLES in IRAM
|
||||
; -DVTABLES_IN_IRAM
|
||||
|
||||
; NO_EXTRA_4K_HEAP - this forces the default NONOS-SDK user's heap location
|
||||
; Default currently overlaps cont stack (Arduino) with sys stack (System)
|
||||
; to save up-to 4 kB of heap.
|
||||
; CONT_STACKSIZE to set the 'cont' (Arduino) stack size. Default = 4096
|
||||
|
||||
[common]
|
||||
board_build.f_cpu = 80000000L
|
||||
@@ -123,15 +129,17 @@ board = esp12e
|
||||
platform = ${core_2_4_2.platform}
|
||||
monitor_speed = 115200
|
||||
|
||||
|
||||
[normal]
|
||||
platform = ${common.platform}
|
||||
build_flags = -DNO_EXTRA_4K_HEAP -DCONT_STACKSIZE=5120
|
||||
|
||||
[testing]
|
||||
platform = ${core_2_4_2.platform}
|
||||
build_flags = -DNO_EXTRA_4K_HEAP -DPLUGIN_BUILD_TESTING
|
||||
|
||||
[dev]
|
||||
platform = ${core_2_4_2.platform}
|
||||
build_flags = -DNO_EXTRA_4K_HEAP -DPLUGIN_BUILD_DEV
|
||||
|
||||
[ir]
|
||||
lib_ignore = ESP32_ping, ESP32WebServer
|
||||
@@ -242,7 +250,7 @@ board_upload.maximum_size = ${esp8266_1M.board_upload.maximum_size}
|
||||
board_build.f_cpu = ${esp8266_1M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
|
||||
build_unflags = ${esp8266_1M.build_unflags}
|
||||
build_flags = ${esp8266_1M.build_flags}
|
||||
build_flags = ${esp8266_1M.build_flags} ${normal.build_flags}
|
||||
|
||||
; NORMAL: 1024k for esp8285 ----------------------
|
||||
[env:normal_ESP8285_1024]
|
||||
@@ -259,7 +267,7 @@ board_upload.maximum_size = ${esp8285_1M.board_upload.maximum_size}
|
||||
board_build.f_cpu = ${esp8285_1M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${esp8285_1M.board_build.flash_mode}
|
||||
build_unflags = ${esp8285_1M.build_unflags}
|
||||
build_flags = ${esp8285_1M.build_flags}
|
||||
build_flags = ${esp8285_1M.build_flags} ${normal.build_flags}
|
||||
|
||||
; NORMAL: 2048k version --------------------------
|
||||
[env:normal_WROOM02_2048]
|
||||
@@ -275,7 +283,7 @@ board = ${espWroom2M.board}
|
||||
board_build.f_cpu = ${espWroom2M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${espWroom2M.board_build.flash_mode}
|
||||
build_unflags = ${espWroom2M.build_unflags}
|
||||
build_flags = ${espWroom2M.build_flags}
|
||||
build_flags = ${espWroom2M.build_flags} ${normal.build_flags}
|
||||
|
||||
; NORMAL: 4096k version --------------------------
|
||||
[env:normal_ESP8266_4096]
|
||||
@@ -291,7 +299,7 @@ board = ${common.board}
|
||||
board_build.f_cpu = ${esp8266_4M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${esp8266_4M.board_build.flash_mode}
|
||||
build_unflags = ${esp8266_4M.build_unflags}
|
||||
build_flags = ${esp8266_4M.build_flags}
|
||||
build_flags = ${esp8266_4M.build_flags} ${normal.build_flags}
|
||||
|
||||
|
||||
; NORMAL IR: 4096k version --------------------------
|
||||
@@ -309,7 +317,7 @@ board = ${common.board}
|
||||
board_build.f_cpu = ${esp8266_4M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${esp8266_4M.board_build.flash_mode}
|
||||
build_unflags = ${esp8266_4M.build_unflags}
|
||||
build_flags = ${esp8266_4M.build_flags} -DPLUGIN_BUILD_NORMAL_IR
|
||||
build_flags = ${esp8266_4M.build_flags} ${normal.build_flags} -DPLUGIN_BUILD_NORMAL_IR
|
||||
|
||||
|
||||
;;; TESTING ; ****; ****; ****; ****; ****; ****; ****; ****; ****; ****; ****; ****; ****
|
||||
@@ -331,7 +339,7 @@ board_upload.maximum_size = ${esp8266_1M.board_upload.maximum_size}
|
||||
board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
|
||||
board_build.f_cpu = ${esp8266_1M.board_build.f_cpu}
|
||||
build_unflags = ${esp8266_1M.build_unflags}
|
||||
build_flags = ${esp8266_1M.build_flags} -D PLUGIN_BUILD_TESTING
|
||||
build_flags = ${esp8266_1M.build_flags} ${testing.build_flags}
|
||||
|
||||
; TEST: 1024k for esp8285 ------------------------
|
||||
[env:test_ESP8285_1024]
|
||||
@@ -348,7 +356,7 @@ board_build.f_cpu = ${esp8285_1M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${esp8285_1M.board_build.flash_mode}
|
||||
board = ${esp8285_1M.board}
|
||||
build_unflags = ${esp8285_1M.build_unflags}
|
||||
build_flags = ${esp8285_1M.build_flags} -D PLUGIN_BUILD_TESTING
|
||||
build_flags = ${esp8285_1M.build_flags} ${testing.build_flags}
|
||||
|
||||
; TEST: 2048k version ----------------------------
|
||||
[env:test_WROOM02_2048]
|
||||
@@ -364,7 +372,7 @@ board_build.f_cpu = ${espWroom2M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${espWroom2M.board_build.flash_mode}
|
||||
board = ${espWroom2M.board}
|
||||
build_unflags = ${espWroom2M.build_unflags}
|
||||
build_flags = ${espWroom2M.build_flags} -D PLUGIN_BUILD_TESTING
|
||||
build_flags = ${espWroom2M.build_flags} ${testing.build_flags}
|
||||
|
||||
; TEST: 4096k version ----------------------------
|
||||
[env:test_ESP8266_4096]
|
||||
@@ -380,7 +388,7 @@ monitor_speed = ${common.monitor_speed}
|
||||
board_build.f_cpu = ${esp8266_4M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${esp8266_4M.board_build.flash_mode}
|
||||
build_unflags = ${esp8266_4M.build_unflags}
|
||||
build_flags = ${esp8266_4M.build_flags} -D PLUGIN_BUILD_TESTING
|
||||
build_flags = ${esp8266_4M.build_flags} ${testing.build_flags}
|
||||
|
||||
; TEST: 4096k version + FEATURE_ADC_VCC ----------
|
||||
[env:test_ESP8266_4096_VCC]
|
||||
@@ -396,7 +404,7 @@ monitor_speed = ${common.monitor_speed}
|
||||
board_build.f_cpu = ${esp8266_4M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${esp8266_4M.board_build.flash_mode}
|
||||
build_unflags = ${esp8266_4M.build_unflags}
|
||||
build_flags = ${esp8266_4M.build_flags} -D PLUGIN_BUILD_TESTING -D FEATURE_ADC_VCC=true
|
||||
build_flags = ${esp8266_4M.build_flags} ${testing.build_flags} -D FEATURE_ADC_VCC=true
|
||||
|
||||
|
||||
|
||||
@@ -419,7 +427,7 @@ board_build.f_cpu = ${esp8266_1M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
|
||||
board = ${common.board}
|
||||
build_unflags = ${esp8266_1M.build_unflags}
|
||||
build_flags = ${esp8266_1M.build_flags} -D PLUGIN_BUILD_DEV
|
||||
build_flags = ${esp8266_1M.build_flags} ${dev.build_flags}
|
||||
|
||||
; DEV: 1024k for esp8285 -------------------------
|
||||
[env:dev_ESP8285_1024]
|
||||
@@ -436,7 +444,7 @@ board_build.f_cpu = ${esp8285_1M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${esp8285_1M.board_build.flash_mode}
|
||||
board = ${esp8285_1M.board}
|
||||
build_unflags = ${esp8285_1M.build_unflags}
|
||||
build_flags = ${esp8285_1M.build_flags} -D PLUGIN_BUILD_DEV
|
||||
build_flags = ${esp8285_1M.build_flags} ${dev.build_flags}
|
||||
|
||||
; DEV: 2048k version -----------------------------
|
||||
[env:dev_WROOM02_2048]
|
||||
@@ -452,7 +460,7 @@ board_build.f_cpu = ${espWroom2M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${espWroom2M.board_build.flash_mode}
|
||||
board = ${espWroom2M.board}
|
||||
build_unflags = ${espWroom2M.build_unflags}
|
||||
build_flags = ${espWroom2M.build_flags} -D PLUGIN_BUILD_DEV
|
||||
build_flags = ${espWroom2M.build_flags} ${dev.build_flags}
|
||||
|
||||
; DEV : 4096k version ----------------------------
|
||||
[env:dev_ESP8266_4096]
|
||||
@@ -468,7 +476,7 @@ monitor_speed = ${common.monitor_speed}
|
||||
board_build.f_cpu = ${esp8266_4M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${esp8266_4M.board_build.flash_mode}
|
||||
build_unflags = ${esp8266_4M.build_unflags}
|
||||
build_flags = ${esp8266_4M.build_flags} -D PLUGIN_BUILD_DEV
|
||||
build_flags = ${esp8266_4M.build_flags} ${dev.build_flags}
|
||||
|
||||
|
||||
|
||||
@@ -491,7 +499,7 @@ board_upload.maximum_size = ${esp8266_1M.board_upload.maximum_size}
|
||||
board_build.f_cpu = ${esp8266_1M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
|
||||
build_unflags = ${esp8266_1M.build_unflags}
|
||||
build_flags = ${esp8266_1M.build_flags} -D PLUGIN_BUILD_DEV -D FLASH_QUIRK_WRITE_0_TO_1
|
||||
build_flags = ${esp8266_1M.build_flags} ${dev.build_flags} -D FLASH_QUIRK_WRITE_0_TO_1
|
||||
|
||||
; DEV+PUYA : 1024k version + FEATURE_ADC_VCC -----
|
||||
[env:dev_ESP8266PUYA_1024_VCC]
|
||||
@@ -508,7 +516,7 @@ board_upload.maximum_size = ${esp8266_1M.board_upload.maximum_size}
|
||||
board_build.f_cpu = ${esp8266_1M.board_build.f_cpu}
|
||||
board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
|
||||
build_unflags = ${esp8266_1M.build_unflags}
|
||||
build_flags = ${esp8266_1M.build_flags} -D PLUGIN_BUILD_DEV -D FLASH_QUIRK_WRITE_0_TO_1 -D FEATURE_ADC_VCC=true
|
||||
build_flags = ${esp8266_1M.build_flags} ${dev.build_flags} -D FLASH_QUIRK_WRITE_0_TO_1 -D FEATURE_ADC_VCC=true
|
||||
|
||||
|
||||
|
||||
|
||||
+37
-9
@@ -68,6 +68,9 @@
|
||||
#if defined(ESP32)
|
||||
#define USE_RTOS_MULTITASKING
|
||||
#endif
|
||||
#ifdef M5STACK_ESP
|
||||
// #include <M5Stack.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_USE_RULES false // (true|false) Enable Rules?
|
||||
|
||||
@@ -411,6 +414,9 @@ void addToLog(byte loglevel, const String& string);
|
||||
void addToLog(byte logLevel, const __FlashStringHelper* flashString);
|
||||
void statusLED(boolean traffic);
|
||||
void backgroundtasks();
|
||||
uint32_t getCurrentFreeStack();
|
||||
uint32_t getFreeStackWatermark();
|
||||
bool canYield();
|
||||
|
||||
bool getBitFromUL(uint32_t number, byte bitnr);
|
||||
void setBitToUL(uint32_t& number, byte bitnr, bool value);
|
||||
@@ -684,17 +690,30 @@ struct SettingsStruct
|
||||
if (VariousBits1 > (1 << 30)) VariousBits1 = 0;
|
||||
}
|
||||
|
||||
void clearNetworkSettings() {
|
||||
for (byte i = 0; i < 4; ++i) {
|
||||
IP[i] = 0;
|
||||
Gateway[i] = 0;
|
||||
Subnet[i] = 0;
|
||||
DNS[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void clearAll() {
|
||||
PID = 0;
|
||||
Version = 0;
|
||||
Build = 0;
|
||||
IP_Octet = 0;
|
||||
Unit = 0;
|
||||
Name[0] = 0;
|
||||
NTPHost[0] = 0;
|
||||
Delay = 0;
|
||||
Pin_i2c_sda = -1;
|
||||
Pin_i2c_scl = -1;
|
||||
Pin_status_led = -1;
|
||||
Pin_sd_cs = -1;
|
||||
for (byte i = 0; i < 17; ++i) { PinBootStates[i] = 0; }
|
||||
for (byte i = 0; i < 4; ++i) { Syslog_IP[i] = 0; }
|
||||
UDPPort = 0;
|
||||
SyslogLevel = 0;
|
||||
SerialLogLevel = 0;
|
||||
@@ -719,12 +738,13 @@ struct SettingsStruct
|
||||
Pin_status_led_Inversed = false;
|
||||
deepSleepOnFail = false;
|
||||
UseValueLogger = false;
|
||||
ArduinoOTAEnable = false;
|
||||
DST_Start = 0;
|
||||
DST_End = 0;
|
||||
UseRTOSMultitasking = false;
|
||||
Pin_Reset = -1;
|
||||
SyslogFacility = DEFAULT_SYSLOG_FACILITY;
|
||||
StructSize = 0;
|
||||
StructSize = sizeof(SettingsStruct);
|
||||
MQTTUseUnitNameAsClientId = 0;
|
||||
Latitude = 0.0;
|
||||
Longitude = 0.0;
|
||||
@@ -741,6 +761,7 @@ struct SettingsStruct
|
||||
for (byte task = 0; task < TASKS_MAX; ++task) {
|
||||
clearTask(task);
|
||||
}
|
||||
clearNetworkSettings();
|
||||
}
|
||||
|
||||
void clearTask(byte task) {
|
||||
@@ -862,10 +883,11 @@ struct SettingsStruct
|
||||
// Try to extend settings to make the checksum 4-byte aligned.
|
||||
// uint8_t ProgmemMd5[16]; // crc of the binary that last saved the struct to file.
|
||||
// uint8_t md5[16];
|
||||
};
|
||||
|
||||
} Settings;
|
||||
/*
|
||||
SettingsStruct* SettingsStruct_ptr = new SettingsStruct;
|
||||
SettingsStruct& Settings = *SettingsStruct_ptr;
|
||||
*/
|
||||
|
||||
/*********************************************************************************************\
|
||||
* ControllerSettingsStruct
|
||||
@@ -1401,6 +1423,7 @@ std::map<unsigned long, systemTimerStruct> systemTimers;
|
||||
\*********************************************************************************************/
|
||||
struct pinStatesStruct
|
||||
{
|
||||
pinStatesStruct() : plugin(0), index(0), mode(0), value(0) {}
|
||||
byte plugin;
|
||||
byte index;
|
||||
byte mode;
|
||||
@@ -1447,6 +1470,8 @@ float UserVar[VARS_PER_TASK * TASKS_MAX];
|
||||
\*********************************************************************************************/
|
||||
struct rulesTimerStatus
|
||||
{
|
||||
rulesTimerStatus() : timestamp(0), interval(0), paused(false) {}
|
||||
|
||||
unsigned long timestamp;
|
||||
unsigned int interval; //interval in milliseconds
|
||||
boolean paused;
|
||||
@@ -1454,11 +1479,11 @@ struct rulesTimerStatus
|
||||
|
||||
msecTimerHandlerStruct msecTimerHandler;
|
||||
|
||||
unsigned long timermqtt_interval;
|
||||
unsigned long lastSend;
|
||||
unsigned long lastWeb;
|
||||
unsigned long timermqtt_interval = 250;
|
||||
unsigned long lastSend = 0;
|
||||
unsigned long lastWeb = 0;
|
||||
byte cmd_within_mainloop = 0;
|
||||
unsigned long connectionFailures;
|
||||
unsigned long connectionFailures = 0;
|
||||
unsigned long wdcounter = 0;
|
||||
unsigned long timerAPoff = 0;
|
||||
unsigned long timerAwakeFromDeepSleep = 0;
|
||||
@@ -1608,15 +1633,18 @@ String eventBuffer = "";
|
||||
|
||||
uint32_t lowestRAM = 0;
|
||||
String lowestRAMfunction = "";
|
||||
uint32_t lowestFreeStack = 0;
|
||||
String lowestFreeStackfunction = "";
|
||||
|
||||
|
||||
bool shouldReboot=false;
|
||||
bool firstLoop=true;
|
||||
|
||||
boolean activeRuleSets[RULESETS_MAX];
|
||||
|
||||
boolean UseRTOSMultitasking;
|
||||
boolean UseRTOSMultitasking = false;
|
||||
|
||||
void (*MainLoopCall_ptr)(void);
|
||||
// void (*MainLoopCall_ptr)(void); //FIXME TD-er: No idea what this does.
|
||||
|
||||
/*********************************************************************************************\
|
||||
* TimingStats
|
||||
|
||||
+5
-2
@@ -109,6 +109,8 @@ void setup()
|
||||
WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters
|
||||
WiFi.setAutoReconnect(false);
|
||||
setWifiMode(WIFI_OFF);
|
||||
lowestFreeStack = getFreeStackWatermark();
|
||||
lowestRAM = FreeMem();
|
||||
|
||||
Plugin_id.resize(PLUGIN_MAX);
|
||||
Task_id_to_Plugin_id.resize(TASKS_MAX);
|
||||
@@ -119,8 +121,6 @@ void setup()
|
||||
ledChannelPin[x] = -1;
|
||||
#endif
|
||||
|
||||
lowestRAM = FreeMem();
|
||||
|
||||
Serial.begin(115200);
|
||||
// Serial.print("\n\n\nBOOOTTT\n\n\n");
|
||||
|
||||
@@ -462,8 +462,11 @@ int getLoopCountPerSec() {
|
||||
\*********************************************************************************************/
|
||||
void loop()
|
||||
{
|
||||
/*
|
||||
//FIXME TD-er: No idea what this does.
|
||||
if(MainLoopCall_ptr)
|
||||
MainLoopCall_ptr();
|
||||
*/
|
||||
|
||||
updateLoopStats();
|
||||
|
||||
|
||||
@@ -535,6 +535,15 @@ String InitFile(const char* fname, int datasize)
|
||||
\*********************************************************************************************/
|
||||
String SaveToFile(char* fname, int index, byte* memAddress, int datasize)
|
||||
{
|
||||
#ifndef ESP32
|
||||
if (allocatedOnStack(memAddress)) {
|
||||
String log = F("SaveToFile: ");
|
||||
log += fname;
|
||||
log += F(" ERROR, Data allocated on stack");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
// return log; // FIXME TD-er: Should this be considered a breaking error?
|
||||
}
|
||||
#endif
|
||||
if (index < 0) {
|
||||
String log = F("SaveToFile: ");
|
||||
log += fname;
|
||||
|
||||
+329
-225
@@ -23,6 +23,85 @@ void tcpCleanup()
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// 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
|
||||
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1)
|
||||
// All version before core 2.4.2
|
||||
extern "C" {
|
||||
#include <cont.h>
|
||||
extern cont_t g_cont;
|
||||
}
|
||||
|
||||
uint32_t getCurrentFreeStack() {
|
||||
register uint32_t *sp asm("a1");
|
||||
return 4 * (sp - g_cont.stack);
|
||||
}
|
||||
|
||||
uint32_t getFreeStackWatermark() {
|
||||
return cont_get_free_stack(&g_cont);
|
||||
}
|
||||
|
||||
bool canYield() {
|
||||
return cont_can_yield(&g_cont);
|
||||
}
|
||||
|
||||
bool allocatedOnStack(const void* address) {
|
||||
register uint32_t *sp asm("a1");
|
||||
if (sp < address) return false;
|
||||
return g_cont.stack < address;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
// All version from core 2.4.2
|
||||
// See: https://github.com/esp8266/Arduino/pull/5018
|
||||
// https://github.com/esp8266/Arduino/pull/4553
|
||||
extern "C" {
|
||||
#include <cont.h>
|
||||
extern cont_t* g_pcont;
|
||||
}
|
||||
|
||||
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 // ARDUINO_ESP8266_RELEASE_2_x_x
|
||||
#endif // ESP32
|
||||
|
||||
bool isDeepSleepEnabled()
|
||||
{
|
||||
if (!Settings.deepSleep)
|
||||
@@ -1365,7 +1444,7 @@ String parseTemplate(String &tmpString, byte lineSize)
|
||||
{
|
||||
checkRAM(F("parseTemplate"));
|
||||
String newString = "";
|
||||
String tmpStringMid = "";
|
||||
//String tmpStringMid = "";
|
||||
newString.reserve(lineSize);
|
||||
|
||||
// replace task template variables
|
||||
@@ -1384,7 +1463,7 @@ String parseTemplate(String &tmpString, byte lineSize)
|
||||
int rightBracketIndex = tmpString.indexOf(']');
|
||||
if (rightBracketIndex >= 0)
|
||||
{
|
||||
tmpStringMid = tmpString.substring(0, rightBracketIndex);
|
||||
String tmpStringMid = tmpString.substring(0, rightBracketIndex);
|
||||
tmpString = tmpString.substring(rightBracketIndex + 1);
|
||||
int hashtagIndex = tmpStringMid.indexOf('#');
|
||||
if (hashtagIndex >= 0) {
|
||||
@@ -1421,232 +1500,14 @@ String parseTemplate(String &tmpString, byte lineSize)
|
||||
if (valueName.equalsIgnoreCase(ExtraTaskSettings.TaskDeviceValueNames[z]))
|
||||
{
|
||||
// here we know the task and value, so find the uservar
|
||||
// Try to format and transform the values
|
||||
// y = taskNr
|
||||
// z = var_of_task
|
||||
match = true;
|
||||
bool isvalid;
|
||||
String value = formatUserVar(y, z, isvalid);
|
||||
if (isvalid) {
|
||||
// start changes by giig1967g - 2018-04-20
|
||||
// Syntax: [task#value#transformation#justification]
|
||||
// valueFormat="transformation#justification"
|
||||
if (valueFormat.length() > 0) //do the checks only if a Format is defined to optimize loop
|
||||
{
|
||||
String valueJust = "";
|
||||
|
||||
hashtagIndex = valueFormat.indexOf('#');
|
||||
if (hashtagIndex >= 0)
|
||||
{
|
||||
valueJust = valueFormat.substring(hashtagIndex + 1); //Justification part
|
||||
valueFormat = valueFormat.substring(0, hashtagIndex); //Transformation part
|
||||
}
|
||||
|
||||
// valueFormat="transformation"
|
||||
// valueJust="justification"
|
||||
if (valueFormat.length() > 0) //do the checks only if a Format is defined to optimize loop
|
||||
{
|
||||
const int val = value == "0" ? 0 : 1; //to be used for GPIO status (0 or 1)
|
||||
const float valFloat = value.toFloat();
|
||||
|
||||
String tempValueFormat = valueFormat;
|
||||
int tempValueFormatLength = tempValueFormat.length();
|
||||
const int invertedIndex = tempValueFormat.indexOf('!');
|
||||
const bool inverted = invertedIndex >= 0 ? 1 : 0;
|
||||
if (inverted)
|
||||
tempValueFormat.remove(invertedIndex,1);
|
||||
|
||||
const int rightJustifyIndex = tempValueFormat.indexOf('R');
|
||||
const bool rightJustify = rightJustifyIndex >= 0 ? 1 : 0;
|
||||
if (rightJustify)
|
||||
tempValueFormat.remove(rightJustifyIndex,1);
|
||||
|
||||
tempValueFormatLength = tempValueFormat.length(); //needed because could have been changed after '!' and 'R' removal
|
||||
|
||||
//Check Transformation syntax
|
||||
if (tempValueFormatLength > 0)
|
||||
{
|
||||
switch (tempValueFormat[0])
|
||||
{
|
||||
case 'V': //value = value without transformations
|
||||
break;
|
||||
case 'O':
|
||||
value = val == inverted ? F("OFF") : F(" ON"); //(equivalent to XOR operator)
|
||||
break;
|
||||
case 'C':
|
||||
value = val == inverted ? F("CLOSE") : F(" OPEN");
|
||||
break;
|
||||
case 'M':
|
||||
value = val == inverted ? F("AUTO") : F(" MAN");
|
||||
break;
|
||||
case 'm':
|
||||
value = val == inverted ? F("A") : F("M");
|
||||
break;
|
||||
case 'H':
|
||||
value = val == inverted ? F("COLD") : F(" HOT");
|
||||
break;
|
||||
case 'U':
|
||||
value = val == inverted ? F("DOWN") : F(" UP");
|
||||
break;
|
||||
case 'u':
|
||||
value = val == inverted ? F("D") : F("U");
|
||||
break;
|
||||
case 'Y':
|
||||
value = val == inverted ? F(" NO") : F("YES");
|
||||
break;
|
||||
case 'y':
|
||||
value = val == inverted ? F("N") : F("Y");
|
||||
break;
|
||||
case 'X':
|
||||
value = val == inverted ? F("O") : F("X");
|
||||
break;
|
||||
case 'I':
|
||||
value = val == inverted ? F("OUT") : F(" IN");
|
||||
break;
|
||||
case 'Z' :// return "0" or "1"
|
||||
value = val == inverted ? F("0") : F("1");
|
||||
break;
|
||||
case 'D' ://Dx.y min 'x' digits zero filled & 'y' decimal fixed digits
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
switch (tempValueFormatLength)
|
||||
{
|
||||
case 2: //Dx
|
||||
if (isDigit(tempValueFormat[1]))
|
||||
{
|
||||
x = (int)tempValueFormat[1]-'0';
|
||||
}
|
||||
break;
|
||||
case 3: //D.y
|
||||
if (tempValueFormat[1]=='.' && isDigit(tempValueFormat[2]))
|
||||
{
|
||||
y = (int)tempValueFormat[2]-'0';
|
||||
}
|
||||
break;
|
||||
case 4: //Dx.y
|
||||
if (isDigit(tempValueFormat[1]) && tempValueFormat[2]=='.' && isDigit(tempValueFormat[3]))
|
||||
{
|
||||
x = (int)tempValueFormat[1]-'0';
|
||||
y = (int)tempValueFormat[3]-'0';
|
||||
}
|
||||
break;
|
||||
case 1: //D
|
||||
default: //any other combination x=0; y=0;
|
||||
break;
|
||||
}
|
||||
value = toString(valFloat,y);
|
||||
int indexDot;
|
||||
indexDot = value.indexOf('.') > 0 ? value.indexOf('.') : value.length();
|
||||
for (byte f = 0; f < (x - indexDot); f++)
|
||||
value = "0" + value;
|
||||
break;
|
||||
}
|
||||
case 'F' :// FLOOR (round down)
|
||||
value = (int)floorf(valFloat);
|
||||
break;
|
||||
case 'E' :// CEILING (round up)
|
||||
value = (int)ceilf(valFloat);
|
||||
break;
|
||||
default:
|
||||
value = F("ERR");
|
||||
break;
|
||||
}
|
||||
|
||||
// Check Justification syntax
|
||||
const int valueJustLength = valueJust.length();
|
||||
if (valueJustLength > 0) //do the checks only if a Justification is defined to optimize loop
|
||||
{
|
||||
value.trim(); //remove right justification spaces for backward compatibility
|
||||
switch (valueJust[0])
|
||||
{
|
||||
case 'P' :// Prefix Fill with n spaces: Pn
|
||||
if (valueJustLength > 1)
|
||||
{
|
||||
if (isDigit(valueJust[1])) //Check Pn where n is between 0 and 9
|
||||
{
|
||||
int filler = valueJust[1] - value.length() - '0' ; //char '0' = 48; char '9' = 58
|
||||
for (byte f = 0; f < filler; f++)
|
||||
newString += " ";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'S' :// Suffix Fill with n spaces: Sn
|
||||
if (valueJustLength > 1)
|
||||
{
|
||||
if (isDigit(valueJust[1])) //Check Sn where n is between 0 and 9
|
||||
{
|
||||
int filler = valueJust[1] - value.length() - '0' ; //48
|
||||
for (byte f = 0; f < filler; f++)
|
||||
value += " ";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'L': //left part of the string
|
||||
if (valueJustLength > 1)
|
||||
{
|
||||
if (isDigit(valueJust[1])) //Check n where n is between 0 and 9
|
||||
{
|
||||
value = value.substring(0,(int)valueJust[1]-'0');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'R': //Right part of the string
|
||||
if (valueJustLength > 1)
|
||||
{
|
||||
if (isDigit(valueJust[1])) //Check n where n is between 0 and 9
|
||||
{
|
||||
value = value.substring(std::max(0,(int)value.length()-((int)valueJust[1]-'0')));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'U': //Substring Ux.y where x=firstChar and y=number of characters
|
||||
if (valueJustLength > 1)
|
||||
{
|
||||
if (isDigit(valueJust[1]) && valueJust[2]=='.' && isDigit(valueJust[3]) && valueJust[1] > '0' && valueJust[3] > '0')
|
||||
{
|
||||
value = value.substring(std::min((int)value.length(),(int)valueJust[1]-'0'-1),(int)valueJust[1]-'0'-1+(int)valueJust[3]-'0');
|
||||
}
|
||||
else
|
||||
{
|
||||
newString += F("ERR");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
newString += F("ERR");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rightJustify)
|
||||
{
|
||||
int filler = lineSize - newString.length() - value.length() - tmpString.length() ;
|
||||
for (byte f = 0; f < filler; f++)
|
||||
newString += " ";
|
||||
}
|
||||
{
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
|
||||
String logFormatted = F("DEBUG: Formatted String='");
|
||||
logFormatted += newString;
|
||||
logFormatted += value;
|
||||
logFormatted += "'";
|
||||
addLog(LOG_LEVEL_DEBUG, logFormatted);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//end of changes by giig1967g - 2018-04-18
|
||||
|
||||
newString += String(value);
|
||||
{
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG_DEV)) {
|
||||
String logParsed = F("DEBUG DEV: Parsed String='");
|
||||
logParsed += newString;
|
||||
logParsed += "'";
|
||||
addLog(LOG_LEVEL_DEBUG_DEV, logParsed);
|
||||
}
|
||||
}
|
||||
transformValue(newString, lineSize, value, valueFormat, tmpString);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1685,6 +1546,245 @@ String parseTemplate(String &tmpString, byte lineSize)
|
||||
return newString;
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Transform values
|
||||
\*********************************************************************************************/
|
||||
// Syntax: [task#value#transformation#justification]
|
||||
// valueFormat="transformation#justification"
|
||||
void transformValue(
|
||||
String& newString,
|
||||
byte lineSize,
|
||||
String value,
|
||||
String& valueFormat,
|
||||
const String &tmpString)
|
||||
{
|
||||
checkRAM(F("transformValue"));
|
||||
|
||||
// start changes by giig1967g - 2018-04-20
|
||||
// Syntax: [task#value#transformation#justification]
|
||||
// valueFormat="transformation#justification"
|
||||
if (valueFormat.length() > 0) //do the checks only if a Format is defined to optimize loop
|
||||
{
|
||||
String valueJust = "";
|
||||
|
||||
int hashtagIndex = valueFormat.indexOf('#');
|
||||
if (hashtagIndex >= 0)
|
||||
{
|
||||
valueJust = valueFormat.substring(hashtagIndex + 1); //Justification part
|
||||
valueFormat = valueFormat.substring(0, hashtagIndex); //Transformation part
|
||||
}
|
||||
|
||||
// valueFormat="transformation"
|
||||
// valueJust="justification"
|
||||
if (valueFormat.length() > 0) //do the checks only if a Format is defined to optimize loop
|
||||
{
|
||||
const int val = value == "0" ? 0 : 1; //to be used for GPIO status (0 or 1)
|
||||
const float valFloat = value.toFloat();
|
||||
|
||||
String tempValueFormat = valueFormat;
|
||||
int tempValueFormatLength = tempValueFormat.length();
|
||||
const int invertedIndex = tempValueFormat.indexOf('!');
|
||||
const bool inverted = invertedIndex >= 0 ? 1 : 0;
|
||||
if (inverted)
|
||||
tempValueFormat.remove(invertedIndex,1);
|
||||
|
||||
const int rightJustifyIndex = tempValueFormat.indexOf('R');
|
||||
const bool rightJustify = rightJustifyIndex >= 0 ? 1 : 0;
|
||||
if (rightJustify)
|
||||
tempValueFormat.remove(rightJustifyIndex,1);
|
||||
|
||||
tempValueFormatLength = tempValueFormat.length(); //needed because could have been changed after '!' and 'R' removal
|
||||
|
||||
//Check Transformation syntax
|
||||
if (tempValueFormatLength > 0)
|
||||
{
|
||||
switch (tempValueFormat[0])
|
||||
{
|
||||
case 'V': //value = value without transformations
|
||||
break;
|
||||
case 'O':
|
||||
value = val == inverted ? F("OFF") : F(" ON"); //(equivalent to XOR operator)
|
||||
break;
|
||||
case 'C':
|
||||
value = val == inverted ? F("CLOSE") : F(" OPEN");
|
||||
break;
|
||||
case 'M':
|
||||
value = val == inverted ? F("AUTO") : F(" MAN");
|
||||
break;
|
||||
case 'm':
|
||||
value = val == inverted ? F("A") : F("M");
|
||||
break;
|
||||
case 'H':
|
||||
value = val == inverted ? F("COLD") : F(" HOT");
|
||||
break;
|
||||
case 'U':
|
||||
value = val == inverted ? F("DOWN") : F(" UP");
|
||||
break;
|
||||
case 'u':
|
||||
value = val == inverted ? F("D") : F("U");
|
||||
break;
|
||||
case 'Y':
|
||||
value = val == inverted ? F(" NO") : F("YES");
|
||||
break;
|
||||
case 'y':
|
||||
value = val == inverted ? F("N") : F("Y");
|
||||
break;
|
||||
case 'X':
|
||||
value = val == inverted ? F("O") : F("X");
|
||||
break;
|
||||
case 'I':
|
||||
value = val == inverted ? F("OUT") : F(" IN");
|
||||
break;
|
||||
case 'Z' :// return "0" or "1"
|
||||
value = val == inverted ? F("0") : F("1");
|
||||
break;
|
||||
case 'D' ://Dx.y min 'x' digits zero filled & 'y' decimal fixed digits
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
switch (tempValueFormatLength)
|
||||
{
|
||||
case 2: //Dx
|
||||
if (isDigit(tempValueFormat[1]))
|
||||
{
|
||||
x = (int)tempValueFormat[1]-'0';
|
||||
}
|
||||
break;
|
||||
case 3: //D.y
|
||||
if (tempValueFormat[1]=='.' && isDigit(tempValueFormat[2]))
|
||||
{
|
||||
y = (int)tempValueFormat[2]-'0';
|
||||
}
|
||||
break;
|
||||
case 4: //Dx.y
|
||||
if (isDigit(tempValueFormat[1]) && tempValueFormat[2]=='.' && isDigit(tempValueFormat[3]))
|
||||
{
|
||||
x = (int)tempValueFormat[1]-'0';
|
||||
y = (int)tempValueFormat[3]-'0';
|
||||
}
|
||||
break;
|
||||
case 1: //D
|
||||
default: //any other combination x=0; y=0;
|
||||
break;
|
||||
}
|
||||
value = toString(valFloat,y);
|
||||
int indexDot;
|
||||
indexDot = value.indexOf('.') > 0 ? value.indexOf('.') : value.length();
|
||||
for (byte f = 0; f < (x - indexDot); f++)
|
||||
value = "0" + value;
|
||||
break;
|
||||
}
|
||||
case 'F' :// FLOOR (round down)
|
||||
value = (int)floorf(valFloat);
|
||||
break;
|
||||
case 'E' :// CEILING (round up)
|
||||
value = (int)ceilf(valFloat);
|
||||
break;
|
||||
default:
|
||||
value = F("ERR");
|
||||
break;
|
||||
}
|
||||
|
||||
// Check Justification syntax
|
||||
const int valueJustLength = valueJust.length();
|
||||
if (valueJustLength > 0) //do the checks only if a Justification is defined to optimize loop
|
||||
{
|
||||
value.trim(); //remove right justification spaces for backward compatibility
|
||||
switch (valueJust[0])
|
||||
{
|
||||
case 'P' :// Prefix Fill with n spaces: Pn
|
||||
if (valueJustLength > 1)
|
||||
{
|
||||
if (isDigit(valueJust[1])) //Check Pn where n is between 0 and 9
|
||||
{
|
||||
int filler = valueJust[1] - value.length() - '0' ; //char '0' = 48; char '9' = 58
|
||||
for (byte f = 0; f < filler; f++)
|
||||
newString += " ";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'S' :// Suffix Fill with n spaces: Sn
|
||||
if (valueJustLength > 1)
|
||||
{
|
||||
if (isDigit(valueJust[1])) //Check Sn where n is between 0 and 9
|
||||
{
|
||||
int filler = valueJust[1] - value.length() - '0' ; //48
|
||||
for (byte f = 0; f < filler; f++)
|
||||
value += " ";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'L': //left part of the string
|
||||
if (valueJustLength > 1)
|
||||
{
|
||||
if (isDigit(valueJust[1])) //Check n where n is between 0 and 9
|
||||
{
|
||||
value = value.substring(0,(int)valueJust[1]-'0');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'R': //Right part of the string
|
||||
if (valueJustLength > 1)
|
||||
{
|
||||
if (isDigit(valueJust[1])) //Check n where n is between 0 and 9
|
||||
{
|
||||
value = value.substring(std::max(0,(int)value.length()-((int)valueJust[1]-'0')));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'U': //Substring Ux.y where x=firstChar and y=number of characters
|
||||
if (valueJustLength > 1)
|
||||
{
|
||||
if (isDigit(valueJust[1]) && valueJust[2]=='.' && isDigit(valueJust[3]) && valueJust[1] > '0' && valueJust[3] > '0')
|
||||
{
|
||||
value = value.substring(std::min((int)value.length(),(int)valueJust[1]-'0'-1),(int)valueJust[1]-'0'-1+(int)valueJust[3]-'0');
|
||||
}
|
||||
else
|
||||
{
|
||||
newString += F("ERR");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
newString += F("ERR");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rightJustify)
|
||||
{
|
||||
int filler = lineSize - newString.length() - value.length() - tmpString.length() ;
|
||||
for (byte f = 0; f < filler; f++)
|
||||
newString += " ";
|
||||
}
|
||||
{
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
|
||||
String logFormatted = F("DEBUG: Formatted String='");
|
||||
logFormatted += newString;
|
||||
logFormatted += value;
|
||||
logFormatted += "'";
|
||||
addLog(LOG_LEVEL_DEBUG, logFormatted);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//end of changes by giig1967g - 2018-04-18
|
||||
|
||||
newString += String(value);
|
||||
{
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG_DEV)) {
|
||||
String logParsed = F("DEBUG DEV: Parsed String='");
|
||||
logParsed += newString;
|
||||
logParsed += "'";
|
||||
addLog(LOG_LEVEL_DEBUG_DEV, logParsed);
|
||||
}
|
||||
}
|
||||
checkRAM(F("transformValue2"));
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Calculate function for simple expressions
|
||||
\*********************************************************************************************/
|
||||
@@ -2905,12 +3005,16 @@ void checkRAM( const __FlashStringHelper* flashString)
|
||||
myRamTracker.registerRamState(s);
|
||||
|
||||
uint32_t freeRAM = FreeMem();
|
||||
|
||||
if (freeRAM < lowestRAM)
|
||||
{
|
||||
lowestRAM = freeRAM;
|
||||
lowestRAMfunction = flashString;
|
||||
}
|
||||
uint32_t freeStack = getFreeStackWatermark();
|
||||
if (freeStack < lowestFreeStack) {
|
||||
lowestFreeStack = freeStack;
|
||||
lowestFreeStackfunction = flashString;
|
||||
}
|
||||
}
|
||||
|
||||
void checkRAM( String &a ) {
|
||||
|
||||
@@ -875,6 +875,13 @@ void handle_root() {
|
||||
TXBuffer += F(" - ");
|
||||
TXBuffer += String(lowestRAMfunction);
|
||||
TXBuffer += F(")");
|
||||
html_TR_TD(); TXBuffer += F("Free Stack:<TD>");
|
||||
TXBuffer += String(getCurrentFreeStack());
|
||||
TXBuffer += F(" (");
|
||||
TXBuffer += String(lowestFreeStack);
|
||||
TXBuffer += F(" - ");
|
||||
TXBuffer += String(lowestFreeStackfunction);
|
||||
TXBuffer += F(")");
|
||||
|
||||
html_TR_TD(); TXBuffer += F("IP:<TD>");
|
||||
TXBuffer += formatIP(ip);
|
||||
@@ -5250,6 +5257,13 @@ void handle_sysinfo() {
|
||||
TXBuffer += F(" - ");
|
||||
TXBuffer += lowestRAMfunction;
|
||||
TXBuffer += F(")");
|
||||
html_TR_TD(); TXBuffer += F("Free Stack<TD>");
|
||||
TXBuffer += getCurrentFreeStack();
|
||||
TXBuffer += F(" (");
|
||||
TXBuffer += lowestFreeStack;
|
||||
TXBuffer += F(" - ");
|
||||
TXBuffer += lowestFreeStackfunction;
|
||||
TXBuffer += F(")");
|
||||
|
||||
html_TR_TD(); TXBuffer += F("Boot<TD>");
|
||||
TXBuffer += getLastBootCauseString();
|
||||
|
||||
+142
-116
@@ -9,6 +9,19 @@
|
||||
#define PLUGIN_VALUENAME1_005 "Temperature"
|
||||
#define PLUGIN_VALUENAME2_005 "Humidity"
|
||||
|
||||
#define P005_DHT11 11
|
||||
#define P005_DHT12 12
|
||||
#define P005_DHT22 22
|
||||
#define P005_AM2301 23
|
||||
#define P005_SI7021 70
|
||||
|
||||
#define P005_error_no_reading 1
|
||||
#define P005_error_protocol_timeout 2
|
||||
#define P005_error_checksum_error 3
|
||||
#define P005_error_invalid_NAN_reading 4
|
||||
#define P005_info_temperature 5
|
||||
#define P005_info_humidity 6
|
||||
|
||||
uint8_t Plugin_005_DHT_Pin;
|
||||
|
||||
boolean Plugin_005(byte function, struct EventStruct *event, String& string)
|
||||
@@ -49,7 +62,7 @@ boolean Plugin_005(byte function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
const String options[] = { F("DHT 11"), F("DHT 22"), F("DHT 12"), F("Sonoff am2301"), F("Sonoff si7021") };
|
||||
int indices[] = { 11, 22, 12, 23, 70 };
|
||||
int indices[] = { P005_DHT11, P005_DHT22, P005_DHT12, P005_AM2301, P005_SI7021 };
|
||||
|
||||
addFormSelector(F("DHT Type"), F("plugin_005_dhttype"), 5, options, indices, Settings.TaskDevicePluginConfig[event->TaskIndex][0] );
|
||||
|
||||
@@ -67,92 +80,7 @@ boolean Plugin_005(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
byte dht_dat[5];
|
||||
byte i;
|
||||
boolean error = false;
|
||||
|
||||
byte Par3 = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
Plugin_005_DHT_Pin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
|
||||
pinMode(Plugin_005_DHT_Pin, OUTPUT);
|
||||
digitalWrite(Plugin_005_DHT_Pin, LOW); // Pull low
|
||||
if(Par3 == 11 || Par3 == 22 || Par3 == 12) delay(18);
|
||||
else if (Par3 == 23 ) delayMicroseconds(900);
|
||||
else if (Par3 == 70 ) delayMicroseconds(500);
|
||||
pinMode(Plugin_005_DHT_Pin, INPUT); // change pin to input
|
||||
delayMicroseconds(50);
|
||||
|
||||
error = waitState(0);
|
||||
if(error)
|
||||
{ logError(event, F("DHT : no Reading !"));
|
||||
break;
|
||||
}
|
||||
error = waitState(1);
|
||||
if(error)
|
||||
{ logError(event, F("DHT : no Reading !"));
|
||||
break;
|
||||
}
|
||||
noInterrupts();
|
||||
error = waitState(0);
|
||||
if(error)
|
||||
{ logError(event, F("DHT : no Reading !"));
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
byte data = Plugin_005_read_dht_dat();
|
||||
if(data == -1)
|
||||
{ logError(event, F("DHT : protocol timeout!"));
|
||||
break;
|
||||
}
|
||||
dht_dat[i] = data;
|
||||
}
|
||||
interrupts();
|
||||
|
||||
// Checksum calculation is a Rollover Checksum by design!
|
||||
byte dht_check_sum = (dht_dat[0] + dht_dat[1] + dht_dat[2] + dht_dat[3]) & 0xFF; // check check_sum
|
||||
if (dht_dat[4] != dht_check_sum)
|
||||
{
|
||||
logError(event, F("DHT : checksum error!"));
|
||||
break;
|
||||
}
|
||||
|
||||
float temperature = NAN;
|
||||
float humidity = NAN;
|
||||
if (Par3 == 11)
|
||||
{
|
||||
temperature = float(dht_dat[2]); // Temperature
|
||||
humidity = float(dht_dat[0]); // Humidity
|
||||
}
|
||||
else if (Par3 == 12)
|
||||
{
|
||||
temperature = float(dht_dat[2]*10 + (dht_dat[3] & 0x7f)) / 10.0; // Temperature
|
||||
if (dht_dat[3] & 0x80) { temperature = -temperature; } // Negative temperature
|
||||
humidity = float(dht_dat[0]*10+dht_dat[1]) / 10.0; // Humidity
|
||||
}
|
||||
else if (Par3 == 22 || Par3 == 23 || Par3 == 70)
|
||||
{
|
||||
if (dht_dat[2] & 0x80) // negative temperature
|
||||
temperature = -0.1 * word(dht_dat[2] & 0x7F, dht_dat[3]);
|
||||
else
|
||||
temperature = 0.1 * word(dht_dat[2], dht_dat[3]);
|
||||
humidity = 0.1 * word(dht_dat[0], dht_dat[1]); // Humidity
|
||||
}
|
||||
|
||||
if (temperature == NAN || humidity == NAN)
|
||||
{ logError(event, F("DHT : invalid NAN reading !"));
|
||||
break;
|
||||
}
|
||||
|
||||
UserVar[event->BaseVarIndex] = temperature;
|
||||
UserVar[event->BaseVarIndex + 1] = humidity;
|
||||
String log = F("DHT : Temperature: ");
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
log = F("DHT : Humidity: ");
|
||||
log += UserVar[event->BaseVarIndex + 1];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
success = true;
|
||||
success = P005_do_plugin_read(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -163,28 +91,144 @@ boolean Plugin_005(byte function, struct EventStruct *event, String& string)
|
||||
/*********************************************************************************************\
|
||||
* DHT sub to log an error
|
||||
\*********************************************************************************************/
|
||||
void logError(struct EventStruct *event, String text)
|
||||
void P005_log(struct EventStruct *event, int logNr)
|
||||
{
|
||||
bool isError = true;
|
||||
String text = F("DHT : ");
|
||||
switch (logNr) {
|
||||
case P005_error_no_reading: text += F("No Reading"); break;
|
||||
case P005_error_protocol_timeout: text += F("Protocol Timeout"); break;
|
||||
case P005_error_checksum_error: text += F("Checksum Error"); break;
|
||||
case P005_error_invalid_NAN_reading: text += F("Invalid NAN reading"); break;
|
||||
case P005_info_temperature:
|
||||
text += F("Temperature: ");
|
||||
text += UserVar[event->BaseVarIndex];
|
||||
isError = false;
|
||||
break;
|
||||
case P005_info_humidity:
|
||||
text += F("Humidity: ");
|
||||
text += UserVar[event->BaseVarIndex + 1];
|
||||
isError = false;
|
||||
break;
|
||||
}
|
||||
addLog(LOG_LEVEL_INFO, text);
|
||||
UserVar[event->BaseVarIndex] = NAN;
|
||||
UserVar[event->BaseVarIndex + 1] = NAN;
|
||||
if (isError) {
|
||||
UserVar[event->BaseVarIndex] = NAN;
|
||||
UserVar[event->BaseVarIndex + 1] = NAN;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* DHT sub to wait until a pin is in a certiin state
|
||||
* DHT sub to wait until a pin is in a certain state
|
||||
\*********************************************************************************************/
|
||||
boolean waitState(int state)
|
||||
boolean P005_waitState(int state)
|
||||
{
|
||||
byte counter = 0;
|
||||
while (( digitalRead(Plugin_005_DHT_Pin) != state) && (counter < 100))
|
||||
unsigned long timeout = micros() + 100;
|
||||
while (digitalRead(Plugin_005_DHT_Pin) != state)
|
||||
{
|
||||
if (usecTimeOutReached(timeout)) return false;
|
||||
delayMicroseconds(1);
|
||||
counter++;
|
||||
}
|
||||
if( counter < 100) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Perform the actual reading + interpreting of data.
|
||||
\*********************************************************************************************/
|
||||
bool P005_do_plugin_read(struct EventStruct *event) {
|
||||
byte i;
|
||||
|
||||
byte Par3 = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
Plugin_005_DHT_Pin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
|
||||
pinMode(Plugin_005_DHT_Pin, OUTPUT);
|
||||
digitalWrite(Plugin_005_DHT_Pin, LOW); // Pull low
|
||||
switch (Par3) {
|
||||
case P005_DHT11:
|
||||
case P005_DHT22:
|
||||
case P005_DHT12: delay(18); break; // FIXME TD-er: Must this be so long?
|
||||
case P005_AM2301: delayMicroseconds(900); break;
|
||||
case P005_SI7021: delayMicroseconds(500); break;
|
||||
}
|
||||
switch (Par3) {
|
||||
case P005_DHT11:
|
||||
case P005_DHT22:
|
||||
case P005_DHT12:
|
||||
case P005_AM2301:
|
||||
pinMode(Plugin_005_DHT_Pin, INPUT);
|
||||
delayMicroseconds(50);
|
||||
break;
|
||||
case P005_SI7021:
|
||||
// See: https://github.com/letscontrolit/ESPEasy/issues/1798
|
||||
digitalWrite(Plugin_005_DHT_Pin, HIGH);
|
||||
delayMicroseconds(20);
|
||||
pinMode(Plugin_005_DHT_Pin, INPUT);
|
||||
break;
|
||||
}
|
||||
if(!P005_waitState(0)) {P005_log(event, P005_error_no_reading); return false; }
|
||||
if(!P005_waitState(1)) {P005_log(event, P005_error_no_reading); return false; }
|
||||
noInterrupts();
|
||||
if(!P005_waitState(0)) {P005_log(event, P005_error_no_reading); return false; }
|
||||
bool readingAborted = false;
|
||||
byte dht_dat[5];
|
||||
for (i = 0; i < 5 && !readingAborted; i++)
|
||||
{
|
||||
byte data = Plugin_005_read_dht_dat();
|
||||
if(data == -1)
|
||||
{ P005_log(event, P005_error_protocol_timeout);
|
||||
readingAborted = true;
|
||||
}
|
||||
dht_dat[i] = data;
|
||||
}
|
||||
interrupts();
|
||||
if (readingAborted)
|
||||
return false;
|
||||
|
||||
// Checksum calculation is a Rollover Checksum by design!
|
||||
byte dht_check_sum = (dht_dat[0] + dht_dat[1] + dht_dat[2] + dht_dat[3]) & 0xFF; // check check_sum
|
||||
if (dht_dat[4] != dht_check_sum)
|
||||
{
|
||||
P005_log(event, P005_error_checksum_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
float temperature = NAN;
|
||||
float humidity = NAN;
|
||||
switch (Par3) {
|
||||
case P005_DHT11:
|
||||
temperature = float(dht_dat[2]); // Temperature
|
||||
humidity = float(dht_dat[0]); // Humidity
|
||||
break;
|
||||
case P005_DHT12:
|
||||
temperature = float(dht_dat[2]*10 + (dht_dat[3] & 0x7f)) / 10.0; // Temperature
|
||||
if (dht_dat[3] & 0x80) { temperature = -temperature; } // Negative temperature
|
||||
humidity = float(dht_dat[0]*10+dht_dat[1]) / 10.0; // Humidity
|
||||
break;
|
||||
case P005_DHT22:
|
||||
case P005_AM2301:
|
||||
case P005_SI7021:
|
||||
if (dht_dat[2] & 0x80) // negative temperature
|
||||
temperature = -0.1 * word(dht_dat[2] & 0x7F, dht_dat[3]);
|
||||
else
|
||||
temperature = 0.1 * word(dht_dat[2], dht_dat[3]);
|
||||
humidity = 0.1 * word(dht_dat[0], dht_dat[1]); // Humidity
|
||||
break;
|
||||
}
|
||||
|
||||
if (temperature == NAN || humidity == NAN)
|
||||
{ P005_log(event, P005_error_invalid_NAN_reading);
|
||||
return false;
|
||||
}
|
||||
|
||||
UserVar[event->BaseVarIndex] = temperature;
|
||||
UserVar[event->BaseVarIndex + 1] = humidity;
|
||||
P005_log(event, P005_info_temperature);
|
||||
P005_log(event, P005_info_humidity);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* DHT sub to get an 8 bit value from the receiving bitstream
|
||||
\*********************************************************************************************/
|
||||
@@ -192,31 +236,13 @@ int Plugin_005_read_dht_dat(void)
|
||||
{
|
||||
byte i = 0;
|
||||
byte result = 0;
|
||||
byte counter = 0;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
while ((!digitalRead(Plugin_005_DHT_Pin)) && (counter < 100))
|
||||
{
|
||||
delayMicroseconds(1);
|
||||
counter++;
|
||||
}
|
||||
if (counter >= 100)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (!P005_waitState(1)) return -1;
|
||||
delayMicroseconds(35); // was 30
|
||||
if (digitalRead(Plugin_005_DHT_Pin))
|
||||
result |= (1 << (7 - i));
|
||||
counter = 0;
|
||||
while ((digitalRead(Plugin_005_DHT_Pin)) && (counter < 100))
|
||||
{
|
||||
delayMicroseconds(1);
|
||||
counter++;
|
||||
}
|
||||
if (counter >= 100)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (!P005_waitState(0)) return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+8
-25
@@ -10,29 +10,11 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <map>
|
||||
//#include <shared_ptr>
|
||||
#include <NewPingESP8266.h>
|
||||
|
||||
struct P_013_sensordef {
|
||||
P_013_sensordef() : sonar(NULL) {}
|
||||
|
||||
P_013_sensordef(byte TRIG_Pin, byte IRQ_Pin, int16_t max_cm_distance) : sonar(NULL) {
|
||||
sonar = new NewPingESP8266(TRIG_Pin, IRQ_Pin, max_cm_distance);
|
||||
}
|
||||
|
||||
~P_013_sensordef() {
|
||||
if (sonar != NULL) {
|
||||
delete sonar;
|
||||
sonar = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
NewPingESP8266 *sonar;
|
||||
};
|
||||
|
||||
std::map<unsigned int, P_013_sensordef> P_013_sensordefs;
|
||||
|
||||
|
||||
|
||||
// map of sensors
|
||||
std::map<unsigned int, std::shared_ptr<NewPingESP8266> > P_013_sensordefs;
|
||||
|
||||
boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
@@ -82,6 +64,7 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 2)
|
||||
{
|
||||
addFormNumericBox(F("Threshold"), F("plugin_013_threshold"), Settings.TaskDevicePluginConfig[event->TaskIndex][1]);
|
||||
addUnit(F("cm"));
|
||||
}
|
||||
addFormNumericBox(F("Max Distance"), F("plugin_013_max_distance"), Settings.TaskDevicePluginConfig[event->TaskIndex][2], 0, 500);
|
||||
addUnit(F("cm"));
|
||||
@@ -107,8 +90,9 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
byte Plugin_013_TRIG_Pin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
byte Plugin_013_IRQ_Pin = Settings.TaskDevicePin2[event->TaskIndex];
|
||||
int16_t max_cm_distance = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
|
||||
P_013_sensordefs.erase(event->TaskIndex);
|
||||
P_013_sensordefs[event->TaskIndex] =
|
||||
P_013_sensordef(Plugin_013_TRIG_Pin, Plugin_013_IRQ_Pin, max_cm_distance);
|
||||
std::shared_ptr<NewPingESP8266> (new NewPingESP8266(Plugin_013_TRIG_Pin, Plugin_013_IRQ_Pin, max_cm_distance));
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex +1;
|
||||
log += F(" TrigPin: ");
|
||||
@@ -118,7 +102,7 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
log += F(" max dist cm: ");
|
||||
log += max_cm_distance;
|
||||
log += F(" max echo: ");
|
||||
log += P_013_sensordefs[event->TaskIndex].sonar->getMaxEchoTime();
|
||||
log += P_013_sensordefs[event->TaskIndex]->getMaxEchoTime();
|
||||
log += F(" nr_tasks: ");
|
||||
log += P_013_sensordefs.size();
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
@@ -203,9 +187,8 @@ float Plugin_013_read(unsigned int taskIndex)
|
||||
/*********************************************************************/
|
||||
{
|
||||
if (P_013_sensordefs.count(taskIndex) == 0) return 0;
|
||||
if (P_013_sensordefs[taskIndex].sonar == NULL) return 0;
|
||||
delay(1);
|
||||
float distance = P_013_sensordefs[taskIndex].sonar->ping_cm();
|
||||
float distance = (P_013_sensordefs[taskIndex])->ping_cm();
|
||||
delay(1);
|
||||
return distance;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user