mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 12:17:05 +00:00
Compare commits
57
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33281c08c2 | ||
|
|
461aee26ad | ||
|
|
2b0b14b2e8 | ||
|
|
b7404666b1 | ||
|
|
da25aa87dd | ||
|
|
10a1e634e2 | ||
|
|
83f86449b9 | ||
|
|
eee337d3e3 | ||
|
|
c549ecd329 | ||
|
|
d9e682668d | ||
|
|
e38072ac24 | ||
|
|
6aebeba5dc | ||
|
|
da01c8f469 | ||
|
|
b3b68856f0 | ||
|
|
bec5cb5334 | ||
|
|
bda6011390 | ||
|
|
f3fdb93a52 | ||
|
|
200b060b15 | ||
|
|
ff41cb2f94 | ||
|
|
c134eb6d13 | ||
|
|
f9e2a211e1 | ||
|
|
bd3d3f66f4 | ||
|
|
3bad683211 | ||
|
|
68f6e913a2 | ||
|
|
96420faa2f | ||
|
|
8eea77e4ed | ||
|
|
3d1f723787 | ||
|
|
5d459003e4 | ||
|
|
ad208c357c | ||
|
|
b1c777e6fd | ||
|
|
f5ab15c255 | ||
|
|
001ec6dcd2 | ||
|
|
15e5edccd8 | ||
|
|
651353cc99 | ||
|
|
85f97551c5 | ||
|
|
6a158f68f5 | ||
|
|
1933714de5 | ||
|
|
545117ddf7 | ||
|
|
8eb479c411 | ||
|
|
b39f51ca3c | ||
|
|
4511e08d3c | ||
|
|
086e836956 | ||
|
|
3e20f617ea | ||
|
|
8d9aacb6a4 | ||
|
|
0670fa98a6 | ||
|
|
2b3d1517c9 | ||
|
|
0be79759d1 | ||
|
|
d47bede215 | ||
|
|
2988a244b2 | ||
|
|
8d87dc0175 | ||
|
|
21c86e666a | ||
|
|
e6fdd3380a | ||
|
|
e04f71ab47 | ||
|
|
c8ecd8d374 | ||
|
|
6e7286c6fb | ||
|
|
639685ea0d | ||
|
|
867209de6d |
Vendored
+101
@@ -1,3 +1,104 @@
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181007 (since mega-20181006)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Sun Oct 7 04:00:09 CEST 2018
|
||||
|
||||
Max (2):
|
||||
Force slash to be converted in htmlEscape
|
||||
Fix XSS-Vulnerabilites on wifi configuration pages
|
||||
|
||||
Plebs (3):
|
||||
Add three new TOGGLE commands
|
||||
fixed float to int conversion
|
||||
added "mcpgpiotoggle" command
|
||||
|
||||
TD-er (3):
|
||||
[ESP32] Allow Wrover dev kit to be used for PIO debug
|
||||
[Stack] Move Arduino 'cont' stack into user RAM
|
||||
[SPIFFS] Make sure to close open files on SPIFFS
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181006 (since mega-20181004)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Sat Oct 6 04:00:13 CEST 2018
|
||||
|
||||
TD-er (3):
|
||||
[Stack] Increase stack to 5k and reduce stack allocations in rules
|
||||
[WiFi] Add delay to connection attempts in ControllerSettings
|
||||
[Build flags] Remove NO_EXTRA_4K_HEAP
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181004 (since mega-20181003)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Thu Oct 4 04:00:08 CEST 2018
|
||||
|
||||
Bartlomiej Zimon (1):
|
||||
- partial fix for #1723
|
||||
|
||||
JojoS (1):
|
||||
added error checking and logging
|
||||
|
||||
JojoS62 (5):
|
||||
added float calculation for time to distance conversion
|
||||
added more settings: unit, filtertype and size
|
||||
max distance depends on measurement unit
|
||||
code clean up
|
||||
fixed 'unused variable' warning
|
||||
|
||||
TD-er (3):
|
||||
[sendHttp] #1830 Set timeout and early exit on timeout reached
|
||||
[WiFiClient] Set timeout and make it configurable for controllers
|
||||
[Core 2.4.1] Move back to core 2.4.1 from 2.4.2
|
||||
|
||||
Thomas (1):
|
||||
Update _P075_Nextion.ino (#1)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181003 (since mega-20181002)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Wed Oct 3 04:00:18 CEST 2018
|
||||
|
||||
David Conran (2):
|
||||
Acknowledge credit & origin of code used in IRTX
|
||||
Acknowledge credit & origin of code used in _P016IR.ino
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
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)
|
||||
-------------------------------------------------
|
||||
|
||||
@@ -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,
|
||||
|
@@ -6,12 +6,13 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#include "NewPingESP8266.h"
|
||||
|
||||
//#include "ESPEasy-Globals.h"
|
||||
// ---------------------------------------------------------------------------
|
||||
// NewPingESP8266 constructor
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
NewPingESP8266::NewPingESP8266(uint32_t trigger_pin, uint32_t echo_pin, unsigned int max_cm_distance) {
|
||||
_errorState = STATUS_SENSOR_READY;
|
||||
#if DO_BITWISE == true
|
||||
_triggerBit = digitalPinToBitMask(trigger_pin); // Get the port register bitmask for the trigger pin.
|
||||
_echoBit = digitalPinToBitMask(echo_pin); // Get the port register bitmask for the echo pin.
|
||||
@@ -58,7 +59,10 @@ unsigned int NewPingESP8266::ping(unsigned int max_cm_distance) {
|
||||
while (!digitalRead(_echoPin)) // Wait for the ping echo.
|
||||
#endif
|
||||
{
|
||||
if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance.
|
||||
if ((_max_cm_distance > 0) && (micros() > _max_time)) {
|
||||
_errorState = STATUS_MAX_DISTANCE_EXCEEDED;
|
||||
return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance.
|
||||
}
|
||||
}
|
||||
#else
|
||||
#if DO_BITWISE == true
|
||||
@@ -67,10 +71,14 @@ unsigned int NewPingESP8266::ping(unsigned int max_cm_distance) {
|
||||
while (digitalRead(_echoPin)) // Wait for the ping echo.
|
||||
#endif
|
||||
{
|
||||
if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance.
|
||||
if ((_max_cm_distance > 0) && (micros() > _max_time)) {
|
||||
_errorState = STATUS_MAX_DISTANCE_EXCEEDED;
|
||||
return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance.
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_errorState = STATUS_MEASUREMENT_VALID;
|
||||
return (micros() - (_max_time - _maxEchoTime) - PING_OVERHEAD); // Calculate ping time, include overhead.
|
||||
}
|
||||
|
||||
@@ -144,15 +152,39 @@ boolean NewPingESP8266::ping_trigger() {
|
||||
#endif
|
||||
|
||||
#if URM37_ENABLED == true
|
||||
if (!(*_echoInput & _echoBit)) return false; // Previous ping hasn't finished, abort.
|
||||
if (!(*_echoInput & _echoBit)) { // Previous ping hasn't finished, abort.{
|
||||
_errorState = STATUS_ECHO_STATE_ERROR;
|
||||
return false;
|
||||
}
|
||||
_max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!)
|
||||
while (*_echoInput & _echoBit) // Wait for ping to start.
|
||||
if (micros() > _max_time) return false; // Took too long to start, abort.
|
||||
{
|
||||
if (millis() > (start + 50)) {
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_50ms;
|
||||
return false;
|
||||
}
|
||||
if ((_max_cm_distance > 0) && (micros() > _max_time)) { // check max. distance if != 0 cm
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_DISTANCE;
|
||||
return false; // echo too late, max distance exceeded
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (*_echoInput & _echoBit) return false; // Previous ping hasn't finished, abort.
|
||||
if (*_echoInput & _echoBit) { // Previous ping hasn't finished, abort.
|
||||
_errorState = STATUS_ECHO_STATE_ERROR;
|
||||
return false;
|
||||
}
|
||||
_max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!)
|
||||
while (!(*_echoInput & _echoBit)) // Wait for ping to start.
|
||||
if (micros() > _max_time) return false; // Took too long to start, abort.
|
||||
{
|
||||
if (millis() > (start + 50)) {
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_50ms;
|
||||
return false;
|
||||
}
|
||||
if ((_max_cm_distance > 0) && (micros() > _max_time)) { // check max. distance if != 0 cm
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_DISTANCE;
|
||||
return false; // echo too late, max distance exceeded
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#if ONE_PIN_ENABLED == true
|
||||
@@ -170,30 +202,51 @@ boolean NewPingESP8266::ping_trigger() {
|
||||
#endif
|
||||
|
||||
#if URM37_ENABLED == true
|
||||
if (!digitalRead(_echoPin)) return false; // Previous ping hasn't finished, abort.
|
||||
if (!digitalRead(_echoPin)) {
|
||||
_errorState = STATUS_ECHO_STATE_ERROR;
|
||||
return false; // Previous ping hasn't finished, abort.
|
||||
}
|
||||
_max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!)
|
||||
while (digitalRead(_echoPin)) // Wait for ping to start.
|
||||
{
|
||||
if (millis() > (start + 50)) return false;
|
||||
if (micros() > _max_time) return false; // Took too long to start, abort.
|
||||
if (millis() > (start + 50)) {
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_50ms;
|
||||
return false;
|
||||
}
|
||||
if ((_max_cm_distance > 0) && (micros() > _max_time)) { // check max. distance if != 0 cm
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_DISTANCE;
|
||||
return false; // echo too late, max distance exceeded
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (digitalRead(_echoPin)) return false; // Previous ping hasn't finished, abort.
|
||||
if (digitalRead(_echoPin)) {
|
||||
_errorState = STATUS_ECHO_STATE_ERROR;
|
||||
return false; // Previous ping hasn't finished, abort.
|
||||
}
|
||||
_max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!)
|
||||
while (!digitalRead(_echoPin)) // Wait for ping to start.
|
||||
{
|
||||
if (millis() > (start + 50)) return false;
|
||||
if (micros() > _max_time) return false; // Took too long to start, abort.
|
||||
if (millis() > (start + 50)) {
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_50ms;
|
||||
return false;
|
||||
}
|
||||
if ((_max_cm_distance > 0) && (micros() > _max_time)) { // check max. distance if != 0 cm
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_DISTANCE;
|
||||
return false; // echo too late, max distance exceeded
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
_max_time = micros() + _maxEchoTime; // Ping started, set the time-out.
|
||||
_errorState = STATUS_ECHO_TRIGGERED;
|
||||
|
||||
return true; // Ping started successfully.
|
||||
}
|
||||
|
||||
|
||||
void NewPingESP8266::set_max_distance(unsigned int max_cm_distance) {
|
||||
_max_cm_distance = max_cm_distance;
|
||||
#if ROUNDING_ENABLED == false
|
||||
_maxEchoTime = min(max_cm_distance + 1, (unsigned int) MAX_SENSOR_DISTANCE + 1) * US_ROUNDTRIP_CM; // Calculate the maximum distance in uS (no rounding).
|
||||
#else
|
||||
@@ -222,3 +275,12 @@ unsigned int NewPingESP8266::convert_in(unsigned int echoTime) {
|
||||
return NewPingESP8266Convert(echoTime, US_ROUNDTRIP_IN); // Convert uS to inches.
|
||||
#endif
|
||||
}
|
||||
|
||||
float NewPingESP8266::convert_cm_F(unsigned int echoTime) {
|
||||
return ((float)echoTime / US_ROUNDTRIP_CM); // Convert uS to centimeters (no rounding).
|
||||
}
|
||||
|
||||
|
||||
float NewPingESP8266::convert_in_F(unsigned int echoTime) {
|
||||
return ((float)echoTime / US_ROUNDTRIP_IN); // Convert uS to inches (no rounding).
|
||||
}
|
||||
|
||||
@@ -194,15 +194,29 @@
|
||||
|
||||
class NewPingESP8266 {
|
||||
public:
|
||||
enum errorState {
|
||||
STATUS_SENSOR_READY, // no error, no measruement started
|
||||
STATUS_MEASUREMENT_VALID, // no errors
|
||||
STATUS_ECHO_TRIGGERED, // echo triggered, intermediate state
|
||||
STATUS_MAX_DISTANCE_EXCEEDED, // echo too late, maximum distance exceeded
|
||||
STATUS_ECHO_START_TIMEOUT_50ms, // no echo start signal after 50 ms
|
||||
STATUS_ECHO_START_TIMEOUT_DISTANCE, // no echo start signal after max. distance
|
||||
STATUS_ECHO_STATE_ERROR // echopin level not low after triggered
|
||||
};
|
||||
|
||||
NewPingESP8266(uint32_t trigger_pin, uint32_t echo_pin, unsigned int max_cm_distance = MAX_SENSOR_DISTANCE);
|
||||
~NewPingESP8266() { };
|
||||
unsigned int ping(unsigned int max_cm_distance = 0);
|
||||
unsigned long ping_cm(unsigned int max_cm_distance = 0);
|
||||
unsigned long ping_in(unsigned int max_cm_distance = 0);
|
||||
unsigned long ping_median(uint32_t it = 5, unsigned int max_cm_distance = 0);
|
||||
static unsigned int convert_cm(unsigned int echoTime);
|
||||
static unsigned int convert_in(unsigned int echoTime);
|
||||
static float convert_cm_F(unsigned int echoTime);
|
||||
static float convert_in_F(unsigned int echoTime);
|
||||
|
||||
unsigned int getMaxEchoTime() { return _maxEchoTime; }
|
||||
unsigned int getMaxEchoTime() { return _maxEchoTime; };
|
||||
errorState getErrorState() { return _errorState; };
|
||||
private:
|
||||
boolean ping_trigger();
|
||||
void set_max_distance(unsigned int max_cm_distance);
|
||||
@@ -218,6 +232,8 @@ class NewPingESP8266 {
|
||||
#endif
|
||||
unsigned int _maxEchoTime;
|
||||
unsigned long _max_time;
|
||||
errorState _errorState;
|
||||
unsigned int _max_cm_distance;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+53
-24
@@ -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,12 @@ 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. (starting core_2.4.2)
|
||||
; ESP8266_DISABLE_EXTRA4K - Calls disable_extra4k_at_link_time() from setup
|
||||
; to force the linker keep user's stack in user ram.
|
||||
; CONT_STACKSIZE to set the 'cont' (Arduino) stack size. Default = 4096
|
||||
|
||||
[common]
|
||||
board_build.f_cpu = 80000000L
|
||||
@@ -120,18 +128,20 @@ lib_archive = false
|
||||
upload_speed = 460800
|
||||
framework = arduino
|
||||
board = esp12e
|
||||
platform = ${core_2_4_2.platform}
|
||||
platform = ${core_2_4_1.platform}
|
||||
monitor_speed = 115200
|
||||
|
||||
|
||||
[normal]
|
||||
platform = ${common.platform}
|
||||
build_flags = -DCONT_STACKSIZE=5120
|
||||
|
||||
[testing]
|
||||
platform = ${core_2_4_2.platform}
|
||||
platform = ${core_2_4_1.platform}
|
||||
build_flags = -DCONT_STACKSIZE=5120 -DPLUGIN_BUILD_TESTING
|
||||
|
||||
[dev]
|
||||
platform = ${core_2_4_2.platform}
|
||||
platform = ${core_2_4_1.platform}
|
||||
build_flags = -DCONT_STACKSIZE=5120 -DPLUGIN_BUILD_DEV
|
||||
|
||||
[ir]
|
||||
lib_ignore = ESP32_ping, ESP32WebServer
|
||||
@@ -159,7 +169,7 @@ board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
|
||||
board_build.f_cpu = ${esp8266_1M.board_build.f_cpu}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld
|
||||
platform = ${core_2_4_2.platform}
|
||||
platform = ${core_2_4_1.platform}
|
||||
|
||||
[Sonoff_8285]
|
||||
board_upload.maximum_size = ${esp8285_1M.board_upload.maximum_size}
|
||||
@@ -168,7 +178,7 @@ board_build.f_cpu = ${esp8285_1M.board_build.f_cpu}
|
||||
board = ${esp8285_1M.board}
|
||||
build_unflags = ${esp8285_1M.build_unflags}
|
||||
build_flags = ${esp8285_1M.build_flags}
|
||||
platform = ${core_2_4_2.platform}
|
||||
platform = ${core_2_4_1.platform}
|
||||
|
||||
[espWroom2M]
|
||||
board_build.flash_mode = dout
|
||||
@@ -194,6 +204,25 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.4m1m.ld
|
||||
; Will probably not work, not tested and guaranteed to take a few hours time of some ;
|
||||
; still trying to build the version without reading this warning. ;
|
||||
; *********************************************************************
|
||||
[env:esp-wrover-kit_test_1M8_partition]
|
||||
platform = ${core_esp32.platform}
|
||||
board = esp-wrover-kit
|
||||
build_unflags = ${core_esp32.build_unflags}
|
||||
build_flags = ${core_esp32.build_flags} -DPLUGIN_SET_TEST_ESP32
|
||||
lib_deps = ${core_esp32.lib_deps}
|
||||
lib_ignore = ${core_esp32.lib_ignore}
|
||||
lib_ldf_mode = ${common.lib_ldf_mode}
|
||||
lib_archive = ${common.lib_archive}
|
||||
framework = ${common.framework}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_protocol = ftdi
|
||||
debug_tool = ftdi
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
board_build.partitions = esp32_partition_app1810k_spiffs316k.csv
|
||||
board_upload.maximum_size = 1900544
|
||||
debug_extra_cmds = break Misc.ino:3011
|
||||
|
||||
|
||||
[env:esp32dev]
|
||||
platform = ${core_esp32.platform}
|
||||
board = esp32dev
|
||||
@@ -242,7 +271,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 +288,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 +304,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 +320,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 +338,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 +360,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 +377,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 +393,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 +409,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 +425,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 +448,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 +465,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 +481,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 +497,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 +520,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 +537,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
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -131,7 +131,8 @@ String doExecuteCommand(const char * cmd, struct EventStruct *event, const char*
|
||||
COMMAND_CASE("taskclear" , Command_Task_Clear); // Tasks.h
|
||||
COMMAND_CASE("taskclearall" , Command_Task_ClearAll); // Tasks.h
|
||||
COMMAND_CASE("taskrun" , Command_Task_Run); // Tasks.h
|
||||
COMMAND_CASE("taskvalueset" , Command_Task_ValueSet); // Tasks.h
|
||||
COMMAND_CASE("taskvalueset" , Command_Task_ValueSet); // Tasks.h
|
||||
COMMAND_CASE("taskvaluetoggle" , Command_Task_ValueToggle); // Tasks.h
|
||||
COMMAND_CASE("taskvaluesetandrun" , Command_Task_ValueSetAndRun); // Tasks.h
|
||||
COMMAND_CASE("timerpause" , Command_Timer_Pause); // Timers.h
|
||||
COMMAND_CASE("timerresume" , Command_Timer_Resume); // Timers.h
|
||||
|
||||
@@ -30,6 +30,15 @@ String Command_Task_ValueSet(struct EventStruct *event, const char* Line)
|
||||
return return_command_success();
|
||||
}
|
||||
|
||||
String Command_Task_ValueToggle(struct EventStruct *event, const char* Line)
|
||||
{
|
||||
const int result = round(UserVar[(VARS_PER_TASK * (event->Par1 - 1)) + event->Par2 - 1]);
|
||||
if (result == 0 || result == 1) {
|
||||
UserVar[(VARS_PER_TASK * (event->Par1 - 1)) + event->Par2 - 1] = !result;
|
||||
}
|
||||
return return_command_success();
|
||||
}
|
||||
|
||||
String Command_Task_ValueSetAndRun(struct EventStruct *event, const char* Line)
|
||||
{
|
||||
char TmpStr1[INPUT_COMMAND_SIZE];
|
||||
|
||||
@@ -141,6 +141,7 @@ bool MQTTConnect(int controller_idx)
|
||||
updateMQTTclient_connected();
|
||||
}
|
||||
mqtt = WiFiClient(); // workaround see: https://github.com/esp8266/Arduino/issues/4497#issuecomment-373023864
|
||||
mqtt.setTimeout(ControllerSettings.ClientTimeout);
|
||||
if (ControllerSettings.UseDNS) {
|
||||
MQTTclient.setServer(ControllerSettings.getHost().c_str(), ControllerSettings.Port);
|
||||
} else {
|
||||
|
||||
+24
-7
@@ -191,6 +191,8 @@
|
||||
|
||||
#define MAX_FLASHWRITES_PER_DAY 100 // per 24 hour window
|
||||
#define INPUT_COMMAND_SIZE 240 // Affects maximum command length in rules and other commands
|
||||
// FIXME TD-er: INPUT_COMMAND_SIZE is also used in commands where simply a check for valid parameter is needed
|
||||
// and some may need less memory. (which is stack allocated)
|
||||
|
||||
#define NODE_TYPE_ID_ESP_EASY_STD 1
|
||||
#define NODE_TYPE_ID_ESP_EASYM_STD 17
|
||||
@@ -226,6 +228,9 @@
|
||||
// N.B. Retries without a connection to wifi do not count as retry.
|
||||
#define CONTROLLER_DELAY_QUEUE_RETRY_MAX 10
|
||||
#define CONTROLLER_DELAY_QUEUE_RETRY_DFLT 10
|
||||
// Timeout of the client in msec.
|
||||
#define CONTROLLER_CLIENTTIMEOUT_MAX 1000
|
||||
#define CONTROLLER_CLIENTTIMEOUT_DFLT 100
|
||||
|
||||
|
||||
#define PLUGIN_INIT_ALL 1
|
||||
@@ -414,6 +419,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);
|
||||
@@ -880,10 +888,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
|
||||
@@ -891,7 +900,7 @@ SettingsStruct& Settings = *SettingsStruct_ptr;
|
||||
struct ControllerSettingsStruct
|
||||
{
|
||||
ControllerSettingsStruct() : UseDNS(false), Port(0),
|
||||
MinimalTimeBetweenMessages(100), MaxQueueDepth(10), MaxRetry(10), DeleteOldest(false) {
|
||||
MinimalTimeBetweenMessages(100), MaxQueueDepth(10), MaxRetry(10), DeleteOldest(false), ClientTimeout(100) {
|
||||
for (byte i = 0; i < 4; ++i) {
|
||||
IP[i] = 0;
|
||||
}
|
||||
@@ -915,13 +924,16 @@ struct ControllerSettingsStruct
|
||||
unsigned int MaxQueueDepth;
|
||||
unsigned int MaxRetry;
|
||||
boolean DeleteOldest; // Action to perform when buffer full, delete oldest, or ignore newest.
|
||||
unsigned int ClientTimeout;
|
||||
|
||||
void validate() {
|
||||
if (Port > 65535) Port = 0;
|
||||
if (MinimalTimeBetweenMessages < 1) MinimalTimeBetweenMessages = 100;
|
||||
if (MinimalTimeBetweenMessages > 3600000) MinimalTimeBetweenMessages = 100;
|
||||
if (MaxQueueDepth > 25) MaxQueueDepth = 10;
|
||||
if (MaxRetry > 10) MaxRetry = 10;
|
||||
if (MinimalTimeBetweenMessages < 1 || MinimalTimeBetweenMessages > CONTROLLER_DELAY_QUEUE_DELAY_MAX)
|
||||
MinimalTimeBetweenMessages = CONTROLLER_DELAY_QUEUE_DELAY_DFLT;
|
||||
if (MaxQueueDepth > CONTROLLER_DELAY_QUEUE_DEPTH_MAX) MaxQueueDepth = CONTROLLER_DELAY_QUEUE_DEPTH_DFLT;
|
||||
if (MaxRetry > CONTROLLER_DELAY_QUEUE_RETRY_MAX) MaxRetry = CONTROLLER_DELAY_QUEUE_RETRY_MAX;
|
||||
if (ClientTimeout < 10 || ClientTimeout > CONTROLLER_CLIENTTIMEOUT_MAX)
|
||||
ClientTimeout = CONTROLLER_CLIENTTIMEOUT_DFLT;
|
||||
}
|
||||
|
||||
IPAddress getIP() const {
|
||||
@@ -945,6 +957,7 @@ struct ControllerSettingsStruct
|
||||
if (!WiFiConnected(10)) {
|
||||
return false; // Not connected, so no use in wasting time to connect to a host.
|
||||
}
|
||||
delay(1); // Make sure the Watchdog will not trigger a reset.
|
||||
if (quick && ipSet()) return true;
|
||||
if (UseDNS) {
|
||||
if (!updateIPcache()) {
|
||||
@@ -1483,6 +1496,7 @@ unsigned long connectionFailures = 0;
|
||||
unsigned long wdcounter = 0;
|
||||
unsigned long timerAPoff = 0;
|
||||
unsigned long timerAwakeFromDeepSleep = 0;
|
||||
unsigned long last_system_event_run = 0;
|
||||
|
||||
#if FEATURE_ADC_VCC
|
||||
float vcc = -1.0;
|
||||
@@ -1629,6 +1643,9 @@ String eventBuffer = "";
|
||||
|
||||
uint32_t lowestRAM = 0;
|
||||
String lowestRAMfunction = "";
|
||||
uint32_t lowestFreeStack = 0;
|
||||
String lowestFreeStackfunction = "";
|
||||
|
||||
|
||||
bool shouldReboot=false;
|
||||
bool firstLoop=true;
|
||||
|
||||
+5
-2
@@ -106,9 +106,14 @@ int firstEnabledBlynkController() {
|
||||
\*********************************************************************************************/
|
||||
void setup()
|
||||
{
|
||||
#ifdef ESP8266_DISABLE_EXTRA4K
|
||||
disable_extra4k_at_link_time();
|
||||
#endif
|
||||
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 +124,6 @@ void setup()
|
||||
ledChannelPin[x] = -1;
|
||||
#endif
|
||||
|
||||
lowestRAM = FreeMem();
|
||||
|
||||
Serial.begin(115200);
|
||||
// Serial.print("\n\n\nBOOOTTT\n\n\n");
|
||||
|
||||
|
||||
+50
-23
@@ -113,7 +113,7 @@ void fileSystemCheck()
|
||||
{
|
||||
ResetFactory();
|
||||
}
|
||||
f.close();
|
||||
if (f) f.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -518,13 +518,15 @@ String InitFile(const char* fname, int datasize)
|
||||
FLASH_GUARD();
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "w");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
if (f) {
|
||||
SPIFFS_CHECK(f, fname);
|
||||
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname);
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname);
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
f.close();
|
||||
|
||||
//OK
|
||||
return String();
|
||||
@@ -535,6 +537,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;
|
||||
@@ -547,19 +558,27 @@ String SaveToFile(char* fname, int index, byte* memAddress, int datasize)
|
||||
FLASH_GUARD();
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "r+");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
if (f) {
|
||||
SPIFFS_CHECK(f, fname);
|
||||
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
byte *pointerToByteToSave = memAddress;
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(*pointerToByteToSave), fname);
|
||||
pointerToByteToSave++;
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
byte *pointerToByteToSave = memAddress;
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(*pointerToByteToSave), fname);
|
||||
pointerToByteToSave++;
|
||||
}
|
||||
f.close();
|
||||
String log = F("FILE : Saved ");
|
||||
log=log+fname;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
} else {
|
||||
String log = F("SaveToFile: ");
|
||||
log += fname;
|
||||
log += F(" ERROR, Cannot save to file");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return log;
|
||||
}
|
||||
f.close();
|
||||
String log = F("FILE : Saved ");
|
||||
log=log+fname;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
//OK
|
||||
return String();
|
||||
@@ -582,14 +601,22 @@ String ClearInFile(char* fname, int index, int datasize)
|
||||
FLASH_GUARD();
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "r+");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
if (f) {
|
||||
SPIFFS_CHECK(f, fname);
|
||||
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname);
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname);
|
||||
}
|
||||
f.close();
|
||||
} else {
|
||||
String log = F("ClearInFile: ");
|
||||
log += fname;
|
||||
log += F(" ERROR, Cannot save to file");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return log;
|
||||
}
|
||||
f.close();
|
||||
|
||||
//OK
|
||||
return String();
|
||||
|
||||
@@ -678,6 +678,7 @@ void WifiScan()
|
||||
|
||||
String formatScanResult(int i, const String& separator) {
|
||||
String result = WiFi.SSID(i);
|
||||
htmlEscape(result);
|
||||
#ifndef ESP32
|
||||
if (WiFi.isHidden(i)) {
|
||||
result += F("#Hidden#");
|
||||
|
||||
+345
-244
@@ -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)
|
||||
@@ -366,23 +445,19 @@ void delayBackground(unsigned long delay)
|
||||
void parseCommandString(struct EventStruct *event, const String& string)
|
||||
{
|
||||
checkRAM(F("parseCommandString"));
|
||||
char command[INPUT_COMMAND_SIZE];
|
||||
command[0] = 0;
|
||||
char TmpStr1[INPUT_COMMAND_SIZE];
|
||||
TmpStr1[0] = 0;
|
||||
|
||||
string.toCharArray(command, INPUT_COMMAND_SIZE);
|
||||
event->Par1 = 0;
|
||||
event->Par2 = 0;
|
||||
event->Par3 = 0;
|
||||
event->Par4 = 0;
|
||||
event->Par5 = 0;
|
||||
|
||||
if (GetArgv(command, TmpStr1, 2)) event->Par1 = CalculateParam(TmpStr1);
|
||||
if (GetArgv(command, TmpStr1, 3)) event->Par2 = CalculateParam(TmpStr1);
|
||||
if (GetArgv(command, TmpStr1, 4)) event->Par3 = CalculateParam(TmpStr1);
|
||||
if (GetArgv(command, TmpStr1, 5)) event->Par4 = CalculateParam(TmpStr1);
|
||||
if (GetArgv(command, TmpStr1, 6)) event->Par5 = CalculateParam(TmpStr1);
|
||||
if (GetArgv(string.c_str(), TmpStr1, 2)) { event->Par1 = CalculateParam(TmpStr1); }
|
||||
if (GetArgv(string.c_str(), TmpStr1, 3)) { event->Par2 = CalculateParam(TmpStr1); }
|
||||
if (GetArgv(string.c_str(), TmpStr1, 4)) { event->Par3 = CalculateParam(TmpStr1); }
|
||||
if (GetArgv(string.c_str(), TmpStr1, 5)) { event->Par4 = CalculateParam(TmpStr1); }
|
||||
if (GetArgv(string.c_str(), TmpStr1, 6)) { event->Par5 = CalculateParam(TmpStr1); }
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
@@ -493,15 +568,18 @@ boolean GetArgv(const char *string, char *argv, unsigned int argc) {
|
||||
|
||||
boolean GetArgv(const char *string, char *argv, unsigned int argv_size, unsigned int argc)
|
||||
{
|
||||
size_t string_len = strlen(string);
|
||||
unsigned int string_pos = 0, argv_pos = 0, argc_pos = 0;
|
||||
char c, d;
|
||||
boolean parenthesis = false;
|
||||
char matching_parenthesis = '"';
|
||||
|
||||
while (string_pos < strlen(string))
|
||||
while (string_pos < string_len)
|
||||
{
|
||||
c = string[string_pos];
|
||||
d = string[string_pos + 1];
|
||||
d = 0;
|
||||
if ((string_pos + 1) < string_len)
|
||||
d = string[string_pos + 1];
|
||||
|
||||
if (!parenthesis && c == ' ' && d == ' ') {}
|
||||
else if (!parenthesis && c == ' ' && d == ',') {}
|
||||
@@ -1365,7 +1443,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 +1462,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 +1499,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 +1545,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
|
||||
\*********************************************************************************************/
|
||||
@@ -2108,7 +2207,7 @@ void rulesProcessing(String& event)
|
||||
/********************************************************************************************\
|
||||
Rules processing
|
||||
\*********************************************************************************************/
|
||||
String rulesProcessingFile(String fileName, String& event)
|
||||
String rulesProcessingFile(const String& fileName, String& event)
|
||||
{
|
||||
checkRAM(F("rulesProcessingFile"));
|
||||
if (Settings.SerialLogLevel == LOG_LEVEL_DEBUG_DEV){
|
||||
@@ -2171,6 +2270,7 @@ String rulesProcessingFile(String fileName, String& event)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (f) f.close();
|
||||
|
||||
nestingLevel--;
|
||||
checkRAM(F("rulesProcessingFile2"));
|
||||
@@ -2404,19 +2504,16 @@ void processMatchedRule(
|
||||
{
|
||||
String tmpString = event.substring(equalsPos + 1);
|
||||
|
||||
char command[INPUT_COMMAND_SIZE];
|
||||
command[0] = 0;
|
||||
char tmpParam[INPUT_COMMAND_SIZE];
|
||||
tmpParam[0] = 0;
|
||||
tmpString.toCharArray(command, INPUT_COMMAND_SIZE);
|
||||
|
||||
if (GetArgv(command,tmpParam,1)) {
|
||||
if (GetArgv(tmpString.c_str(),tmpParam,1)) {
|
||||
action.replace(F("%eventvalue%"), tmpParam); // for compatibility issues
|
||||
action.replace(F("%eventvalue1%"), tmpParam); // substitute %eventvalue1% in actions with the actual value from the event
|
||||
}
|
||||
if (GetArgv(command,tmpParam,2)) action.replace(F("%eventvalue2%"), tmpParam); // substitute %eventvalue2% in actions with the actual value from the event
|
||||
if (GetArgv(command,tmpParam,3)) action.replace(F("%eventvalue3%"), tmpParam); // substitute %eventvalue3% in actions with the actual value from the event
|
||||
if (GetArgv(command,tmpParam,4)) action.replace(F("%eventvalue4%"), tmpParam); // substitute %eventvalue4% in actions with the actual value from the event
|
||||
if (GetArgv(tmpString.c_str(),tmpParam,2)) action.replace(F("%eventvalue2%"), tmpParam); // substitute %eventvalue2% in actions with the actual value from the event
|
||||
if (GetArgv(tmpString.c_str(),tmpParam,3)) action.replace(F("%eventvalue3%"), tmpParam); // substitute %eventvalue3% in actions with the actual value from the event
|
||||
if (GetArgv(tmpString.c_str(),tmpParam,4)) action.replace(F("%eventvalue4%"), tmpParam); // substitute %eventvalue4% in actions with the actual value from the event
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2905,12 +3002,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 ) {
|
||||
|
||||
+8
-1
@@ -41,19 +41,26 @@ unsigned long getMixedId(unsigned long timerType, unsigned long id) {
|
||||
\*********************************************************************************************/
|
||||
void handle_schedule() {
|
||||
unsigned long timer;
|
||||
const unsigned long mixed_id = msecTimerHandler.getNextId(timer);
|
||||
unsigned long mixed_id = 0;
|
||||
if (timePassedSince(last_system_event_run) < 500) {
|
||||
// Make sure system event queue will be looked at every now and then.
|
||||
mixed_id = msecTimerHandler.getNextId(timer);
|
||||
}
|
||||
if (mixed_id == 0) {
|
||||
// No id ready to run right now.
|
||||
// Events are not that important to run immediately.
|
||||
// Make sure normal scheduled jobs run at higher priority.
|
||||
backgroundtasks();
|
||||
process_system_event_queue();
|
||||
last_system_event_run = millis();
|
||||
return;
|
||||
}
|
||||
const unsigned long timerType = (mixed_id >> TIMER_ID_SHIFT);
|
||||
const unsigned long mask = (1 << TIMER_ID_SHIFT) -1;
|
||||
const unsigned long id = mixed_id & mask;
|
||||
|
||||
yield(); // See: https://github.com/letscontrolit/ESPEasy/issues/1818#issuecomment-425351328
|
||||
|
||||
switch (timerType) {
|
||||
case CONST_INTERVAL_TIMER:
|
||||
process_interval_timer(id, timer);
|
||||
|
||||
@@ -373,8 +373,31 @@ void htmlEscape(String & html)
|
||||
html.replace("'", F("'"));
|
||||
html.replace("<", F("<"));
|
||||
html.replace(">", F(">"));
|
||||
html.replace("/", F("/"));
|
||||
}
|
||||
|
||||
void htmlStrongEscape(String & html)
|
||||
{
|
||||
String escaped;
|
||||
for (unsigned i = 0; i < html.length(); ++i)
|
||||
{
|
||||
if ((html[i] >= 'a' && html[i] <= 'z') || (html[i] >= 'A' && html[i] <= 'Z') || (html[i] >= '0' && html[i] <= '9'))
|
||||
{
|
||||
escaped += html[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
char s [4];
|
||||
sprintf(s, "%03d", static_cast<int>(html[i]));
|
||||
escaped += "&#";
|
||||
escaped += s;
|
||||
escaped += ";";
|
||||
}
|
||||
}
|
||||
html = escaped;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
replace other system variables like %sysname%, %systime%, %ip%
|
||||
\*********************************************************************************************/
|
||||
|
||||
+32
-4
@@ -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);
|
||||
@@ -1176,6 +1183,7 @@ void handle_controllers() {
|
||||
const int maxqueuedepth = getFormItemInt(F("maxqueuedepth"), 10);
|
||||
const int maxretry = getFormItemInt(F("maxretry"), 10);
|
||||
String deleteoldest = WebServer.arg(F("deleteoldest"));
|
||||
const int clienttimeout = getFormItemInt(F("clienttimeout"), CONTROLLER_CLIENTTIMEOUT_DFLT);
|
||||
|
||||
|
||||
//submitted data
|
||||
@@ -1194,7 +1202,8 @@ void handle_controllers() {
|
||||
//reset (some) default-settings
|
||||
byte ProtocolIndex = getProtocolIndex(Settings.Protocol[controllerindex]);
|
||||
ControllerSettings.Port = Protocol[ProtocolIndex].defaultPort;
|
||||
ControllerSettings.MinimalTimeBetweenMessages = 100;
|
||||
ControllerSettings.MinimalTimeBetweenMessages = CONTROLLER_DELAY_QUEUE_DELAY_DFLT;
|
||||
ControllerSettings.ClientTimeout = CONTROLLER_CLIENTTIMEOUT_DFLT;
|
||||
// ControllerSettings.MaxQueueDepth = 0;
|
||||
if (Protocol[ProtocolIndex].usesTemplate)
|
||||
CPlugin_ptr[ProtocolIndex](CPLUGIN_PROTOCOL_TEMPLATE, &TempEvent, dummyString);
|
||||
@@ -1259,6 +1268,7 @@ void handle_controllers() {
|
||||
ControllerSettings.MaxQueueDepth = maxqueuedepth;
|
||||
ControllerSettings.MaxRetry = maxretry;
|
||||
ControllerSettings.DeleteOldest = deleteoldest.toInt();
|
||||
ControllerSettings.ClientTimeout = clienttimeout;
|
||||
|
||||
|
||||
CPlugin_ptr[ProtocolIndex](CPLUGIN_INIT, &TempEvent, dummyString);
|
||||
@@ -1366,6 +1376,8 @@ void handle_controllers() {
|
||||
addFormNumericBox( F("Max Queue Depth"), F("maxqueuedepth"), ControllerSettings.MaxQueueDepth, 1, CONTROLLER_DELAY_QUEUE_DEPTH_MAX);
|
||||
addFormNumericBox( F("Max Retries"), F("maxretry"), ControllerSettings.MaxRetry, 1, CONTROLLER_DELAY_QUEUE_RETRY_MAX);
|
||||
addFormSelector(F("Full Queue Action"), F("deleteoldest"), 2, options_delete_oldest, NULL, NULL, choice_delete_oldest, true);
|
||||
addFormNumericBox( F("Client Timeout"), F("clienttimeout"), ControllerSettings.ClientTimeout, 10, CONTROLLER_CLIENTTIMEOUT_MAX);
|
||||
addUnit(F("ms"));
|
||||
|
||||
|
||||
if (Protocol[ProtocolIndex].usesAccount)
|
||||
@@ -3653,6 +3665,7 @@ void handle_control() {
|
||||
}
|
||||
else if (command.equalsIgnoreCase(F("taskrun")) ||
|
||||
command.equalsIgnoreCase(F("taskvalueset")) ||
|
||||
command.equalsIgnoreCase(F("taskvaluetoggle")) ||
|
||||
command.equalsIgnoreCase(F("rules"))) {
|
||||
addLog(LOG_LEVEL_INFO,String(F("HTTP : ")) + webrequest);
|
||||
ExecuteCommand(VALUE_SOURCE_HTTP,webrequest.c_str());
|
||||
@@ -4194,6 +4207,7 @@ void handle_download()
|
||||
|
||||
WebServer.sendHeader(F("Content-Disposition"), str);
|
||||
WebServer.streamFile(dataFile, F("application/octet-stream"));
|
||||
dataFile.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -4617,7 +4631,10 @@ void handle_filelist() {
|
||||
TXBuffer += F("</a>");
|
||||
fs::File f = dir.openFile("r");
|
||||
html_TD();
|
||||
TXBuffer += f.size();
|
||||
if (f) {
|
||||
TXBuffer += f.size();
|
||||
f.close();
|
||||
}
|
||||
if (count >= endIdx)
|
||||
{
|
||||
break;
|
||||
@@ -4975,7 +4992,11 @@ void handle_setup() {
|
||||
{
|
||||
html_TR_TD(); TXBuffer += F("<label class='container2'>");
|
||||
TXBuffer += F("<input type='radio' name='ssid' value='");
|
||||
TXBuffer += WiFi.SSID(i);
|
||||
{
|
||||
String escapeBuffer = WiFi.SSID(i);
|
||||
htmlStrongEscape(escapeBuffer);
|
||||
TXBuffer += escapeBuffer;
|
||||
}
|
||||
TXBuffer += F("'");
|
||||
if (WiFi.SSID(i) == ssid)
|
||||
TXBuffer += F(" checked ");
|
||||
@@ -5114,7 +5135,7 @@ void handle_rules() {
|
||||
log += F(" Create new file: ");
|
||||
log += fileName;
|
||||
fs::File f = SPIFFS.open(fileName, "w");
|
||||
f.close();
|
||||
if (f) f.close();
|
||||
}
|
||||
}
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
@@ -5250,6 +5271,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();
|
||||
|
||||
@@ -382,7 +382,7 @@ bool safeReadStringUntil(Stream &input, String &str, char terminator, unsigned i
|
||||
int c;
|
||||
const unsigned long start = millis();
|
||||
const unsigned long timer = start + timeout;
|
||||
unsigned long backgroundtasks_timer = start + 100;
|
||||
unsigned long backgroundtasks_timer = start + 10;
|
||||
str = "";
|
||||
|
||||
do {
|
||||
@@ -405,7 +405,7 @@ bool safeReadStringUntil(Stream &input, String &str, char terminator, unsigned i
|
||||
}
|
||||
// We must run the backgroundtasks every now and then.
|
||||
if (timeOutReached(backgroundtasks_timer)) {
|
||||
backgroundtasks_timer += 100;
|
||||
backgroundtasks_timer += 10;
|
||||
backgroundtasks();
|
||||
} else {
|
||||
yield();
|
||||
@@ -584,6 +584,7 @@ bool count_connection_results(bool success, const String& prefix, int controller
|
||||
}
|
||||
|
||||
bool try_connect_host(int controller_number, WiFiUDP& client, ControllerSettingsStruct& ControllerSettings) {
|
||||
client.setTimeout(ControllerSettings.ClientTimeout);
|
||||
log_connecting_to(F("UDP : "), controller_number, ControllerSettings);
|
||||
bool success = ControllerSettings.beginPacket(client) != 0;
|
||||
return count_connection_results(
|
||||
@@ -593,6 +594,7 @@ bool try_connect_host(int controller_number, WiFiUDP& client, ControllerSettings
|
||||
|
||||
bool try_connect_host(int controller_number, WiFiClient& client, ControllerSettingsStruct& ControllerSettings) {
|
||||
// Use WiFiClient class to create TCP connections
|
||||
client.setTimeout(ControllerSettings.ClientTimeout);
|
||||
log_connecting_to(F("HTTP : "), controller_number, ControllerSettings);
|
||||
bool success = ControllerSettings.connectToHost(client);
|
||||
return count_connection_results(
|
||||
@@ -613,8 +615,10 @@ bool send_via_http(const String& logIdentifier, WiFiClient& client, const String
|
||||
client.print(postStr);
|
||||
|
||||
unsigned long timer = millis() + 200;
|
||||
while (!client.available() && !timeOutReached(timer))
|
||||
while (!client.available()) {
|
||||
if (timeOutReached(timer)) return false;
|
||||
delay(1);
|
||||
}
|
||||
|
||||
// Read all the lines of the reply from server and print them to Serial
|
||||
while (client_available(client) && !success) {
|
||||
|
||||
@@ -73,6 +73,7 @@ boolean NPlugin_001_send(const NotificationSettingsStruct& notificationsettings,
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
client.setTimeout(CONTROLLER_CLIENTTIMEOUT_DFLT);
|
||||
String aHost = notificationsettings.Server;
|
||||
addLog(LOG_LEVEL_DEBUG, String(F("EMAIL: Connecting to ")) + aHost + notificationsettings.Port);
|
||||
if (client.connect(aHost.c_str(), notificationsettings.Port) != 1) {
|
||||
|
||||
@@ -257,6 +257,22 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
}
|
||||
|
||||
if (command == F("gpiotoggle"))
|
||||
{
|
||||
success = true;
|
||||
byte mode;
|
||||
uint16_t currentState;
|
||||
|
||||
getPinState(PLUGIN_ID_001, event->Par1, &mode, ¤tState);
|
||||
if (mode == PIN_MODE_OUTPUT || mode == PIN_MODE_UNDEFINED) { //toggle only output pins
|
||||
digitalWrite(event->Par1, !currentState);
|
||||
setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_OUTPUT, !currentState);
|
||||
log = String(F("SW : Toggle GPIO ")) + String(event->Par1) + String(F(" Set to ")) + String(!currentState);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_001, event->Par1, log, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (command == F("pwm"))
|
||||
{
|
||||
success = true;
|
||||
|
||||
@@ -90,7 +90,7 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
|
||||
resolutionChoice = Plugin_004_DS_getResolution(savedAddress);
|
||||
else
|
||||
resolutionChoice = 9;
|
||||
String resultsOptions[4] = { "9", "10", "11", "12" };
|
||||
String resultsOptions[4] = { F("9"), F("10"), F("11"), F("12") };
|
||||
int resultsOptionValues[4] = { 9, 10, 11, 12 };
|
||||
addFormSelector(F("Device Resolution"), F("plugin_004_res"), 4, resultsOptions, resultsOptionValues, resolutionChoice);
|
||||
addHtml(F(" Bit"));
|
||||
@@ -105,7 +105,6 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
|
||||
|
||||
// save the address for selected device and store into extra tasksettings
|
||||
Plugin_004_DallasPin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
// byte devCount =
|
||||
if (Plugin_004_DallasPin != -1){
|
||||
Plugin_004_DS_scan(getFormItemInt(F("plugin_004_dev")), addr);
|
||||
for (byte x = 0; x < 8; x++)
|
||||
@@ -124,11 +123,12 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
|
||||
{
|
||||
if (x != 0)
|
||||
string += "-";
|
||||
// string += String(ExtraTaskSettings.TaskDevicePluginConfigLong[x], HEX);
|
||||
string += String(ExtraTaskSettings.TaskDevicePluginConfigLong[x], HEX);
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
Plugin_004_DallasPin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
@@ -169,7 +169,7 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
|
||||
for (byte x = 0; x < 8; x++)
|
||||
{
|
||||
if (x != 0)
|
||||
log += "-";
|
||||
log += '-';
|
||||
log += String(ExtraTaskSettings.TaskDevicePluginConfigLong[x], HEX);
|
||||
}
|
||||
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
@@ -124,6 +124,22 @@ boolean Plugin_009(byte function, struct EventStruct *event, String& string)
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_009, event->Par1, log, 0));
|
||||
}
|
||||
|
||||
if (command == F("mcpgpiotoggle"))
|
||||
{
|
||||
success = true;
|
||||
byte mode;
|
||||
uint16_t currentState;
|
||||
|
||||
getPinState(PLUGIN_ID_009, event->Par1, &mode, ¤tState);
|
||||
if (mode == PIN_MODE_OUTPUT || mode == PIN_MODE_UNDEFINED) {
|
||||
setPinState(PLUGIN_ID_009, event->Par1, PIN_MODE_OUTPUT, !currentState);
|
||||
Plugin_009_Write(event->Par1, !currentState);
|
||||
log = String(F("MCP : Toggle GPIO ")) + String(event->Par1) + String(F(" Set to ")) + String(!currentState);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_009, event->Par1, log, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (command == F("mcppulse"))
|
||||
{
|
||||
success = true;
|
||||
|
||||
+198
-40
@@ -10,9 +10,21 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <map>
|
||||
//#include <shared_ptr>
|
||||
#include <NewPingESP8266.h>
|
||||
|
||||
// PlugIn specific defines
|
||||
// operatingMode
|
||||
#define OPMODE_VALUE (0)
|
||||
#define OPMODE_STATE (1)
|
||||
|
||||
// measuringUnit
|
||||
#define UNIT_CM (0)
|
||||
#define UNIT_INCH (1)
|
||||
|
||||
// filterType
|
||||
#define FILTER_NONE (0)
|
||||
#define FILTER_MEDIAN (1)
|
||||
|
||||
// map of sensors
|
||||
std::map<unsigned int, std::shared_ptr<NewPingESP8266> > P_013_sensordefs;
|
||||
|
||||
@@ -36,6 +48,7 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -54,20 +67,51 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
byte choice = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
String options[2];
|
||||
options[0] = F("Value");
|
||||
options[1] = F("State");
|
||||
int optionValues[2] = { 1, 2 };
|
||||
addFormSelector(F("Mode"), F("plugin_013_mode"), 2, options, optionValues, choice);
|
||||
int16_t operatingMode = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
int16_t threshold = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
int16_t max_distance = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
|
||||
int16_t measuringUnit = Settings.TaskDevicePluginConfig[event->TaskIndex][3];
|
||||
int16_t filterType = Settings.TaskDevicePluginConfig[event->TaskIndex][4];
|
||||
int16_t filterSize = Settings.TaskDevicePluginConfig[event->TaskIndex][5];
|
||||
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 2)
|
||||
{
|
||||
addFormNumericBox(F("Threshold"), F("plugin_013_threshold"), Settings.TaskDevicePluginConfig[event->TaskIndex][1]);
|
||||
addUnit(F("cm"));
|
||||
// default filtersize = 5
|
||||
if (filterSize == 0) {
|
||||
filterSize = 5;
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][5] = filterSize;
|
||||
}
|
||||
addFormNumericBox(F("Max Distance"), F("plugin_013_max_distance"), Settings.TaskDevicePluginConfig[event->TaskIndex][2], 0, 500);
|
||||
addUnit(F("cm"));
|
||||
|
||||
|
||||
String strUnit = (measuringUnit == UNIT_CM) ? F("cm") : F("inch");
|
||||
|
||||
String optionsOpMode[2];
|
||||
int optionValuesOpMode[2] = { 0, 1 };
|
||||
optionsOpMode[0] = F("Value");
|
||||
optionsOpMode[1] = F("State");
|
||||
addFormSelector(F("Mode"), F("plugin_013_mode"), 2, optionsOpMode, optionValuesOpMode, operatingMode);
|
||||
|
||||
if (operatingMode == OPMODE_STATE)
|
||||
{
|
||||
addFormNumericBox(F("Threshold"), F("plugin_013_threshold"), threshold);
|
||||
addUnit(strUnit);
|
||||
}
|
||||
addFormNumericBox(F("Max Distance"), F("plugin_013_max_distance"), max_distance, 0, 500);
|
||||
addUnit(strUnit);
|
||||
|
||||
String optionsUnit[2];
|
||||
int optionValuesUnit[2] = { 0, 1 };
|
||||
optionsUnit[0] = F("Metric");
|
||||
optionsUnit[1] = F("Imperial");
|
||||
addFormSelector(F("Unit"), F("plugin_013_Unit"), 2, optionsUnit, optionValuesUnit, measuringUnit);
|
||||
|
||||
String optionsFilter[2];
|
||||
int optionValuesFilter[2] = { 0, 1 };
|
||||
optionsFilter[0] = F("None");
|
||||
optionsFilter[1] = F("Median");
|
||||
addFormSelector(F("Filter"), F("plugin_013_FilterType"), 2, optionsFilter, optionValuesFilter, filterType);
|
||||
|
||||
// enable filtersize option if filter is used,
|
||||
if (filterType != FILTER_NONE)
|
||||
addFormNumericBox(F("Filter size"), F("plugin_013_FilterSize"), filterSize, 2, 20);
|
||||
|
||||
success = true;
|
||||
break;
|
||||
@@ -75,34 +119,60 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
int16_t operatingMode = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
int16_t filterType = Settings.TaskDevicePluginConfig[event->TaskIndex][4];
|
||||
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = getFormItemInt(F("plugin_013_mode"));
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 2)
|
||||
{
|
||||
if (operatingMode == OPMODE_STATE)
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = getFormItemInt(F("plugin_013_threshold"));
|
||||
}
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = getFormItemInt(F("plugin_013_max_distance"));
|
||||
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][3] = getFormItemInt(F("plugin_013_Unit"));
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][4] = getFormItemInt(F("plugin_013_FilterType"));
|
||||
if (filterType != FILTER_NONE)
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][5] = getFormItemInt(F("plugin_013_FilterSize"));
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
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];
|
||||
int16_t max_distance = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
|
||||
int16_t measuringUnit = Settings.TaskDevicePluginConfig[event->TaskIndex][3];
|
||||
int16_t filterType = Settings.TaskDevicePluginConfig[event->TaskIndex][4];
|
||||
int16_t filterSize = Settings.TaskDevicePluginConfig[event->TaskIndex][5];
|
||||
|
||||
int8_t Plugin_013_TRIG_Pin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
int8_t Plugin_013_IRQ_Pin = Settings.TaskDevicePin2[event->TaskIndex];
|
||||
int16_t max_distance_cm = (measuringUnit == UNIT_CM) ? max_distance : (float)max_distance * 2.54f;
|
||||
|
||||
// create sensor instance and add to std::map
|
||||
P_013_sensordefs.erase(event->TaskIndex);
|
||||
P_013_sensordefs[event->TaskIndex] =
|
||||
std::shared_ptr<NewPingESP8266> (new NewPingESP8266(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_distance_cm));
|
||||
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex +1;
|
||||
log += F(" TrigPin: ");
|
||||
log += Plugin_013_TRIG_Pin;
|
||||
log += F(" IRQ_Pin: ");
|
||||
log += Plugin_013_IRQ_Pin;
|
||||
log += F(" max dist cm: ");
|
||||
log += max_cm_distance;
|
||||
log += F(" max dist ");
|
||||
log += (measuringUnit == UNIT_CM) ? F("[cm]: ") : F("[inch]: ");
|
||||
log += max_distance;
|
||||
log += F(" max echo: ");
|
||||
log += P_013_sensordefs[event->TaskIndex]->getMaxEchoTime();
|
||||
log += F(" Filter: ");
|
||||
if (filterType == FILTER_NONE)
|
||||
log += F("none");
|
||||
else
|
||||
if (filterType == FILTER_MEDIAN) {
|
||||
log += F("Median size: ");
|
||||
log += filterSize;
|
||||
}
|
||||
else
|
||||
log += F("invalid!");
|
||||
log += F(" nr_tasks: ");
|
||||
log += P_013_sensordefs.size();
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
@@ -120,7 +190,6 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
log += F(" usec, ");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
@@ -133,39 +202,48 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_READ: // If we select value mode, read and send the value based on global timer
|
||||
{
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 1)
|
||||
int16_t operatingMode = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
int16_t measuringUnit = Settings.TaskDevicePluginConfig[event->TaskIndex][3];
|
||||
|
||||
if (operatingMode == OPMODE_VALUE)
|
||||
{
|
||||
float value = Plugin_013_read(event->TaskIndex);
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex +1;
|
||||
log += F(" Distance: ");
|
||||
if (value > 0)
|
||||
UserVar[event->BaseVarIndex] = value;
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
log += (measuringUnit == UNIT_CM) ? F(" cm ") : F(" inch ");
|
||||
if (value == NO_ECHO)
|
||||
{
|
||||
UserVar[event->BaseVarIndex] = value;
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
success = true;
|
||||
log += F(" Error: ");
|
||||
log += Plugin_013_getErrorStatusString(event->TaskIndex);
|
||||
}
|
||||
else
|
||||
log += F("No reading!");
|
||||
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_TEN_PER_SECOND: // If we select state mode, do more frequent checks and send only state changes
|
||||
{
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 2)
|
||||
int16_t operatingMode = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
int16_t threshold = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
|
||||
if (operatingMode == OPMODE_STATE)
|
||||
{
|
||||
byte state = 0;
|
||||
float value = Plugin_013_read(event->TaskIndex);
|
||||
if (value > 0)
|
||||
if (value != NO_ECHO)
|
||||
{
|
||||
if (value < Settings.TaskDevicePluginConfig[event->TaskIndex][1])
|
||||
if (value < threshold)
|
||||
state = 1;
|
||||
if (state != switchstate[event->TaskIndex])
|
||||
{
|
||||
String log = F("ULTRASONIC : State ");
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex +1;
|
||||
log += F(" state: ");
|
||||
log += state;
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
switchstate[event->TaskIndex] = state;
|
||||
@@ -174,6 +252,14 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
sendData(event);
|
||||
}
|
||||
}
|
||||
else {
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex +1;
|
||||
log += F(" Error: ");
|
||||
log += Plugin_013_getErrorStatusString(event->TaskIndex);
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
}
|
||||
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
@@ -186,10 +272,82 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
float Plugin_013_read(unsigned int taskIndex)
|
||||
/*********************************************************************/
|
||||
{
|
||||
if (P_013_sensordefs.count(taskIndex) == 0) return 0;
|
||||
delay(1);
|
||||
float distance = (P_013_sensordefs[taskIndex])->ping_cm();
|
||||
delay(1);
|
||||
return distance;
|
||||
if (P_013_sensordefs.count(taskIndex) == 0)
|
||||
return 0;
|
||||
|
||||
int16_t max_distance = Settings.TaskDevicePluginConfig[taskIndex][2];
|
||||
int16_t measuringUnit = Settings.TaskDevicePluginConfig[taskIndex][3];
|
||||
int16_t filterType = Settings.TaskDevicePluginConfig[taskIndex][4];
|
||||
int16_t filterSize = Settings.TaskDevicePluginConfig[taskIndex][5];
|
||||
int16_t max_distance_cm = (measuringUnit == UNIT_CM) ? max_distance : (float)max_distance * 2.54f;
|
||||
|
||||
unsigned int echoTime = 0;
|
||||
|
||||
switch (filterType) {
|
||||
case FILTER_NONE:
|
||||
echoTime = (P_013_sensordefs[taskIndex])->ping();
|
||||
break;
|
||||
case FILTER_MEDIAN:
|
||||
echoTime = (P_013_sensordefs[taskIndex])->ping_median(filterSize, max_distance_cm);
|
||||
break;
|
||||
default:
|
||||
addLog(LOG_LEVEL_INFO, F("invalid Filter Type setting!"));
|
||||
}
|
||||
|
||||
if (measuringUnit == UNIT_CM)
|
||||
return NewPingESP8266::convert_cm_F(echoTime);
|
||||
else
|
||||
return NewPingESP8266::convert_in_F(echoTime);
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
String Plugin_013_getErrorStatusString(unsigned int taskIndex)
|
||||
/*********************************************************************/
|
||||
{
|
||||
if (P_013_sensordefs.count(taskIndex) == 0)
|
||||
return String(F("invalid taskindex"));
|
||||
|
||||
switch ((P_013_sensordefs[taskIndex])->getErrorState()) {
|
||||
case NewPingESP8266::STATUS_SENSOR_READY: {
|
||||
return String(F("Sensor ready"));
|
||||
break;
|
||||
}
|
||||
|
||||
case NewPingESP8266::STATUS_MEASUREMENT_VALID: {
|
||||
return String(F("no error, measurement valid"));
|
||||
break;
|
||||
}
|
||||
|
||||
case NewPingESP8266::STATUS_ECHO_TRIGGERED: {
|
||||
return String(F("Echo triggered, waiting for Echo end"));
|
||||
break;
|
||||
}
|
||||
|
||||
case NewPingESP8266::STATUS_ECHO_STATE_ERROR: {
|
||||
return String(F("Echo pulse error, Echopin not low on trigger"));
|
||||
break;
|
||||
}
|
||||
|
||||
case NewPingESP8266::STATUS_ECHO_START_TIMEOUT_50ms: {
|
||||
return String(F("Echo timeout error, no echo start whithin 50 ms"));
|
||||
break;
|
||||
}
|
||||
|
||||
case NewPingESP8266::STATUS_ECHO_START_TIMEOUT_DISTANCE: {
|
||||
return String(F("Echo timeout error, no echo start whithin time for max. distance"));
|
||||
break;
|
||||
}
|
||||
|
||||
case NewPingESP8266::STATUS_MAX_DISTANCE_EXCEEDED: {
|
||||
return String(F("Echo too late, maximum distance exceeded"));
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
return String(F("unknown error"));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif // USES_P013
|
||||
|
||||
@@ -41,6 +41,9 @@ decode_results results;
|
||||
#define PLUGIN_NAME_016 "Communication - TSOP4838"
|
||||
#define PLUGIN_VALUENAME1_016 "IR"
|
||||
|
||||
// A lot of the following code has been taken directly (with permission) from the IRrecvDumpV2.ino example code
|
||||
// of the IRremoteESP8266 library. (https://github.com/markszabo/IRremoteESP8266)
|
||||
|
||||
// ==================== start of TUNEABLE PARAMETERS ====================
|
||||
// As this program is a special purpose capture/decoder, let us use a larger
|
||||
// than normal buffer so we can handle Air Conditioner remote codes.
|
||||
|
||||
@@ -128,6 +128,22 @@ boolean Plugin_019(byte function, struct EventStruct *event, String& string)
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_019, event->Par1, log, 0));
|
||||
}
|
||||
|
||||
if (command == F("pcfgpiotoggle"))
|
||||
{
|
||||
success = true;
|
||||
byte mode;
|
||||
uint16_t currentState;
|
||||
|
||||
getPinState(PLUGIN_ID_019, event->Par1, &mode, ¤tState);
|
||||
if (mode == PIN_MODE_OUTPUT || mode == PIN_MODE_UNDEFINED) {
|
||||
setPinState(PLUGIN_ID_019, event->Par1, PIN_MODE_OUTPUT, !currentState);
|
||||
Plugin_019_Write(event->Par1, !currentState);
|
||||
log = String(F("PCF : Toggle GPIO ")) + String(event->Par1) + String(F(" Set to ")) + String(!currentState);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_019, event->Par1, log, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (command == F("pcfpulse"))
|
||||
{
|
||||
success = true;
|
||||
|
||||
+3
-1
@@ -274,6 +274,8 @@ boolean Plugin_035(byte function, struct EventStruct *event, String& string)
|
||||
return success;
|
||||
}
|
||||
|
||||
// A lot of the following code has been taken directly (with permission) from the IRMQTTServer.ino example code
|
||||
// of the IRremoteESP8266 library. (https://github.com/markszabo/IRremoteESP8266)
|
||||
|
||||
// Parse an Air Conditioner A/C Hex String/code and send it.
|
||||
// Args:
|
||||
@@ -615,4 +617,4 @@ uint16_t countValuesInStr(const String str, char sep) {
|
||||
// }
|
||||
// return result;
|
||||
//}
|
||||
#endif // USES_P035
|
||||
#endif // USES_P035
|
||||
|
||||
@@ -41,6 +41,7 @@ void Plugin_037_try_connect() {
|
||||
if (MQTTclient_037_connected) return;
|
||||
// workaround see: https://github.com/esp8266/Arduino/issues/4497#issuecomment-373023864
|
||||
espclient_037 = WiFiClient();
|
||||
espclient_037.setTimeout(CONTROLLER_CLIENTTIMEOUT_DFLT);
|
||||
|
||||
if (MQTTclient_037 == NULL) {
|
||||
MQTTclient_037 = new PubSubClient(espclient_037);
|
||||
@@ -69,6 +70,7 @@ void Plugin_037_update_connect_status() {
|
||||
if (!connected) {
|
||||
// workaround see: https://github.com/esp8266/Arduino/issues/4497#issuecomment-373023864
|
||||
espclient_037 = WiFiClient();
|
||||
espclient_037.setTimeout(CONTROLLER_CLIENTTIMEOUT_DFLT);
|
||||
++reconnectCount;
|
||||
addLog(LOG_LEVEL_ERROR, F("IMPT : MQTT 037 Connection lost"));
|
||||
}
|
||||
|
||||
+84
-42
@@ -3,10 +3,15 @@
|
||||
//################################### Plugin 075: Nextion <info@sensorio.cz> ###########################
|
||||
//################################### Created on the work of majklovec ###########################
|
||||
//################################### Revisions by BertB and ThomasB ###########################
|
||||
//################################### Last Revision: Aug-03-2018 (TB) ###########################
|
||||
//################################### Last Revision: Oct-03-2018 (TB) ###########################
|
||||
//#######################################################################################################
|
||||
//
|
||||
// Updated: Aug-03-2018, ThomasB.
|
||||
// Updated: Oct-03-2018, ThomasB.
|
||||
// Added DEBUG_LOG define to reduce info log messages and prevent serial log flooding.
|
||||
// Added SendStatus() to post log message on browser to acknowledge HTTP write.
|
||||
// Added reserve() to minimize string memory allocations.
|
||||
//
|
||||
// Aug-03-2018 change log summary:
|
||||
// This updated Nextion Plugin introduces hardware (UART) serial as an alternative to SoftSerial.
|
||||
// Hardware serial offers more reliable communication with the Nextion display.
|
||||
// Created on the experimental Serial.swap() work of BertB.
|
||||
@@ -19,6 +24,9 @@
|
||||
// Defines start here
|
||||
// *****************************************************************************************************
|
||||
|
||||
//#define DEBUG_LOG // Enable this to include additional info messages in log output.
|
||||
|
||||
|
||||
// Plug-In defines
|
||||
#define PLUGIN_075
|
||||
#define PLUGIN_ID_075 75
|
||||
@@ -241,7 +249,9 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
SoftSerial = NULL;
|
||||
}
|
||||
|
||||
String log = F("NEXTION075 : serial pin config RX:");
|
||||
String log;
|
||||
log.reserve(80); // Prevent re-allocation
|
||||
log = F("NEXTION075 : serial pin config RX:");
|
||||
log += rxPin;
|
||||
log += F(", TX:");
|
||||
log += txPin;
|
||||
@@ -313,6 +323,7 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
RssiIndex = UcTmpString.indexOf(F("RSSIBAR")); // RSSI bargraph Keyword found, wifi value in dBm.
|
||||
if(RssiIndex >= 0) {
|
||||
int barVal;
|
||||
newString.reserve(Lenlines+10); // Prevent re-allocation
|
||||
newString = tmpString.substring(0, RssiIndex);
|
||||
int nbars = WiFi.RSSI();
|
||||
if (nbars < -100 || nbars >= 0)
|
||||
@@ -345,31 +356,38 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
|
||||
sendCommand(newString.c_str(), HwSerial);
|
||||
|
||||
String log = F("NEXTION075 : Cmd Statement Line-");
|
||||
log += String(x+1);
|
||||
log += F(" Sent: ");
|
||||
log += newString;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#ifdef DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(Lenlines+50); // Prevent re-allocation
|
||||
log = F("NEXTION075 : Cmd Statement Line-");
|
||||
log += String(x+1);
|
||||
log += F(" Sent: ");
|
||||
log += newString;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// At Interval timer, send idx & value data only if user enabled "values" interval mode.
|
||||
if(IncludeValues) {
|
||||
/*
|
||||
String log = F("NEXTION075: Interval values data enabled, resending idx=");
|
||||
log += String(UserVar[event->BaseVarIndex]);
|
||||
log += F(", value=");
|
||||
log += String(UserVar[event->BaseVarIndex+1]);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
*/
|
||||
#ifdef DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(120); // Prevent re-allocation
|
||||
log = F("NEXTION075: Interval values data enabled, resending idx=");
|
||||
log += String(UserVar[event->BaseVarIndex]);
|
||||
log += F(", value=");
|
||||
log += String(UserVar[event->BaseVarIndex+1]);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
|
||||
success = true;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
String log = F("NEXTION075: Interval values data disabled, idx & value not resent");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
*/
|
||||
#ifdef DEBUG_LOG
|
||||
String log = F("NEXTION075: Interval values data disabled, idx & value not resent");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
|
||||
success = false;
|
||||
}
|
||||
|
||||
@@ -386,6 +404,8 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
// Enable addLog() code below to help debug plugin write problems.
|
||||
/*
|
||||
String log;
|
||||
log.reserve(140); // Prevent re-allocation
|
||||
String log = F("Nextion arg0: ");
|
||||
log += tmpString;
|
||||
log += F(", TaskDeviceName: ");
|
||||
@@ -401,11 +421,14 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
tmpString = string.substring(argIndex + 1);
|
||||
sendCommand(tmpString.c_str(), HwSerial);
|
||||
|
||||
String log = F("NEXTION075 : WRITE, ");
|
||||
log += F("Command is ");
|
||||
log += (tmpString.c_str());
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
String log;
|
||||
log.reserve(110); // Prevent re-allocation
|
||||
log = F("NEXTION075 : WRITE = ");
|
||||
log += tmpString;
|
||||
#ifdef DEBUG_LOG
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
SendStatus(event->Source, log); // Reply (echo) to sender. This will print message on browser.
|
||||
success = true; // Set true only if plugin found a command to execute.
|
||||
}
|
||||
break;
|
||||
@@ -439,7 +462,6 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
uint16_t i;
|
||||
uint8_t c;
|
||||
uint8_t charCount;
|
||||
String log;
|
||||
String Vidx;
|
||||
String Nvalue;
|
||||
String Svalue;
|
||||
@@ -447,7 +469,7 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
char __buffer[RXBUFFSZ+1]; // Staging buffer.
|
||||
|
||||
if(rxPin < 0) {
|
||||
String log = F("NEXTION075 : Missing RxD Pin Number, aborted serial receive");
|
||||
String log = F("NEXTION075 : Missing RxD Pin, aborted serial receive");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
break;
|
||||
}
|
||||
@@ -455,6 +477,8 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
if(HwSerial == UARTSERIAL) {
|
||||
charCount = Serial.available(); // Prime the Hardware Serial engine.
|
||||
if(charCount >= RXBUFFWARN) { // ESP8266 has 128 byte circular Rx buffer.
|
||||
String log;
|
||||
log.reserve(70); // Prevent re-allocation
|
||||
log = F("NEXTION075 : RxD UART Buffer capacity warning,");
|
||||
log += String(charCount);
|
||||
log += F(" bytes");
|
||||
@@ -465,6 +489,8 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
if(SoftSerial == NULL) break; // SoftSerial missing, exit.
|
||||
charCount = SoftSerial->available(); // Prime the Soft Serial engine.
|
||||
if(charCount >= RXBUFFWARN) {
|
||||
String log;
|
||||
log.reserve(70); // Prevent re-allocation
|
||||
log = F("NEXTION075 : RxD SoftSerial Buffer capacity warning, ");
|
||||
log += String(charCount);
|
||||
log += F(" bytes");
|
||||
@@ -495,13 +521,17 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
UserVar[event->BaseVarIndex + 1] = __buffer[3];
|
||||
sendData(event);
|
||||
|
||||
log = F("NEXTION075 : code: ");
|
||||
log += __buffer[1];
|
||||
log += ",";
|
||||
log += __buffer[2];
|
||||
log += ",";
|
||||
log += __buffer[3];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#ifdef DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(70); // Prevent re-allocation
|
||||
log = F("NEXTION075 : code: ");
|
||||
log += __buffer[1];
|
||||
log += ",";
|
||||
log += __buffer[2];
|
||||
log += ",";
|
||||
log += __buffer[3];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -534,9 +564,14 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
__buffer[i] = 0x00;
|
||||
|
||||
String tmpString = __buffer;
|
||||
log = F("NEXTION075 : code: ");
|
||||
log += tmpString;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(50); // Prevent re-allocation
|
||||
log = F("NEXTION075 : Code = ");
|
||||
log += tmpString;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
|
||||
int argIndex = tmpString.indexOf(F(",i"));
|
||||
int argEnd = tmpString.indexOf(',', argIndex + 1);
|
||||
@@ -568,14 +603,21 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
UserVar[event->BaseVarIndex+1] = Svalue.toFloat();
|
||||
sendData(event);
|
||||
|
||||
log = F("NEXTION075 : Pipe Command Sent: ");
|
||||
log += __buffer;
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
#ifdef DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(80); // Prevent re-allocation
|
||||
log = F("NEXTION075 : Pipe Command Sent: ");
|
||||
log += __buffer;
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
log = F("NEXTION075 : Unknown Pipe Command, skipped");
|
||||
#ifdef DEBUG_LOG
|
||||
String log = F("NEXTION075 : Unknown Pipe Command, skipped");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
}
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
}
|
||||
if(HwSerial == UARTSERIAL) charCount = Serial.available();
|
||||
|
||||
Reference in New Issue
Block a user