Compare commits

...
Author SHA1 Message Date
ESPEasy release bot 71caf09c70 automatically updated release notes for mega-20180722 2018-07-22 04:00:08 +02:00
Gijs NoorlanderandGitHub ee3164a8f6 Merge pull request #1602 from TD-er/feature/LogLevelCheck
Feature/log level check
2018-07-22 02:58:21 +02:00
TD-er 3d5f612ac9 [Scheduler] Call yield() when idle
This makes the ESP do a lot more background tasks, which makes each yield() call shorter on average.
This makes the ESP feel more snappy.
2018-07-22 02:53:49 +02:00
TD-er 79f2eaf808 [Scheduler] Keep statistics on timeDiff computations
Apparently it is called 1.4 million times in 30 seconds and takes 8.5 CPU cycles on average (about 50'000 calls per second)
So maybe this function can benefit from some optimisation?
2018-07-22 02:39:02 +02:00
TD-er 1806a1438a [LogLevel] Added extra checks and make sure loglevel cache is up to date 2018-07-22 02:34:36 +02:00
TD-er 5108967c35 [LogLevel] Add checks for LOG_LEVEL_DEBUG_DEV 2018-07-22 01:31:14 +02:00
TD-er d0f1014bef [LogLevel] Add checks for LOG_LEVEL_DEBUG_MORE
Do not create Strings when not needed.
Highest level of checks added: LOG_LEVEL_DEBUG_MORE
2018-07-22 00:52:58 +02:00
TD-er 2afc143051 [LogLevel] Check loglevel before sending to log
Using template to do the check to prevent creation of Strings when required log level is higher than anyone is reading.
2018-07-21 23:54:51 +02:00
TD-er b2bf70e4ce [LogLevel] Use function to set loglevel and keep track of max log level 2018-07-21 23:32:37 +02:00
TD-er 6a5f090198 [LogLevel] LoadFromFile log to LOG_LEVEL_DEBUG_DEV 2018-07-21 22:56:08 +02:00
Gijs NoorlanderandGitHub 92c0543743 Merge pull request #1601 from TD-er/bugfix/logviewer_JavaScript
[Log Viewer] Fix a 1-off error when parsing logs
2018-07-21 21:29:30 +02:00
TD-er 1859aaad7d [Log Viewer] Fix a 1-off error when parsing logs 2018-07-21 21:27:23 +02:00
Gijs NoorlanderandGitHub 7e67ce536d Merge pull request #1594 from TD-er/bugfix/longpulse
[#1591] Move system timers to main scheduler
2018-07-21 21:19:32 +02:00
TD-er 2bd573963a [#1596] Remove timerSensor and make it set its own interval.
All enabled plugins have their own timer added to the scheduler.
The `PLUGIN_INIT` function call is used to reschedule when it was added, or enabled.
The set interval for the plugin will be used to set the new entry in the scheduler.
2018-07-21 01:28:14 +02:00
TD-er 447e958e74 [#1592] Remove systemCMDTimers
These timers were not used.
2018-07-20 21:52:49 +02:00
ESPEasy release bot 43908b37cd automatically updated release notes for mega-20180720 2018-07-20 04:00:16 +02:00
TD-er 04b631e4c9 [#1591] Move system timers to main scheduler
And fix longpulse command

With other plugins active, like the OLED Framed, the set period of `longpulse_ms` may fluctuate and durations below 100 msec are quite useless.

However, when running just a few sensors, the set pulse width is quite accurate.

Must still check a few other plugins.
2018-07-20 02:17:00 +02:00
Gijs NoorlanderandGitHub 2e8fc777d2 Merge pull request #1568 from TD-er/bugfix/1556_change_parse_params
[ParseString] Make ParseString more efficient and check results when used
2018-07-19 18:43:49 +02:00
ESPEasy release bot e060c83cf8 automatically updated release notes for mega-20180719 2018-07-19 04:00:14 +02:00
Gijs NoorlanderandGitHub 5480af2d5d Merge pull request #1587 from TD-er/feature/sunrise_sunset_offset
[sunrise/sunset] Allow offset from sunrise/sunset
2018-07-19 01:07:39 +02:00
TD-er ff28605d39 [sunrise/sunset] Allow offset from sunrise/sunset
`%sunrise%` and `%sunset%` were already available.
Now it is also possible to get some time before or after those times.
For example `%sunrise+10m%` or `%sunset-1h%`
The offset must be an integer (including + or -) and can have a postfix of "m" or "h".
Default is "s", for seconds.
2018-07-19 01:06:06 +02:00
Gijs NoorlanderandGitHub fe0ca9b9a3 Merge pull request #1584 from denisfrench/enable_clientid_is_name_without_unit
When clientid = %sysname%, only add %unit% if non-zero (#1155)
2018-07-18 21:17:06 +02:00
Gijs NoorlanderandGitHub 54ef70aee9 Merge pull request #1586 from beigenmann/mega
lib_archive already exists & Implicit dependency not found
2018-07-18 21:16:03 +02:00
Gijs NoorlanderandGitHub e24d077061 Merge pull request #1583 from clumsy-stefan/P077_fix
Fix for P077 crashes
2018-07-18 21:15:44 +02:00
Benno Eigenmann 7ebf29d857 lib_archive already exists & Implicit dependency not found 2018-07-18 14:02:01 +02:00
denisfrench 33c6925376 When clientid = %sysname%, only add %unit% if non-zero 2018-07-17 19:35:17 +10:00
stefan 0b383a1f3b Fix for P077 crashes
some code rearrangements and improvements:
- fix a rare buffer overflow
- only update variables when new (correct) values are received
- little speed-up
- correct code indentations...
2018-07-16 13:39:51 +02:00
stefan 70d1b0807c Merge remote-tracking branch 'origin/mega' into mega 2018-07-16 07:22:31 +02:00
ESPEasy release bot 8e1f4d628b automatically updated release notes for mega-20180716 2018-07-16 04:00:09 +02:00
Gijs NoorlanderandGitHub ef29603f05 Merge pull request #1581 from TD-er/feature/ESP32_partitiontable
[ESP32] Show partition table on sysinfo page
2018-07-16 00:59:50 +02:00
Gijs NoorlanderandGitHub 71b27d95fa Merge pull request #1562 from TD-er/bugfix/wifi_reset_empty_IP
[WiFi] Reset wifi when IP is set to 0.0.0.0
2018-07-16 00:58:31 +02:00
Gijs NoorlanderandGitHub 787c1c6c39 Merge pull request #1579 from TD-er/bugfix/scheduler_rewrite
[Scheduler] Complete rewrite of time based scheduling
2018-07-16 00:58:02 +02:00
Gijs NoorlanderandGitHub 74e4848edc Merge pull request #1578 from TD-er/bugfix/JSON_device_info
[JSON] Fixed broken JSON output on /json URL
2018-07-16 00:57:41 +02:00
TD-er 9a7690473a [ESP32] Show partition table on sysinfo page
Graphical display of partition table.
2018-07-16 00:49:30 +02:00
TD-er c401edde6b [ParseString] Fix getting the right part of the command line
Fix several 1-off errors.
Should drink more coffee ;)
2018-07-15 21:34:29 +02:00
TD-er 3fc1ba27e5 [JSON] Fixed broken JSON output on /json URL
This bug also broke the auto update of the sensor values on the device tab.
2018-07-15 20:23:11 +02:00
TD-er b2212d2edb [Scheduler] Complete rewrite of time based scheduling
All scheduled operations are now handled by a time scheduler.
Also the CPU load is now based entirely on the idle time found by this scheduler.
2018-07-15 20:21:37 +02:00
stefan 76f7dc82fc Merge branch 'bugfix/wifi_reset_empty_IP' into mega 2018-07-15 11:07:47 +02:00
ESPEasy release bot 86233b65bc automatically updated release notes for mega-20180714 2018-07-14 04:00:13 +02:00
Gijs NoorlanderandGitHub 984cfe23a0 Merge pull request #1569 from letscontrolit/bugfix/1567_uservarcheck
[#1567] Only check values set before sending
2018-07-13 10:35:25 +02:00
Gijs NoorlanderandGitHub 621087d48f [#1567] Only check values set before sending
Fix suggested by @s0170071 [here](https://github.com/letscontrolit/ESPEasy/issues/1567#issuecomment-404746920)
2018-07-13 09:21:42 +02:00
TD-er 00683a38c5 [ParseString] Make ParseString more efficient and check results before use
`ParseString` and `getParamStartPos` made (lots of) copies of the strings.
Also the result of `getParamStartPos` was not checked, which can result in crashes.
2018-07-13 08:09:42 +02:00
TD-er ad06cbc835 [WiFi] Reset wifi when IP is set to 0.0.0.0
As being described a few times and a screenshot shown here: https://github.com/letscontrolit/ESPEasy/issues/1302#issuecomment-393631572
It looks like a DHCP request may fail resulting in a cleared IP setup. The web server then still replies to requests, but no new connections can be made then.

This patch should detect such a situation and then reset the wifi and make a new connection.
2018-07-12 00:20:55 +02:00
37 changed files with 1748 additions and 1083 deletions
+74
View File
@@ -1,3 +1,77 @@
-------------------------------------------------
Changes in release mega-20180722 (since mega-20180720)
-------------------------------------------------
Release date: Sun Jul 22 04:00:08 CEST 2018
TD-er (12):
[#1591] Move system timers to main scheduler
[#1592] Remove systemCMDTimers
[#1596] Remove timerSensor and make it set its own interval.
[Log Viewer] Fix a 1-off error when parsing logs
[LogLevel] LoadFromFile log to LOG_LEVEL_DEBUG_DEV
[LogLevel] Use function to set loglevel and keep track of max log level
[LogLevel] Check loglevel before sending to log
[LogLevel] Add checks for LOG_LEVEL_DEBUG_MORE
[LogLevel] Add checks for LOG_LEVEL_DEBUG_DEV
[LogLevel] Added extra checks and make sure loglevel cache is up to date
[Scheduler] Keep statistics on timeDiff computations
[Scheduler] Call yield() when idle
-------------------------------------------------
Changes in release mega-20180720 (since mega-20180719)
-------------------------------------------------
Release date: Fri Jul 20 04:00:16 CEST 2018
TD-er (2):
[ParseString] Make ParseString more efficient and check results before use
[ParseString] Fix getting the right part of the command line
-------------------------------------------------
Changes in release mega-20180719 (since mega-20180716)
-------------------------------------------------
Release date: Thu Jul 19 04:00:14 CEST 2018
Benno Eigenmann (1):
lib_archive already exists & Implicit dependency not found
TD-er (1):
[sunrise/sunset] Allow offset from sunrise/sunset
denisfrench (1):
When clientid = %sysname%, only add %unit% if non-zero
stefan (1):
Fix for P077 crashes
-------------------------------------------------
Changes in release mega-20180716 (since mega-20180714)
-------------------------------------------------
Release date: Mon Jul 16 04:00:09 CEST 2018
TD-er (4):
[WiFi] Reset wifi when IP is set to 0.0.0.0
[Scheduler] Complete rewrite of time based scheduling
[JSON] Fixed broken JSON output on /json URL
[ESP32] Show partition table on sysinfo page
-------------------------------------------------
Changes in release mega-20180714 (since mega-20180712)
-------------------------------------------------
Release date: Sat Jul 14 04:00:13 CEST 2018
Gijs Noorlander (1):
[#1567] Only check values set before sending
-------------------------------------------------
Changes in release mega-20180712 (since mega-20180710)
-------------------------------------------------
+17 -18
View File
@@ -70,7 +70,7 @@ platform = espressif32@1.1.1
platform = https://github.com/platformio/platform-espressif32.git#feature/stage
[core_esp32]
platform = ${core_esp32_1_1_1.platform}
platform = ${core_esp32_0_12_0.platform}
build_flags = -D BUILD_GIT='"${sysenv.TRAVIS_TAG}"'
-lstdc++ -lsupc++
lib_ignore = AS_BH1750, ESP8266WiFi, ESP8266Ping, ESP8266WebServer, ESP8266HTTPUpdateServer, ESP8266mDNS, IRremoteESP8266, ESPEasy_ESP8266Ping, SerialSensors
@@ -79,7 +79,7 @@ monitor_speed = 115200
[common]
build_flags = -D BUILD_GIT='"${sysenv.TRAVIS_TAG}"' ; ${compiler_warnings.build_flags}
build_flags = -D BUILD_GIT='"${sysenv.TRAVIS_TAG}"'
-D PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
-D NDEBUG
-D VTABLES_IN_FLASH
@@ -183,7 +183,6 @@ lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
lib_archive = ${common.lib_archive}
framework = ${common.framework}
upload_speed = ${common.upload_speed}
monitor_speed = ${common.monitor_speed}
@@ -416,7 +415,7 @@ build_flags = ${esp8266_1M.build_flags} -D PLUGIN_BUILD_DEV -D FLA
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_build.flash_mode = ${Sonoff.board_build.flash_mode}
;board = ${Sonoff.board}
;build_flags = ${Sonoff.build_flags} -D PLUGIN_SET_SONOFF_BASIC
@@ -430,7 +429,7 @@ lib_archive = ${common.lib_archive}
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_build.flash_mode = ${Sonoff.board_build.flash_mode}
;board = ${Sonoff.board}
;build_flags = ${Sonoff.build_flags} -D PLUGIN_SET_SONOFF_TH10
@@ -444,7 +443,7 @@ lib_archive = ${common.lib_archive}
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_build.flash_mode = ${Sonoff.board_build.flash_mode}
;board = ${Sonoff.board}
;build_flags = ${Sonoff.build_flags} -D PLUGIN_SET_SONOFF_TH16
@@ -498,7 +497,7 @@ build_flags = ${Sonoff.build_flags} -D PLUGIN_SET_SONOFF_POW_R2
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_build.flash_mode = ${Sonoff.board_build.flash_mode}
;board = ${Sonoff.board}
;build_flags = ${Sonoff.build_flags} -D PLUGIN_SET_SONOFF_S20
@@ -512,7 +511,7 @@ lib_archive = ${common.lib_archive}
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_build.flash_mode = ${Sonoff.board_build.flash_mode}
;board = ${Sonoff.board}
;build_flags = ${Sonoff.build_flags} -D PLUGIN_SET_SONOFF_4CH
@@ -526,7 +525,7 @@ lib_archive = ${common.lib_archive}
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_build.flash_mode = ${Sonoff.board_build.flash_mode}
;board = ${Sonoff.board}
;build_flags = ${Sonoff.build_flags} -D PLUGIN_SET_SONOFF_TOUCH
@@ -544,7 +543,7 @@ lib_archive = ${common.lib_archive}
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_upload.maximum_size = ${esp8266_1M.board_upload.maximum_size}
;board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
;board = esp01_1m
@@ -559,7 +558,7 @@ lib_archive = ${common.lib_archive}
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_upload.maximum_size = ${esp8266_1M.board_upload.maximum_size}
;board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
;board = esp01_1m
@@ -574,7 +573,7 @@ lib_archive = ${common.lib_archive}
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_upload.maximum_size = ${esp8266_1M.board_upload.maximum_size}
;board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
;board = esp01_1m
@@ -596,7 +595,7 @@ lib_archive = ${common.lib_archive}
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_upload.maximum_size = ${esp8266_1M.board_upload.maximum_size}
;board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
;board = esp01_1m
@@ -612,7 +611,7 @@ lib_archive = ${common.lib_archive}
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_upload.maximum_size = ${esp8266_1M.board_upload.maximum_size}
;board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
;board = esp01_1m
@@ -630,7 +629,7 @@ lib_archive = ${common.lib_archive}
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_upload.maximum_size = ${esp8266_1M.board_upload.maximum_size}
;board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
;board = esp01_1m
@@ -645,7 +644,7 @@ lib_archive = ${common.lib_archive}
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_upload.maximum_size = ${esp8266_1M.board_upload.maximum_size}
;board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
;board = esp01_1m
@@ -660,7 +659,7 @@ lib_archive = ${common.lib_archive}
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_upload.maximum_size = ${esp8266_1M.board_upload.maximum_size}
;board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
;board = esp01_1m
@@ -675,7 +674,7 @@ lib_archive = ${common.lib_archive}
;lib_deps = ${common.lib_deps}
;lib_ignore = ${common.lib_ignore}
;lib_ldf_mode = ${common.lib_ldf_mode}
lib_archive = ${common.lib_archive}
;lib_archive = ${common.lib_archive}
;board_upload.maximum_size = ${esp8266_1M.board_upload.maximum_size}
;board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
;board = esp01_1m
+68 -65
View File
@@ -25,96 +25,96 @@
\*********************************************************************************************/
bool doExecuteCommand(const char * cmd, struct EventStruct *event, const char* line) {
// Simple macro to match command to function call.
#define COMMAND_CASE(S,C) if (strcmp_P(cmd_lc, PSTR(S)) == 0) return (C(event,line));
String tmpcmd;
tmpcmd = cmd;
tmpcmd.toLowerCase();
String log = F("Command: ");
log += tmpcmd;
addLog(LOG_LEVEL_INFO, log);
char cmd_lc[INPUT_COMMAND_SIZE];
tmpcmd.toCharArray(cmd_lc, tmpcmd.length() + 1);
#define COMMAND_CASE(S,C) if (strcmp_P(cmd_lc, PSTR(S)) == 0) return (C(event,line));
String tmpcmd;
tmpcmd = cmd;
tmpcmd.toLowerCase();
String log = F("Command: ");
log += tmpcmd;
addLog(LOG_LEVEL_INFO, log);
char cmd_lc[INPUT_COMMAND_SIZE];
tmpcmd.toCharArray(cmd_lc, tmpcmd.length() + 1);
switch (cmd_lc[0]) {
case 'a': {
case 'a': {
COMMAND_CASE("accessinfo" , Command_AccessInfo_Ls); // Network Command
break;
}
case 'b': {
break;
}
case 'b': {
COMMAND_CASE("background" , Command_Background); // Diagnostic.h
#ifdef CPLUGIN_012
COMMAND_CASE("blynkget" , Command_Blynk_Get);
#endif
COMMAND_CASE("build" , Command_Settings_Build); // Settings.h
break;
}
case 'c': {
break;
}
case 'c': {
COMMAND_CASE("clearaccessblock" , Command_AccessInfo_Clear); // Network Command
COMMAND_CASE("clearrtcram" , Command_RTC_Clear); // RTC.h
COMMAND_CASE("config" , Command_Task_RemoteConfig); // Tasks.h
break;
}
case 'd': {
break;
}
case 'd': {
COMMAND_CASE("debug" , Command_Debug); // Diagnostic.h
COMMAND_CASE("deepsleep" , Command_System_deepSleep); // System.h
COMMAND_CASE("delay" , Command_Delay); // Timers.h
COMMAND_CASE("dns" , Command_DNS); // Network Command
COMMAND_CASE("dst" , Command_DST); // Time.h
break;
}
case 'e': {
break;
}
case 'e': {
COMMAND_CASE("erase" , Command_WiFi_Erase); // WiFi.h
COMMAND_CASE("event" , Command_Rules_Events); // Rule.h
COMMAND_CASE("executerules" , Command_Rules_Execute); // Rule.h
break;
}
case 'g': {
break;
}
case 'g': {
COMMAND_CASE("gateway" , Command_Gateway); // Network Command
break;
}
case 'i': {
break;
}
case 'i': {
COMMAND_CASE("i2cscanner" , Command_i2c_Scanner); // i2c.h
COMMAND_CASE("ip" , Command_IP); // Network Command
break;
}
case 'l': {
break;
}
case 'l': {
COMMAND_CASE("load" , Command_Settings_Load); // Settings.h
COMMAND_CASE("logentry" , Command_logentry); // Diagnostic.h
COMMAND_CASE("lowmem" , Command_Lowmem); // Diagnostic.h
break;
}
case 'm': {
break;
}
case 'm': {
COMMAND_CASE("malloc" , Command_Malloc); // Diagnostic.h
COMMAND_CASE("meminfo" , Command_MenInfo); // Diagnostic.h
COMMAND_CASE("messagedelay" , Command_MQTT_messageDelay); // MQTT.h
COMMAND_CASE("mqttretainflag" , Command_MQTT_Retain); // MQTT.h
break;
}
case 'n': {
break;
}
case 'n': {
COMMAND_CASE("name" , Command_Settings_Name); // Settings.h
COMMAND_CASE("nosleep" , Command_System_NoSleep); // System.h
COMMAND_CASE("notify" , Command_Notifications_Notify); // Notifications.h
COMMAND_CASE("ntphost" , Command_NTPHost); // Time.h
break;
}
case 'p': {
break;
}
case 'p': {
COMMAND_CASE("password" , Command_Settings_Password); // Settings.h
COMMAND_CASE("publish" , Command_MQTT_Publish); // MQTT.h
break;
}
case 'r': {
break;
}
case 'r': {
COMMAND_CASE("reboot" , Command_System_Reboot); // System.h
COMMAND_CASE("reset" , Command_Settings_Reset); // Settings.h
COMMAND_CASE("resetflashwritecounter" , Command_RTC_resetFlashWriteCounter); // RTC.h
COMMAND_CASE("restart" , Command_System_Restart); // System.h
COMMAND_CASE("rules" , Command_Rules_UseRules); // Rule.h
break;
}
case 's': {
break;
}
case 's': {
COMMAND_CASE("save" , Command_Settings_Save); // Settings.h
#if FEATURE_SD
COMMAND_CASE("sdcard" , Command_SD_LS); // SDCARDS.h
COMMAND_CASE("sdremove" , Command_SD_Remove); // SDCARDS.h
COMMAND_CASE("sdremove" , Command_SD_Remove); // SDCARDS.h
#endif
COMMAND_CASE("sendto" , Command_UPD_SendTo); // UDP.h
COMMAND_CASE("sendtohttp" , Command_HTTP_SendToHTTP); // HTTP.h
@@ -123,9 +123,9 @@ bool doExecuteCommand(const char * cmd, struct EventStruct *event, const char* l
COMMAND_CASE("settings" , Command_Settings_Print); // Settings.h
COMMAND_CASE("subnet" , Command_Subnet); // Network Command
COMMAND_CASE("sysload" , Command_SysLoad); // Diagnostic.h
break;
}
case 't': {
break;
}
case 't': {
COMMAND_CASE("taskclear" , Command_Task_Clear); // Tasks.h
COMMAND_CASE("taskclearall" , Command_Task_ClearAll); // Tasks.h
COMMAND_CASE("taskrun" , Command_Task_Run); // Tasks.h
@@ -135,16 +135,16 @@ bool doExecuteCommand(const char * cmd, struct EventStruct *event, const char* l
COMMAND_CASE("timerresume" , Command_Timer_Resume); // Timers.h
COMMAND_CASE("timerset" , Command_Timer_Set); // Timers.h
COMMAND_CASE("timezone" , Command_TimeZone); // Time.h
break;
}
case 'u': {
break;
}
case 'u': {
COMMAND_CASE("udpport" , Command_UDP_Port); // UDP.h
COMMAND_CASE("udptest" , Command_UDP_Test); // UDP.h
COMMAND_CASE("unit" , Command_Settings_Unit); // Settings.h
COMMAND_CASE("usentp" , Command_useNTP); // Time.h
break;
}
case 'w': {
break;
}
case 'w': {
COMMAND_CASE("wdconfig" , Command_WD_Config); // WD.h
COMMAND_CASE("wdread" , Command_WD_Read); // WD.h
COMMAND_CASE("wifiapmode" , Command_Wifi_APMode); // WiFi.h
@@ -157,12 +157,15 @@ bool doExecuteCommand(const char * cmd, struct EventStruct *event, const char* l
COMMAND_CASE("wifissid" , Command_Wifi_SSID); // WiFi.h
COMMAND_CASE("wifissid2" , Command_Wifi_SSID2); // WiFi.h
COMMAND_CASE("wifistamode" , Command_Wifi_STAMode); // WiFi.h
break;
}
default:
break;
}
addLog(LOG_LEVEL_INFO, F("Command unknown"));
}
default:
break;
}
String errorUnknown = F("Command unknown: \"");
errorUnknown += cmd_lc;
errorUnknown += '\"';
addLog(LOG_LEVEL_INFO, errorUnknown);
return false;
#undef COMMAND_CASE
@@ -175,17 +178,17 @@ void ExecuteCommand(byte source, const char *Line)
boolean success = false;
char TmpStr1[INPUT_COMMAND_SIZE];
TmpStr1[0] = 0;
char cmd[INPUT_COMMAND_SIZE];
char cmd[INPUT_COMMAND_SIZE];
cmd[0] = 0;
struct EventStruct TempEvent;
TempEvent.Source = source;
TempEvent.Source = source;
GetArgv(Line, cmd, 1);
if (GetArgv(Line, TmpStr1, 2)) TempEvent.Par1 = str2int(TmpStr1);
if (GetArgv(Line, TmpStr1, 3)) TempEvent.Par2 = str2int(TmpStr1);
if (GetArgv(Line, TmpStr1, 4)) TempEvent.Par3 = str2int(TmpStr1);
if (GetArgv(Line, TmpStr1, 5)) TempEvent.Par4 = str2int(TmpStr1);
if (GetArgv(Line, TmpStr1, 6)) TempEvent.Par5 = str2int(TmpStr1);
success = doExecuteCommand((char*)&cmd[0], &TempEvent, Line);
yield();
+5 -5
View File
@@ -35,7 +35,7 @@ bool Command_SerialFloat(struct EventStruct *event, const char* Line)
pinMode(1, INPUT);
pinMode(3, INPUT);
delay(60000);
return success;
return success;
}
bool Command_MenInfo(struct EventStruct *event, const char* Line)
@@ -49,7 +49,7 @@ bool Command_MenInfo(struct EventStruct *event, const char* Line)
Serial.println(sizeof(ExtraTaskSettings));
Serial.print(F("DeviceStruct: "));
Serial.println(sizeof(Device));
return success;
return success;
}
bool Command_Background(struct EventStruct *event, const char* Line)
@@ -60,7 +60,7 @@ bool Command_Background(struct EventStruct *event, const char* Line)
while (!timeOutReached(timer))
backgroundtasks();
Serial.println(F("end"));
return success;
return success;
}
@@ -68,7 +68,7 @@ bool Command_Debug(struct EventStruct *event, const char* Line)
{
char TmpStr1[INPUT_COMMAND_SIZE];
if (GetArgv(Line, TmpStr1, 2)) {
Settings.SerialLogLevel = event->Par1;
setLogLevelFor(LOG_TO_SERIAL, event->Par1);
}
else{
Serial.println();
@@ -83,4 +83,4 @@ bool Command_logentry(struct EventStruct *event, const char* Line)
return true;
}
#endif // COMMAND_DIAGNOSTIC_H
#endif // COMMAND_DIAGNOSTIC_H
+5 -1
View File
@@ -8,8 +8,11 @@ bool Command_HTTP_SendToHTTP(struct EventStruct *event, const char* Line)
String strLine = Line;
String host = parseString(strLine, 2);
String port = parseString(strLine, 3);
if (!isInt(port)) return false;
int pathpos = getParamStartPos(strLine, 4);
String path = strLine.substring(pathpos);
String path;
if (pathpos >= 0)
path = strLine.substring(pathpos);
WiFiClient client;
if (client.connect(host.c_str(), port.toInt()))
{
@@ -20,6 +23,7 @@ bool Command_HTTP_SendToHTTP(struct EventStruct *event, const char* Line)
reply += host;
reply += F("\r\n");
reply += F("Connection: close\r\n\r\n");
addLog(LOG_LEVEL_DEBUG, reply);
client.print(reply);
unsigned long timer = millis() + 200;
+5 -2
View File
@@ -39,12 +39,14 @@ bool Command_UDP_SendToUPD(struct EventStruct *event, const char* Line)
{
bool success = false;
if (wifiStatus == ESPEASY_WIFI_SERVICES_INITIALIZED) {
success = true;
String strLine = Line;
String ip = parseString(strLine, 2);
String port = parseString(strLine, 3);
if (!isInt(port)) return success;
int msgpos = getParamStartPos(strLine, 4);
String message = strLine.substring(msgpos);
String message;
if (msgpos >= 0)
message = strLine.substring(msgpos);
IPAddress UDP_IP;
if(UDP_IP.fromString(ip)) {
portUDP.beginPacket(UDP_IP, port.toInt());
@@ -56,6 +58,7 @@ bool Command_UDP_SendToUPD(struct EventStruct *event, const char* Line)
#endif
portUDP.endPacket();
}
success = true;
}
return success;
}
+16 -11
View File
@@ -60,7 +60,8 @@ void sendData(struct EventStruct *event)
}
boolean validUserVar(struct EventStruct *event) {
for (int i = 0; i < VARS_PER_TASK; ++i) {
byte valueCount = getValueCountFromSensorType(event->sensorType);
for (int i = 0; i < valueCount; ++i) {
const float f(UserVar[event->BaseVarIndex + i]);
if (!isValidFloat(f)) return false;
}
@@ -92,14 +93,16 @@ void callback(char* c_topic, byte* b_payload, unsigned int length) {
c_payload[length] = 0;
/*
String log;
log=F("MQTT : Topic: ");
log+=c_topic;
addLog(LOG_LEVEL_DEBUG_MORE, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) {
String log;
log=F("MQTT : Topic: ");
log+=c_topic;
addLog(LOG_LEVEL_DEBUG_MORE, log);
log=F("MQTT : Payload: ");
log+=c_payload;
addLog(LOG_LEVEL_DEBUG_MORE, log);
log=F("MQTT : Payload: ");
log+=c_payload;
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
*/
// sprintf_P(log, PSTR("%s%s"), "MQTT : Topic: ", c_topic);
@@ -141,8 +144,10 @@ bool MQTTConnect(int controller_idx)
String clientid;
if(Settings.MQTTUseUnitNameAsClientId){
clientid = Settings.Name;
clientid += F("_");
clientid += Settings.Unit;
if (Settings.Unit != 0) { // only append non-zero unit number
clientid += F("_");
clientid += Settings.Unit;
}
}
else{
clientid = F("ESPClient_");
@@ -259,7 +264,7 @@ void SendStatus(byte source, String status)
boolean MQTTpublish(int controller_idx, const char* topic, const char* payload, boolean retained)
{
if (MQTTclient.publish(topic, payload, retained)) {
timermqtt = millis() + 10; // Make sure the MQTT is being processed as soon as possible.
setIntervalTimerOverride(TIMER_MQTT, 10); // Make sure the MQTT is being processed as soon as possible.
return true;
}
addLog(LOG_LEVEL_DEBUG, F("MQTT : publish failed"));
+44 -41
View File
@@ -196,6 +196,13 @@
#define NODE_TYPE_ID_ARDUINO_EASY_STD 65
#define NODE_TYPE_ID_NANO_EASY_STD 81
#define TIMER_20MSEC 1
#define TIMER_100MSEC 2
#define TIMER_1SEC 3
#define TIMER_30SEC 4
#define TIMER_MQTT 5
#define TIMER_STATISTICS 6
#define PLUGIN_INIT_ALL 1
#define PLUGIN_INIT 2
#define PLUGIN_READ 3
@@ -290,8 +297,6 @@
#define NPLUGIN_MAX 4
#define UNIT_MAX 32 // Only relevant for UDP unicast message 'sweeps' and the nodelist.
#define RULES_TIMER_MAX 8
#define SYSTEM_TIMER_MAX 8
#define SYSTEM_CMD_TIMER_MAX 2
#define PINSTATE_TABLE_MAX 32
#define RULES_MAX_SIZE 2048
#define RULES_MAX_NESTING_LEVEL 3
@@ -373,6 +378,7 @@
#include "ESPEasyTimeTypes.h"
#include "I2CTypes.h"
#include <I2Cdev.h>
#include <map>
#define FS_NO_GLOBALS
#if defined(ESP8266)
@@ -1035,6 +1041,11 @@ struct LogStruct {
} Logging;
byte highest_active_log_level = 0;
bool log_to_serial_disabled = false;
// Do this in a template to prevent casting to String when not needed.
#define addLog(L,S) if (loglevelActiveFor(L)) { addToLog(L,S); }
struct DeviceStruct
{
DeviceStruct() :
@@ -1109,16 +1120,8 @@ struct systemTimerStruct
int Par3;
int Par4;
int Par5;
} systemTimers[SYSTEM_TIMER_MAX];
#define NOTAVAILABLE_SYSTEM_TIMER_ERROR "There are no system timer available, max parallel timers are " STR(SYSTEM_TIMER_MAX)
struct systemCMDTimerStruct
{
systemCMDTimerStruct() : timer(0) {}
unsigned long timer;
String action;
} systemCMDTimers[SYSTEM_CMD_TIMER_MAX];
};
std::map<unsigned long, systemTimerStruct> systemTimers;
struct pinStatesStruct
{
@@ -1157,19 +1160,15 @@ String printWebString = "";
boolean printToWebJSON = false;
float UserVar[VARS_PER_TASK * TASKS_MAX];
struct rulesTiemerStatus
struct rulesTimerStatus
{
unsigned long timestamp;
unsigned int interval; //interval in millisencond
unsigned int interval; //interval in milliseconds
boolean paused;
} RulesTimer[RULES_TIMER_MAX];
unsigned long timerSensor[TASKS_MAX];
unsigned long timer100ms;
unsigned long timer20ms;
unsigned long timer1s;
unsigned long timerwd;
unsigned long timermqtt;
msecTimerHandlerStruct msecTimerHandler;
unsigned long timermqtt_interval;
unsigned long lastSend;
unsigned long lastWeb;
@@ -1293,6 +1292,7 @@ bool processedScanDone = true;
bool webserver_state = false;
bool webserver_init = false;
unsigned long idle_msec_per_sec = 0;
unsigned long elapsed10ps = 0;
unsigned long elapsed10psU = 0;
unsigned long elapsed50ps = 0;
@@ -1306,9 +1306,6 @@ unsigned long loopCounter_full = 1;
float loop_usec_duration_total = 0.0;
unsigned long countFindPluginId = 0;
unsigned long systemTimerCalls = 1;
float systemTimerDurationTotal = 0.0;
unsigned long dailyResetCounter = 0;
String eventBuffer = "";
@@ -1325,8 +1322,6 @@ boolean UseRTOSMultitasking;
void (*MainLoopCall_ptr)(void);
#include <map>
class TimingStats {
public:
TimingStats() : _timeTotal(0.0), _count(0), _maxVal(0), _minVal(4294967295) {}
@@ -1443,7 +1438,7 @@ bool mustLogFunction(int function) {
case PLUGIN_SERIAL_IN: return true;
case PLUGIN_UDP_IN: return true;
case PLUGIN_CLOCK_IN: return false;
case PLUGIN_TIMER_IN: return false;
case PLUGIN_TIMER_IN: return true;
case PLUGIN_FIFTY_PER_SECOND: return true;
case PLUGIN_SET_CONFIG: return false;
case PLUGIN_GET_DEVICEGPIONAMES: return false;
@@ -1457,16 +1452,21 @@ bool mustLogFunction(int function) {
std::map<int,TimingStats> pluginStats;
std::map<int,TimingStats> miscStats;
unsigned long timediff_calls = 0;
unsigned long timediff_cpu_cycles_total = 0;
#define LOADFILE_STATS 0
#define LOOP_STATS 1
#define PLUGIN_CALL_50PS 2
#define PLUGIN_CALL_10PS 3
#define PLUGIN_CALL_10PSU 4
#define PLUGIN_CALL_1PS 5
#define CHECK_SENSORS 6
#define SEND_DATA_STATS 7
#define LOADFILE_STATS 0
#define LOOP_STATS 1
#define PLUGIN_CALL_50PS 2
#define PLUGIN_CALL_10PS 3
#define PLUGIN_CALL_10PSU 4
#define PLUGIN_CALL_1PS 5
#define SENSOR_SEND_TASK 6
#define SEND_DATA_STATS 7
#define COMPUTE_FORMULA_STATS 8
#define PROC_SYS_TIMER 9
#define SET_NEW_TIMER 10
#define TIME_DIFF_COMPUTE 11
@@ -1482,13 +1482,16 @@ String getMiscStatsName(int stat) {
switch (stat) {
case LOADFILE_STATS: return F("Load File");
case LOOP_STATS: return F("Loop");
case PLUGIN_CALL_50PS : return F("Plugin call 50 p/s ");
case PLUGIN_CALL_10PS : return F("Plugin call 10 p/s ");
case PLUGIN_CALL_10PSU : return F("Plugin call 10 p/s U");
case PLUGIN_CALL_1PS : return F("Plugin call 1 p/s ");
case CHECK_SENSORS: return F("checkSensors() ");
case SEND_DATA_STATS: return F("sendData() ");
case COMPUTE_FORMULA_STATS: return F("Compute formula ");
case PLUGIN_CALL_50PS: return F("Plugin call 50 p/s ");
case PLUGIN_CALL_10PS: return F("Plugin call 10 p/s ");
case PLUGIN_CALL_10PSU: return F("Plugin call 10 p/s U");
case PLUGIN_CALL_1PS: return F("Plugin call 1 p/s ");
case SENSOR_SEND_TASK: return F("SensorSendTask() ");
case SEND_DATA_STATS: return F("sendData() ");
case COMPUTE_FORMULA_STATS: return F("Compute formula ");
case PROC_SYS_TIMER: return F("proc_system_timer() ");
case SET_NEW_TIMER: return F("setNewTimerAt() ");
case TIME_DIFF_COMPUTE: return F("timeDiff() ");
}
return F("Unknown");
}
+58 -222
View File
@@ -233,17 +233,6 @@ void setup()
checkRAM(F("hardwareInit"));
hardwareInit();
//After booting, we want all the tasks to run without delaying more than neccesary.
//Plugins that need an initial startup delay need to overwrite their initial timerSensor value in PLUGIN_INIT
//They should also check if we returned from deep sleep so that they can skip the delay in that case.
for (byte x = 0; x < TASKS_MAX; x++)
if (Settings.TaskDeviceTimer[x] !=0)
timerSensor[x] = millis() + (x * Settings.MessageDelay);
timer100ms = 0; // timer for periodic actions 10 x per/sec
timer1s = 0; // timer for periodic actions once per/sec
timerwd = 0; // timer for watchdog once per 30 sec
timermqtt = 10000; // Timer for the MQTT keep alive loop, initial value can be high, since it will be set as soon as IP is set.
timermqtt_interval = 250; // Interval for checking MQTT
timerAwakeFromDeepSleep = millis();
@@ -324,9 +313,16 @@ void setup()
// #ifndef ESP32
// connectionCheck.attach(30, connectionCheckHandler);
// #endif
timer20ms = millis();
timer100ms = millis();
timer1s = millis();
// Start the interval timers at N msec from now.
// Make sure to start them at some time after eachother,
// since they will keep running at the same interval.
setIntervalTimerOverride(TIMER_20MSEC, 5); // timer for periodic actions 50 x per/sec
setIntervalTimerOverride(TIMER_100MSEC, 66); // timer for periodic actions 10 x per/sec
setIntervalTimerOverride(TIMER_1SEC, 777); // timer for periodic actions once per/sec
setIntervalTimerOverride(TIMER_30SEC, 1333); // timer for watchdog once per 30 sec
setIntervalTimerOverride(TIMER_MQTT, 88); // timer for interaction with MQTT
setIntervalTimerOverride(TIMER_STATISTICS, 2222);
}
#ifdef USE_RTOS_MULTITASKING
@@ -395,38 +391,36 @@ void updateLoopStats() {
longestLoop = usecSince;
}
void updateLoopStats_30sec() {
void updateLoopStats_30sec(byte loglevel) {
loopCounterLast = loopCounter;
loopCounter = 0;
if (loopCounterLast > loopCounterMax)
loopCounterMax = loopCounterLast;
String log = F("LoopStats: shortestLoop: ");
log += shortestLoop;
log += F(" longestLoop: ");
log += longestLoop;
log += F(" avgLoopDuration: ");
log += loop_usec_duration_total / loopCounter_full;
log += F(" systemTimerDuration: ");
log += systemTimerDurationTotal / systemTimerCalls;
log += F(" systemTimerCalls: ");
log += systemTimerCalls;
log += F(" loopCounterMax: ");
log += loopCounterMax;
log += F(" loopCounterLast: ");
log += loopCounterLast;
log += F(" countFindPluginId: ");
log += countFindPluginId;
addLog(LOG_LEVEL_INFO, log);
msecTimerHandler.updateIdleTimeStats();
if (loglevelActiveFor(loglevel)) {
String log = F("LoopStats: shortestLoop: ");
log += shortestLoop;
log += F(" longestLoop: ");
log += longestLoop;
log += F(" avgLoopDuration: ");
log += loop_usec_duration_total / loopCounter_full;
log += F(" loopCounterMax: ");
log += loopCounterMax;
log += F(" loopCounterLast: ");
log += loopCounterLast;
log += F(" countFindPluginId: ");
log += countFindPluginId;
addLog(loglevel, log);
}
countFindPluginId = 0;
loop_usec_duration_total = 0;
loopCounter_full = 1;
systemTimerDurationTotal = 0;
systemTimerCalls = 1;
}
int getCPUload() {
return 100 - (100 * loopCounterLast / loopCounterMax);
float getCPUload() {
return 100.0 - msecTimerHandler.getIdleTimePct();
}
int getLoopCountPerSec() {
@@ -435,6 +429,7 @@ int getLoopCountPerSec() {
/*********************************************************************************************\
* MAIN LOOP
\*********************************************************************************************/
@@ -484,23 +479,7 @@ void loop()
//normal mode, run each task when its time
else
{
if (timeOutReached(timer20ms))
run50TimesPerSecond();
if (timeOutReached(timer100ms))
if(!UseRTOSMultitasking)
run10TimesPerSecond();
if (timeOutReached(timerwd))
runEach30Seconds();
if (timeOutReached(timer1s))
runOncePerSecond();
if (timeOutReached(timermqtt)) {
runPeriodicalMQTT();
}
handle_schedule();
}
backgroundtasks();
@@ -561,16 +540,14 @@ void updateMQTTclient_connected() {
} else {
timermqtt_interval = 250;
}
timermqtt = millis() + timermqtt_interval;
setIntervalTimer(TIMER_MQTT);
}
/*********************************************************************************************\
* Tasks that run 50 times per second
\*********************************************************************************************/
void run50TimesPerSecond()
{
setNextTimeInterval(timer20ms, 20);
void run50TimesPerSecond() {
START_TIMER;
PluginCall(PLUGIN_FIFTY_PER_SECOND, 0, dummyString);
STOP_TIMER(PLUGIN_CALL_50PS);
@@ -579,9 +556,7 @@ void run50TimesPerSecond()
/*********************************************************************************************\
* Tasks that run 10 times per second
\*********************************************************************************************/
void run10TimesPerSecond()
{
setNextTimeInterval(timer100ms, 100);
void run10TimesPerSecond() {
{
START_TIMER;
PluginCall(PLUGIN_TEN_PER_SECOND, 0, dummyString);
@@ -609,7 +584,7 @@ void run10TimesPerSecond()
void runOncePerSecond()
{
START_TIMER;
setNextTimeInterval(timer1s, 1000);
updateLogLevelCache();
dailyResetCounter++;
if (dailyResetCounter > 86400) // 1 day elapsed... //86400
{
@@ -620,8 +595,6 @@ void runOncePerSecond()
addLog(LOG_LEVEL_INFO, log);
}
checkSensors();
if (Settings.ConnectionFailuresThreshold)
if (connectionFailures > Settings.ConnectionFailuresThreshold)
delayedReboot(60);
@@ -658,8 +631,6 @@ void runOncePerSecond()
PluginCall(PLUGIN_ONCE_A_SECOND, 0, dummyString);
// unsigned long elapsed = micros() - start;
checkSystemTimers();
if (Settings.UseRules)
rulesTimers();
@@ -701,6 +672,17 @@ void runOncePerSecond()
STOP_TIMER(PLUGIN_CALL_1PS);
}
void logTimerStatistics() {
byte loglevel = LOG_LEVEL_DEBUG;
updateLoopStats_30sec(loglevel);
logStatistics(loglevel, true);
if (loglevelActiveFor(loglevel)) {
String queueLog = F("Scheduler stats: (called/tasks/max_length/idle%) ");
queueLog += msecTimerHandler.getQueueStats();
addLog(loglevel, queueLog);
}
}
/*********************************************************************************************\
* Tasks each 30 seconds
\*********************************************************************************************/
@@ -708,19 +690,18 @@ void runEach30Seconds()
{
extern void checkRAMtoLog();
checkRAMtoLog();
updateLoopStats_30sec();
logStatistics(true);
wdcounter++;
timerwd = millis() + 30000;
String log;
log.reserve(60);
log = F("WD : Uptime ");
log += wdcounter / 2;
log += F(" ConnectFailures ");
log += connectionFailures;
log += F(" FreeMem ");
log += FreeMem();
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log;
log.reserve(60);
log = F("WD : Uptime ");
log += wdcounter / 2;
log += F(" ConnectFailures ");
log += connectionFailures;
log += F(" FreeMem ");
log += FreeMem();
addLog(LOG_LEVEL_INFO, log);
}
sendSysInfoUDP(1);
refreshNodeList();
@@ -739,33 +720,6 @@ void runEach30Seconds()
}
/*********************************************************************************************\
* Check sensor timers
\*********************************************************************************************/
void checkSensors()
{
START_TIMER;
checkRAM(F("checkSensors"));
bool isDeepSleep = isDeepSleepEnabled();
//check all the devices and only run the sendtask if its time, or we if we used deep sleep mode
for (byte x = 0; x < TASKS_MAX; x++)
{
if (
(Settings.TaskDeviceTimer[x] != 0) &&
(isDeepSleep || timeOutReached(timerSensor[x]))
)
{
setNextTimeInterval(timerSensor[x], Settings.TaskDeviceTimer[x] * 1000);
if (timerSensor[x] == 0) // small fix if result is 0, else timer will be stopped...
timerSensor[x] = 1;
SensorSendTask(x);
}
}
saveUserVarToRTC();
STOP_TIMER(CHECK_SENSORS);
}
/*********************************************************************************************\
* send all sensordata
\*********************************************************************************************/
@@ -833,124 +787,6 @@ void SensorSendTask(byte TaskIndex)
}
/*********************************************************************************************\
* set global system timer
\*********************************************************************************************/
void setSystemTimer(unsigned long timer, byte plugin, int Par1, int Par2, int Par3)
{
setSystemTimer(timer, plugin, -1, Par1, Par2, Par3, 0, 0);
}
void setSystemTimer(unsigned long timer, byte plugin, short taskIndex, int Par1, int Par2, int Par3)
{
setSystemTimer(timer, plugin, taskIndex , Par1, Par2, Par3, 0, 0);
}
void setSystemTimer(unsigned long timer, byte plugin, short taskIndex, int Par1, int Par2, int Par3, int Par4)
{
setSystemTimer(timer, plugin, taskIndex , Par1, Par2, Par3, Par4, 0);
}
void setSystemTimer(unsigned long timer, byte plugin, short taskIndex, int Par1, int Par2, int Par3, int Par4, int Par5)
{
// plugin number and par1 form a unique key that can be used to restart a timer
// first check if a timer is not already running for this request
byte firstAvailable = SYSTEM_TIMER_MAX;
for (byte x = 0; x < SYSTEM_TIMER_MAX; x++)
{
if (systemTimers[x].timer != 0)
{
if ((systemTimers[x].plugin == plugin) && systemTimers[x].TaskIndex == taskIndex && (systemTimers[x].Par1 == Par1))
{
firstAvailable = x;
break;
}
}
else if(firstAvailable == SYSTEM_TIMER_MAX)
{
firstAvailable = x;
}
}
if (firstAvailable == SYSTEM_TIMER_MAX )
{
addLog(LOG_LEVEL_ERROR, F(NOTAVAILABLE_SYSTEM_TIMER_ERROR));
}
else
{
systemTimers[firstAvailable].plugin = plugin;
systemTimers[firstAvailable].TaskIndex = taskIndex;
systemTimers[firstAvailable].Par1 = Par1;
systemTimers[firstAvailable].Par2 = Par2;
systemTimers[firstAvailable].Par3 = Par3;
systemTimers[firstAvailable].Par4 = Par4;
systemTimers[firstAvailable].Par5 = Par5;
systemTimers[firstAvailable].timer = timer > 0
? millis() + timer
: 0;
}
}
//EDWIN: this function seems to be unused?
/*********************************************************************************************\
* set global system command timer
\*********************************************************************************************/
void setSystemCMDTimer(unsigned long timer, String& action)
{
for (byte x = 0; x < SYSTEM_CMD_TIMER_MAX; x++)
if (systemCMDTimers[x].timer == 0)
{
systemCMDTimers[x].timer = millis() + timer;
systemCMDTimers[x].action = action;
break;
}
}
/*********************************************************************************************\
* check global system timers
\*********************************************************************************************/
void checkSystemTimers()
{
unsigned long start = micros();
for (byte x = 0; x < SYSTEM_TIMER_MAX; x++)
if (systemTimers[x].timer != 0)
{
if (timeOutReached(systemTimers[x].timer))
{
struct EventStruct TempEvent;
TempEvent.TaskIndex = systemTimers[x].TaskIndex;
TempEvent.Par1 = systemTimers[x].Par1;
TempEvent.Par2 = systemTimers[x].Par2;
TempEvent.Par3 = systemTimers[x].Par3;
TempEvent.Par4 = systemTimers[x].Par4;
TempEvent.Par5 = systemTimers[x].Par5;
systemTimers[x].timer = 0;
const int y = getPluginId(systemTimers[x].TaskIndex);
if (y >= 0) {
Plugin_ptr[y](PLUGIN_TIMER_IN, &TempEvent, dummyString);
}
}
}
for (byte x = 0; x < SYSTEM_CMD_TIMER_MAX; x++)
if (systemCMDTimers[x].timer != 0)
if (timeOutReached(systemCMDTimers[x].timer))
{
struct EventStruct TempEvent;
parseCommandString(&TempEvent, systemCMDTimers[x].action);
if (!PluginCall(PLUGIN_WRITE, &TempEvent, systemCMDTimers[x].action))
ExecuteCommand(VALUE_SOURCE_SYSTEM, systemCMDTimers[x].action.c_str());
systemCMDTimers[x].timer = 0;
systemCMDTimers[x].action = "";
}
++systemTimerCalls;
systemTimerDurationTotal += usecPassedSince(start);;
}
/*********************************************************************************************\
* run background tasks
\*********************************************************************************************/
+16 -4
View File
@@ -1,10 +1,11 @@
void logStatistics(bool clearLog) {
void logStatistics(byte loglevel, bool clearLog) {
if (loglevelActiveFor(loglevel)) {
String log;
log.reserve(80);
for (auto& x: pluginStats) {
if (!x.second.isEmpty()) {
const int pluginId = x.first/32;
String P_name = "";
String P_name = "";
Plugin_ptr[pluginId](PLUGIN_GET_DEVICENAME, NULL, P_name);
log = F("PluginStats P_");
log += pluginId + 1;
@@ -14,7 +15,7 @@ void logStatistics(bool clearLog) {
log += getPluginFunctionName(x.first%32);
log += ' ';
log += getLogLine(x.second);
addLog(LOG_LEVEL_DEBUG, log);
addLog(loglevel, log);
if (clearLog) x.second.reset();
}
}
@@ -23,8 +24,19 @@ void logStatistics(bool clearLog) {
log = getMiscStatsName(x.first);
log += F(" stats: ");
log += getLogLine(x.second);
addLog(LOG_LEVEL_DEBUG, log);
addLog(loglevel, log);
if (clearLog) x.second.reset();
}
}
log = getMiscStatsName(TIME_DIFF_COMPUTE);
log += F(" stats: Count: ");
log += timediff_calls;
log += F(" - CPU cycles per call: ");
log += static_cast<float>(timediff_cpu_cycles_total) / static_cast<float>(timediff_calls);
addLog(loglevel, log);
if (clearLog) {
timediff_calls = 0;
timediff_cpu_cycles_total = 0;
}
}
}
+144
View File
@@ -2,6 +2,7 @@
#define ESPEASY_TIMETYPES_H_
#include <stdint.h>
#include <list>
struct timeStruct {
timeStruct() : Second(0), Minute(0), Hour(0), Wday(0), Day(0), Month(0), Year(0) {}
@@ -65,6 +66,149 @@ uint32_t calcTimeChangeForRule(const TimeChangeRule& r, int yr);
String getTimeString(char delimiter, bool show_seconds=true);
String getTimeString_ampm(char delimiter, bool show_seconds=true);
long timeDiff(unsigned long prev, unsigned long next);
long timePassedSince(unsigned long timestamp);
boolean timeOutReached(unsigned long timer);
long usecPassedSince(unsigned long timestamp);
boolean usecTimeOutReached(unsigned long timer);
void setSystemTimer(unsigned long timer, byte plugin, short taskIndex, int Par1,
int Par2 = 0, int Par3 = 0, int Par4 = 0, int Par5 = 0);
/*********************************************************************************************\
* TimerHandler Used by the Scheduler
\*********************************************************************************************/
struct timer_id_couple {
timer_id_couple(unsigned long id, unsigned long newtimer) : _id(id), _timer(newtimer) {}
timer_id_couple(unsigned long id) : _id(id) {
_timer = millis();
}
bool operator<(const timer_id_couple& other) {
const unsigned long now(millis());
// timediff > 0, means timer has already passed
return (timeDiff(_timer, now) > timeDiff(other._timer, now));
}
unsigned long _id;
unsigned long _timer;
};
struct msecTimerHandlerStruct {
msecTimerHandlerStruct() : get_called(0), get_called_ret_id(0), max_queue_length(0),
last_exec_time_usec(0), total_idle_time_usec(0), is_idle(false), idle_time_pct(0.0)
{
last_log_start_time = millis();
}
void registerAt(unsigned long id, unsigned long timer) {
timer_id_couple item(id, timer);
insert(item);
}
// Check if timeout has been reached and also return its set timer.
// Return 0 if no item has reached timeout moment.
unsigned long getNextId(unsigned long& timer) {
++get_called;
if (_timer_ids.empty()) {
recordIdle();
return 0;
}
timer_id_couple item = _timer_ids.front();
if (!timeOutReached(item._timer)) {
recordIdle();
return 0;
}
recordRunning();
unsigned long size = _timer_ids.size();
if (size > max_queue_length) max_queue_length = size;
_timer_ids.pop_front();
timer = item._timer;
++get_called_ret_id;
return item._id;
}
String getQueueStats() {
String result;
result += get_called;
result += '/';
result += get_called_ret_id;
result += '/';
result += max_queue_length;
result += '/';
result += idle_time_pct;
get_called = 0;
get_called_ret_id = 0;
//max_queue_length = 0;
return result;
}
void updateIdleTimeStats() {
const long duration = timePassedSince(last_log_start_time);
last_log_start_time = millis();
idle_time_pct = total_idle_time_usec / duration / 10.0;
total_idle_time_usec = 0;
}
float getIdleTimePct() {
return idle_time_pct;
}
private:
struct match_id {
match_id(unsigned long id) : _id(id) {}
bool operator() (const timer_id_couple& item) { return _id == item._id; }
unsigned long _id;
};
void insert(const timer_id_couple& item) {
if (item._id == 0) return;
// Make sure only one is present with the same id.
_timer_ids.remove_if(match_id(item._id));
const bool mustSort = !_timer_ids.empty();
_timer_ids.push_front(item);
if (mustSort)
_timer_ids.sort(); // TD-er: Must check if this is an expensive operation.
// It should be a relative light operation, to insert into a sorted list.
// Perhaps it is better to use std::set ????
// Keep in mind: order is based on timer, uniqueness is based on id.
}
void recordIdle() {
if (is_idle) return;
last_exec_time_usec = micros();
is_idle = true;
yield(); // Nothing to do, so call yield for backgroundtasks
}
void recordRunning() {
if (!is_idle) return;
is_idle = false;
total_idle_time_usec += usecPassedSince(last_exec_time_usec);
}
// Statistics
unsigned long get_called;
unsigned long get_called_ret_id;
unsigned long max_queue_length;
// Compute idle system time
unsigned long last_exec_time_usec;
unsigned long total_idle_time_usec;
unsigned long last_log_start_time;
bool is_idle;
float idle_time_pct;
// The list of set timers
std::list<timer_id_couple> _timer_ids;
};
#endif /* ESPEASY_TIMETYPES_H_ */
+151 -109
View File
@@ -11,19 +11,21 @@ void processConnect() {
++wifi_reconnects;
if (wifiStatus < ESPEASY_WIFI_CONNECTED) return;
const long connect_duration = timeDiff(last_wifi_connect_attempt_moment, lastConnectMoment);
String log = F("WIFI : Connected! AP: ");
log += WiFi.SSID();
log += F(" (");
log += WiFi.BSSIDstr();
log += F(") Ch: ");
log += last_channel;
if (connect_duration > 0 && connect_duration < 30000) {
// Just log times when they make sense.
log += F(" Duration: ");
log += connect_duration;
log += F(" ms");
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("WIFI : Connected! AP: ");
log += WiFi.SSID();
log += F(" (");
log += WiFi.BSSIDstr();
log += F(") Ch: ");
log += last_channel;
if (connect_duration > 0 && connect_duration < 30000) {
// Just log times when they make sense.
log += F(" Duration: ");
log += connect_duration;
log += F(" ms");
}
addLog(LOG_LEVEL_INFO, log);
}
addLog(LOG_LEVEL_INFO, log);
if (Settings.UseRules && bssid_changed) {
String event = F("WiFi#ChangedAccesspoint");
rulesProcessing(event);
@@ -42,14 +44,16 @@ void processDisconnect() {
String event = F("WiFi#Disconnected");
rulesProcessing(event);
}
String log = F("WIFI : Disconnected! Reason: '");
log += getLastDisconnectReason();
log += F("'");
if (lastConnectedDuration > 0) {
log += F(" Connected for ");
log += format_msec_duration(lastConnectedDuration);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("WIFI : Disconnected! Reason: '");
log += getLastDisconnectReason();
log += F("'");
if (lastConnectedDuration > 0) {
log += F(" Connected for ");
log += format_msec_duration(lastConnectedDuration);
}
addLog(LOG_LEVEL_INFO, log);
}
addLog(LOG_LEVEL_INFO, log);
logConnectionStatus();
}
@@ -64,52 +68,57 @@ void processGotIP() {
processedGetIP = true;
const IPAddress gw = WiFi.gatewayIP();
const IPAddress subnet = WiFi.subnetMask();
String log = F("WIFI : ");
if (useStaticIP()) {
log += F("Static IP: ");
} else {
log += F("DHCP IP: ");
}
log += formatIP(ip);
log += F(" (");
log += WifiGetHostname();
log += F(") GW: ");
log += formatIP(gw);
log += F(" SN: ");
log += formatIP(subnet);
const long dhcp_duration = timeDiff(lastConnectMoment, lastGetIPmoment);
if (dhcp_duration > 0 && dhcp_duration < 30000) {
// Just log times when they make sense.
log += F(" duration: ");
log += dhcp_duration;
log += F(" ms");
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("WIFI : ");
if (useStaticIP()) {
log += F("Static IP: ");
} else {
log += F("DHCP IP: ");
}
log += formatIP(ip);
log += F(" (");
log += WifiGetHostname();
log += F(") GW: ");
log += formatIP(gw);
log += F(" SN: ");
log += formatIP(subnet);
if (dhcp_duration > 0 && dhcp_duration < 30000) {
// Just log times when they make sense.
log += F(" duration: ");
log += dhcp_duration;
log += F(" ms");
}
addLog(LOG_LEVEL_INFO, log);
}
addLog(LOG_LEVEL_INFO, log);
// fix octet?
if (Settings.IP_Octet != 0 && Settings.IP_Octet != 255)
{
ip[3] = Settings.IP_Octet;
log = F("IP : Fixed IP octet:");
log += formatIP(ip);
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("IP : Fixed IP octet:");
log += formatIP(ip);
addLog(LOG_LEVEL_INFO, log);
}
WiFi.config(ip, gw, subnet);
}
#ifdef FEATURE_MDNS
log = F("WIFI : ");
if (MDNS.begin(WifiGetHostname().c_str(), WiFi.localIP())) {
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("WIFI : ");
if (MDNS.begin(WifiGetHostname().c_str(), WiFi.localIP())) {
log += F("mDNS started, with name: ");
log += WifiGetHostname();
log += F(".local");
log += F("mDNS started, with name: ");
log += WifiGetHostname();
log += F(".local");
}
else{
log += F("mDNS failed");
}
addLog(LOG_LEVEL_INFO, log);
}
else{
log += F("mDNS failed");
}
addLog(LOG_LEVEL_INFO, log);
#endif
// First try to get the time, since that may be used in logs
@@ -118,7 +127,7 @@ void processGotIP() {
}
mqtt_reconnect_count = 0;
timermqtt_interval = 100;
timermqtt = millis() + timermqtt_interval;
setIntervalTimer(TIMER_MQTT);
if (Settings.UseRules)
{
String event = F("WiFi#Connected");
@@ -140,11 +149,13 @@ void processGotIP() {
void processConnectAPmode() {
if (processedConnectAPmode) return;
processedConnectAPmode = true;
String log = F("AP Mode: Client connected: ");
log += formatMAC(lastMacConnectedAPmode);
log += F(" Connected devices: ");
log += WiFi.softAPgetStationNum();
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("AP Mode: Client connected: ");
log += formatMAC(lastMacConnectedAPmode);
log += F(" Connected devices: ");
log += WiFi.softAPgetStationNum();
addLog(LOG_LEVEL_INFO, log);
}
timerAPoff = 0; // Disable timer to switch AP off
setWebserverRunning(true);
// Start DNS, only used if the ESP has no valid WiFi config
@@ -160,11 +171,13 @@ void processDisconnectAPmode() {
if (processedDisconnectAPmode) return;
processedDisconnectAPmode = true;
const int nrStationsConnected = WiFi.softAPgetStationNum();
String log = F("AP Mode: Client disconnected: ");
log += formatMAC(lastMacDisconnectedAPmode);
log += F(" Connected devices: ");
log += nrStationsConnected;
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("AP Mode: Client disconnected: ");
log += formatMAC(lastMacDisconnectedAPmode);
log += F(" Connected devices: ");
log += nrStationsConnected;
addLog(LOG_LEVEL_INFO, log);
}
if (nrStationsConnected == 0) {
timerAPoff = millis() + WIFI_AP_OFF_TIMER_DURATION;
}
@@ -183,9 +196,11 @@ void processDisableAPmode() {
void processScanDone() {
if (processedScanDone) return;
processedScanDone = true;
String log = F("WIFI : Scan finished, found: ");
log += scan_done_number;
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("WIFI : Scan finished, found: ");
log += scan_done_number;
addLog(LOG_LEVEL_INFO, log);
}
int bestScanID = -1;
int32_t bestRssi = -1000;
@@ -207,9 +222,11 @@ void processScanDone() {
if (!selectNextWiFiSettings()) done = true;
}
if (bestScanID >= 0) {
log = F("WIFI : Selected: ");
log += formatScanResult(bestScanID, " ");
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("WIFI : Selected: ");
log += formatScanResult(bestScanID, " ");
addLog(LOG_LEVEL_INFO, log);
}
lastWiFiSettings = bestWiFiSettings;
uint8_t * scanbssid = WiFi.BSSID(bestScanID);
if (scanbssid) {
@@ -333,17 +350,21 @@ void setAPinternal(bool enable)
addLog(LOG_LEVEL_ERROR, F("WIFI : [AP] softAPConfig failed!"));
}
if (WiFi.softAP(softAPSSID.c_str(),pwd.c_str())) {
String log(F("WIFI : AP Mode ssid will be "));
log += softAPSSID;
log += F(" with address ");
log += WiFi.softAPIP().toString();
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log(F("WIFI : AP Mode ssid will be "));
log += softAPSSID;
log += F(" with address ");
log += WiFi.softAPIP().toString();
addLog(LOG_LEVEL_INFO, log);
}
} else {
String log(F("WIFI : Error while starting AP Mode with SSID: "));
log += softAPSSID;
log += F(" IP: ");
log += apIP.toString();
addLog(LOG_LEVEL_ERROR, log);
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
String log(F("WIFI : Error while starting AP Mode with SSID: "));
log += softAPSSID;
log += F(" IP: ");
log += apIP.toString();
addLog(LOG_LEVEL_ERROR, log);
}
}
#ifdef ESP32
@@ -445,7 +466,6 @@ bool prepareWiFi() {
return false;
}
setSTA(true);
String log = "";
char hostname[40];
strncpy(hostname, WifiGetHostname().c_str(), sizeof(hostname));
#if defined(ESP8266)
@@ -524,15 +544,17 @@ void setupStaticIPconfig() {
const IPAddress gw = Settings.Gateway;
const IPAddress subnet = Settings.Subnet;
const IPAddress dns = Settings.DNS;
String log = F("IP : Static IP : ");
log += formatIP(ip);
log += F(" GW: ");
log += formatIP(gw);
log += F(" SN: ");
log += formatIP(subnet);
log += F(" DNS: ");
log += formatIP(dns);
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("IP : Static IP : ");
log += formatIP(ip);
log += F(" GW: ");
log += formatIP(gw);
log += F(" SN: ");
log += formatIP(subnet);
log += F(" DNS: ");
log += formatIP(dns);
addLog(LOG_LEVEL_INFO, log);
}
WiFi.config(ip, gw, subnet, dns);
}
@@ -564,11 +586,13 @@ bool tryConnectWiFi() {
}
const char* ssid = getLastWiFiSettingsSSID();
const char* passphrase = getLastWiFiSettingsPassphrase();
String log = F("WIFI : Connecting ");
log += ssid;
log += F(" attempt #");
log += wifi_connect_attempt;
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("WIFI : Connecting ");
log += ssid;
log += F(" attempt #");
log += wifi_connect_attempt;
addLog(LOG_LEVEL_INFO, log);
}
setupStaticIPconfig();
last_wifi_connect_attempt_moment = millis();
switch (wifi_connect_attempt) {
@@ -585,15 +609,19 @@ bool tryConnectWiFi() {
logConnectionStatus();
switch (WiFi.status()) {
case WL_NO_SSID_AVAIL: {
log = F("WIFI : No SSID found matching: ");
log += ssid;
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("WIFI : No SSID found matching: ");
log += ssid;
addLog(LOG_LEVEL_INFO, log);
}
return false;
}
case WL_CONNECT_FAILED: {
log = F("WIFI : Connection failed to: ");
log += ssid;
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("WIFI : Connection failed to: ");
log += ssid;
addLog(LOG_LEVEL_INFO, log);
}
return false;
}
default:
@@ -728,18 +756,22 @@ void logConnectionStatus() {
#ifndef ESP32
const uint8_t sdk_wifistatus = wifi_station_get_connect_status();
if ((arduino_corelib_wifistatus == WL_CONNECTED) != (sdk_wifistatus == STATION_GOT_IP)) {
log = F("WIFI : SDK station status differs from Arduino status. SDK-status: ");
log += SDKwifiStatusToString(sdk_wifistatus);
log += F(" Arduino status: ");
log += ArduinoWifiStatusToString(arduino_corelib_wifistatus);
addLog(LOG_LEVEL_ERROR, log);
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
String log = F("WIFI : SDK station status differs from Arduino status. SDK-status: ");
log += SDKwifiStatusToString(sdk_wifistatus);
log += F(" Arduino status: ");
log += ArduinoWifiStatusToString(arduino_corelib_wifistatus);
addLog(LOG_LEVEL_ERROR, log);
}
}
#endif
log = F("WIFI : Arduino wifi status: ");
log += ArduinoWifiStatusToString(arduino_corelib_wifistatus);
log += F(" ESPeasy internal wifi status: ");
log += ESPeasyWifiStatusToString();
addLog(LOG_LEVEL_DEBUG_MORE, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) {
String log = F("WIFI : Arduino wifi status: ");
log += ArduinoWifiStatusToString(arduino_corelib_wifistatus);
log += F(" ESPeasy internal wifi status: ");
log += ESPeasyWifiStatusToString();
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
}
@@ -752,6 +784,16 @@ void WifiCheck()
return;
processDisableAPmode();
IPAddress ip = WiFi.localIP();
if (!useStaticIP()) {
if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0) {
if (WiFiConnected()) {
// Some strange situation where the DHCP renew probably has failed and erased the config.
resetWiFi();
}
}
}
if (wifiStatus != ESPEASY_WIFI_SERVICES_INITIALIZED) {
if (timeOutReached(last_wifi_connect_attempt_moment + (1000 + wifi_connect_attempt * 200))) {
WiFiConnectRelaxed();
+186 -97
View File
@@ -73,7 +73,7 @@ void deepSleep(int delay)
return;
}
}
saveUserVarToRTC();
deepSleepStart(delay); // Call deepSleepStart function after these checks
}
@@ -100,7 +100,7 @@ void deepSleepStart(int delay)
#endif
}
boolean remoteConfig(struct EventStruct *event, String& string)
boolean remoteConfig(struct EventStruct *event, const String& string)
{
checkRAM(F("remoteConfig"));
boolean success = false;
@@ -112,7 +112,9 @@ boolean remoteConfig(struct EventStruct *event, String& string)
if (parseString(string, 2) == F("task"))
{
int configCommandPos1 = getParamStartPos(string, 3);
if (configCommandPos1 < 0) return success; // TD-er: Should this be return false?
int configCommandPos2 = getParamStartPos(string, 4);
if (configCommandPos2 < 0 || (configCommandPos2 - configCommandPos1) < 1) return success; // TD-er: Should this be return false?
String configTaskName = string.substring(configCommandPos1, configCommandPos2 - 1);
String configCommand = string.substring(configCommandPos2);
@@ -517,11 +519,13 @@ void fileSystemCheck()
fs::FSInfo fs_info;
SPIFFS.info(fs_info);
String log = F("FS : Mount successful, used ");
log=log+fs_info.usedBytes;
log=log+F(" bytes of ");
log=log+fs_info.totalBytes;
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("FS : Mount successful, used ");
log=log+fs_info.usedBytes;
log=log+F(" bytes of ");
log=log+fs_info.totalBytes;
addLog(LOG_LEVEL_INFO, log);
}
#endif
fs::File f = SPIFFS.open(FILE_CONFIG, "r");
@@ -1054,13 +1058,15 @@ String LoadFromFile(char* fname, int index, byte* memAddress, int datasize)
START_TIMER;
checkRAM(F("LoadFromFile"));
String log = F("LoadFromFile: ");
log += fname;
log += F(" index: ");
log += index;
log += F(" datasize: ");
log += datasize;
addLog(LOG_LEVEL_DEBUG, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_DEV)) {
String log = F("LoadFromFile: ");
log += fname;
log += F(" index: ");
log += index;
log += F(" datasize: ");
log += datasize;
addLog(LOG_LEVEL_DEBUG_DEV, log);
}
fs::File f = SPIFFS.open(fname, "r+");
SPIFFS_CHECK(f, fname);
@@ -1209,11 +1215,11 @@ void ResetFactory(void)
str2ip((char*)DEFAULT_SYSLOG_IP, Settings.Syslog_IP);
Settings.SyslogLevel = DEFAULT_SYSLOG_LEVEL;
Settings.SerialLogLevel = DEFAULT_SERIAL_LOG_LEVEL;
Settings.SyslogFacility = DEFAULT_SYSLOG_FACILITY;
Settings.WebLogLevel = DEFAULT_WEB_LOG_LEVEL;
Settings.SDLogLevel = DEFAULT_SD_LOG_LEVEL;
setLogLevelFor(LOG_TO_SYSLOG, DEFAULT_SYSLOG_LEVEL);
setLogLevelFor(LOG_TO_SERIAL, DEFAULT_SERIAL_LOG_LEVEL);
setLogLevelFor(LOG_TO_WEBLOG, DEFAULT_WEB_LOG_LEVEL);
setLogLevelFor(LOG_TO_SDCARD, DEFAULT_SD_LOG_LEVEL);
Settings.SyslogFacility = DEFAULT_SYSLOG_FACILITY;
Settings.UseValueLogger = DEFAULT_USE_SD_LOG;
Settings.UseSerial = DEFAULT_USE_SERIAL;
@@ -1438,8 +1444,8 @@ String getPartitionType(byte pType, byte pSubType) {
}
switch (partitionSubType) {
case ESP_PARTITION_SUBTYPE_APP_FACTORY: return F("Factory application");
case ESP_PARTITION_SUBTYPE_APP_TEST: return F("Test application");
case ESP_PARTITION_SUBTYPE_APP_FACTORY: return F("Factory app");
case ESP_PARTITION_SUBTYPE_APP_TEST: return F("Test app");
default: break;
}
}
@@ -1522,21 +1528,48 @@ boolean isInt(const String& tBuf) {
return isNumerical(tBuf, true);
}
String getNumerical(const String& tBuf, bool mustBeInteger) {
String result = "";
const unsigned int bufLength = tBuf.length();
if (bufLength == 0) return result;
boolean decPt = false;
int firstDec = 0;
char c = tBuf.charAt(0);
if(c == '+' || c == '-') {
result += c;
firstDec = 1;
}
for(unsigned int x=firstDec; x < bufLength; ++x) {
c = tBuf.charAt(x);
if(c == '.') {
if (mustBeInteger) return result;
// Only one decimal point allowed
if(decPt) return result;
else decPt = true;
}
else if(c < '0' || c > '9') return result;
result += c;
}
return result;
}
boolean isNumerical(const String& tBuf, bool mustBeInteger) {
const unsigned int bufLength = tBuf.length();
if (bufLength == 0) return false;
boolean decPt = false;
int firstDec = 0;
if(tBuf.charAt(0) == '+' || tBuf.charAt(0) == '-')
char c = tBuf.charAt(0);
if(c == '+' || c == '-')
firstDec = 1;
for(unsigned int x=firstDec; x < bufLength; ++x) {
if(tBuf.charAt(x) == '.') {
c = tBuf.charAt(x);
if(c == '.') {
if (mustBeInteger) return false;
// Only one decimal point allowed
if(decPt) return false;
else decPt = true;
}
else if(tBuf.charAt(x) < '0' || tBuf.charAt(x) > '9') return false;
else if(c < '0' || c > '9') return false;
}
return true;
}
@@ -1568,11 +1601,11 @@ void initLog()
{
//make sure addLog doesnt do any stuff before initalisation of Settings is complete.
Settings.UseSerial=true;
Settings.SyslogLevel=0;
Settings.SyslogFacility=0;
Settings.SerialLogLevel=2; //logging during initialisation
Settings.WebLogLevel=2;
Settings.SDLogLevel=0;
setLogLevelFor(LOG_TO_SYSLOG, 0);
setLogLevelFor(LOG_TO_SERIAL, 2); //logging during initialisation
setLogLevelFor(LOG_TO_WEBLOG, 2);
setLogLevelFor(LOG_TO_SDCARD, 0);
}
/********************************************************************************************\
@@ -1590,17 +1623,16 @@ String getLogLevelDisplayString(byte index, int& logLevel) {
}
}
void addLog(byte loglevel, String& string)
void addToLog(byte loglevel, String& string)
{
addLog(loglevel, string.c_str());
addToLog(loglevel, string.c_str());
}
void addLog(byte logLevel, const __FlashStringHelper* flashString)
void addToLog(byte logLevel, const __FlashStringHelper* flashString)
{
checkRAM(F("addLog"));
checkRAM(F("addToLog"));
String s(flashString);
addLog(logLevel, s.c_str());
addToLog(logLevel, s.c_str());
}
bool SerialAvailableForWrite() {
@@ -1611,6 +1643,38 @@ bool SerialAvailableForWrite() {
return true;
}
void disableSerialLog() {
log_to_serial_disabled = true;
setLogLevelFor(LOG_TO_SERIAL, 0);
}
void setLogLevelFor(byte destination, byte logLevel) {
switch (destination) {
case LOG_TO_SERIAL:
if (!log_to_serial_disabled || logLevel == 0)
Settings.SerialLogLevel = logLevel; break;
case LOG_TO_SYSLOG: Settings.SyslogLevel = logLevel; break;
case LOG_TO_WEBLOG: Settings.WebLogLevel = logLevel; break;
case LOG_TO_SDCARD: Settings.SDLogLevel = logLevel; break;
default:
break;
}
updateLogLevelCache();
}
void updateLogLevelCache() {
byte max_lvl = 0;
max_lvl = _max(max_lvl, Settings.SerialLogLevel);
max_lvl = _max(max_lvl, Settings.SyslogLevel);
max_lvl = _max(max_lvl, Settings.WebLogLevel);
max_lvl = _max(max_lvl, Settings.SDLogLevel);
highest_active_log_level = max_lvl;
}
bool loglevelActiveFor(byte logLevel) {
return loglevelActive(logLevel, highest_active_log_level);
}
boolean loglevelActiveFor(byte destination, byte logLevel) {
byte logLevelSettings = 0;
switch (destination) {
@@ -1644,7 +1708,7 @@ boolean loglevelActive(byte logLevel, byte logLevelSettings) {
return (logLevel <= logLevelSettings);
}
void addLog(byte logLevel, const char *line)
void addToLog(byte logLevel, const char *line)
{
if (loglevelActiveFor(LOG_TO_SERIAL, logLevel)) {
Serial.print(millis());
@@ -2064,11 +2128,13 @@ String parseTemplate(String &tmpString, byte lineSize)
newString += " ";
}
{
String logFormatted = F("DEBUG: Formatted String='");
logFormatted += newString;
logFormatted += value;
logFormatted += "'";
addLog(LOG_LEVEL_DEBUG, logFormatted);
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
String logFormatted = F("DEBUG: Formatted String='");
logFormatted += newString;
logFormatted += value;
logFormatted += "'";
addLog(LOG_LEVEL_DEBUG, logFormatted);
}
}
}
}
@@ -2076,10 +2142,12 @@ String parseTemplate(String &tmpString, byte lineSize)
newString += String(value);
{
String logParsed = F("DEBUG DEV: Parsed String='");
logParsed += newString;
logParsed += "'";
addLog(LOG_LEVEL_DEBUG_DEV, logParsed);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_DEV)) {
String logParsed = F("DEBUG DEV: Parsed String='");
logParsed += newString;
logParsed += "'";
addLog(LOG_LEVEL_DEBUG_DEV, logParsed);
}
}
break;
}
@@ -2424,11 +2492,11 @@ void rulesProcessing(String& event)
{
checkRAM(F("rulesProcessing"));
unsigned long timer = millis();
String log = "";
log = F("EVENT: ");
log += event;
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("EVENT: ");
log += event;
addLog(LOG_LEVEL_INFO, log);
}
for (byte x = 0; x < RULESETS_MAX; x++)
{
@@ -2444,10 +2512,14 @@ void rulesProcessing(String& event)
rulesProcessingFile(fileName, event);
}
log += F(" Processing time:");
log += timePassedSince(timer);
log += F(" milliSeconds");
addLog(LOG_LEVEL_DEBUG, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
String log = F("EVENT: ");
log += event;
log += F(" Processing time:");
log += timePassedSince(timer);
log += F(" milliSeconds");
addLog(LOG_LEVEL_DEBUG, log);
}
}
@@ -2470,8 +2542,7 @@ String rulesProcessingFile(String fileName, String& event)
nestingLevel++;
if (nestingLevel > RULES_MAX_NESTING_LEVEL)
{
log = F("EVENT: Error: Nesting level exceeded!");
addLog(LOG_LEVEL_ERROR, log);
addLog(LOG_LEVEL_ERROR, F("EVENT: Error: Nesting level exceeded!"));
nestingLevel--;
return (log);
}
@@ -2585,6 +2656,8 @@ String rulesProcessingFile(String fileName, String& event)
{
conditional = true;
String check = lcAction.substring(split + 3);
log = F("[if ");
log += check;
log += F("]=");
@@ -2620,9 +2693,11 @@ String rulesProcessingFile(String fileName, String& event)
{
ifBranche = false;
isCommand = false;
log = F("else = ");
log += (conditional && (condition == ifBranche)) ? F("true") : F("false");
addLog(LOG_LEVEL_DEBUG, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
String log = F("else = ");
log += (conditional && (condition == ifBranche)) ? F("true") : F("false");
addLog(LOG_LEVEL_DEBUG, log);
}
}
if (lcAction == "endif") // conditional block ends here
@@ -2649,9 +2724,12 @@ String rulesProcessingFile(String fileName, String& event)
action.replace(F("%eventvalue%"), tmpString); // substitute %eventvalue% in actions with the actual value from the event
}
}
log = F("ACT : ");
log += action;
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("ACT : ");
log += action;
addLog(LOG_LEVEL_INFO, log);
}
struct EventStruct TempEvent;
parseCommandString(&TempEvent, action);
@@ -2660,11 +2738,13 @@ String rulesProcessingFile(String fileName, String& event)
String tmpAction(action);
if (!PluginCall(PLUGIN_WRITE, &TempEvent, tmpAction)) {
if (!tmpAction.equals(action)) {
String log = F("PLUGIN_WRITE altered the string: ");
log += action;
log += F(" to: ");
log += tmpAction;
addLog(LOG_LEVEL_ERROR, log);
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
String log = F("PLUGIN_WRITE altered the string: ");
log += action;
log += F(" to: ");
log += tmpAction;
addLog(LOG_LEVEL_ERROR, log);
}
}
ExecuteCommand(VALUE_SOURCE_SYSTEM, action.c_str());
}
@@ -2994,28 +3074,34 @@ void createRuleEvents(byte TaskIndex)
void SendValueLogger(byte TaskIndex)
{
bool featureSD = false;
#ifdef FEATURE_SD
featureSD = true;
#endif
String logger;
if (featureSD || loglevelActiveFor(LOG_LEVEL_DEBUG)) {
LoadTaskSettings(TaskIndex);
byte DeviceIndex = getDeviceIndex(Settings.TaskDeviceNumber[TaskIndex]);
for (byte varNr = 0; varNr < Device[DeviceIndex].ValueCount; varNr++)
{
logger += getDateString('-');
logger += F(" ");
logger += getTimeString(':');
logger += F(",");
logger += Settings.Unit;
logger += F(",");
logger += ExtraTaskSettings.TaskDeviceName;
logger += F(",");
logger += ExtraTaskSettings.TaskDeviceValueNames[varNr];
logger += F(",");
logger += formatUserVarNoCheck(TaskIndex, varNr);
logger += F("\r\n");
}
LoadTaskSettings(TaskIndex);
byte DeviceIndex = getDeviceIndex(Settings.TaskDeviceNumber[TaskIndex]);
for (byte varNr = 0; varNr < Device[DeviceIndex].ValueCount; varNr++)
{
logger += getDateString('-');
logger += F(" ");
logger += getTimeString(':');
logger += F(",");
logger += Settings.Unit;
logger += F(",");
logger += ExtraTaskSettings.TaskDeviceName;
logger += F(",");
logger += ExtraTaskSettings.TaskDeviceValueNames[varNr];
logger += F(",");
logger += formatUserVarNoCheck(TaskIndex, varNr);
logger += F("\r\n");
addLog(LOG_LEVEL_DEBUG, logger);
}
addLog(LOG_LEVEL_DEBUG, logger);
#ifdef FEATURE_SD
String filename = F("VALUES.CSV");
File logFile = SD.open(filename, FILE_WRITE);
@@ -3087,15 +3173,17 @@ class RamTracker{
if (writePtr >= TRACEENTRIES) writePtr=0; // inc write pointer and wrap around too.
};
void getTraceBuffer(){ // return giant strings, one line per trace. Add stremToWeb method to avoid large strings.
String retval="Memtrace\n";
for (int i = 0; i< TRACES; i++){
retval += String(i);
retval += ": lowest: ";
retval += String(tracesMemory[i]);
retval += " ";
retval += traces[i];
addLog(LOG_LEVEL_DEBUG_DEV, retval);
retval="";
if (loglevelActiveFor(LOG_LEVEL_DEBUG_DEV)) {
String retval="Memtrace\n";
for (int i = 0; i< TRACES; i++){
retval += String(i);
retval += ": lowest: ";
retval += String(tracesMemory[i]);
retval += " ";
retval += traces[i];
addLog(LOG_LEVEL_DEBUG_DEV, retval);
retval="";
}
}
}
}myRamTracker; // instantiate class. (is global now)
@@ -3367,10 +3455,11 @@ void ArduinoOTAInit()
});
ArduinoOTA.begin();
String log = F("OTA : Arduino OTA enabled on port ");
log += ARDUINO_OTA_PORT;
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("OTA : Arduino OTA enabled on port ");
log += ARDUINO_OTA_PORT;
addLog(LOG_LEVEL_INFO, log);
}
}
#endif
+17 -12
View File
@@ -121,9 +121,11 @@ void checkUDP()
formatMAC(mac, macaddress);
char ipaddress[20];
formatIP(ip, ipaddress);
char log[80];
sprintf_P(log, PSTR("UDP : %s,%s,%u"), macaddress, ipaddress, unit);
addLog(LOG_LEVEL_DEBUG_MORE, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) {
char log[80];
sprintf_P(log, PSTR("UDP : %s,%s,%u"), macaddress, ipaddress, unit);
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
break;
}
@@ -181,9 +183,12 @@ void sendUDP(byte unit, byte* data, byte size)
if (unit != 255)
if (Nodes[unit].ip[0] == 0)
return;
String log = F("UDP : Send UDP message to ");
log += unit;
addLog(LOG_LEVEL_DEBUG_MORE, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) {
String log = F("UDP : Send UDP message to ");
log += unit;
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
statusLED(true);
@@ -220,7 +225,6 @@ void refreshNodeList()
\*********************************************************************************************/
void sendSysInfoUDP(byte repeats)
{
char log[80];
if (Settings.UDPPort == 0 || !WiFiConnected(100))
return;
@@ -235,8 +239,7 @@ void sendSysInfoUDP(byte repeats)
// 1 byte node type id
// send my info to the world...
strcpy_P(log, PSTR("UDP : Send Sysinfo message"));
addLog(LOG_LEVEL_DEBUG_MORE, log);
addLog(LOG_LEVEL_DEBUG_MORE, F("UDP : Send Sysinfo message"));
for (byte counter = 0; counter < repeats; counter++)
{
uint8_t mac[] = {0, 0, 0, 0, 0, 0};
@@ -635,9 +638,11 @@ bool hostReachable(const IPAddress& ip) {
delay(50);
--retry;
}
String log = F("Host unreachable: ");
log += formatIP(ip);
addLog(LOG_LEVEL_ERROR, log);
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
String log = F("Host unreachable: ");
log += formatIP(ip);
addLog(LOG_LEVEL_ERROR, log);
}
if (ip[1] == 0 && ip[2] == 0 && ip[3] == 0) {
// Work-around to fix connected but not able to communicate.
addLog(LOG_LEVEL_ERROR, F("Wifi : Detected strange behavior, reconnect wifi."));
+194
View File
@@ -0,0 +1,194 @@
#define TIMER_ID_SHIFT 28
#define CONST_INTERVAL_TIMER 1
#define GENERIC_TIMER 2
#define SYSTEM_TIMER 3
#define TASK_DEVICE_TIMER 4
void setTimer(unsigned long id) {
setTimer(GENERIC_TIMER, id, 0);
}
void setIntervalTimer(unsigned long id) {
setIntervalTimer(id, millis());
}
void setIntervalTimerOverride(unsigned long id, unsigned long msecFromNow) {
unsigned long timer = millis();
setNextTimeInterval(timer, msecFromNow);
setNewTimerAt(getMixedId(CONST_INTERVAL_TIMER, id), timer);
}
void setIntervalTimer(unsigned long id, unsigned long lasttimer) {
// Set the initial timers for the regular runs
unsigned long interval = 0;
switch (id) {
case TIMER_20MSEC: interval = 20; break;
case TIMER_100MSEC: interval = 100; break;
case TIMER_1SEC: interval = 1000; break;
case TIMER_30SEC: interval = 30000; break;
case TIMER_MQTT: interval = timermqtt_interval; break;
case TIMER_STATISTICS: interval = 30000; break;
}
unsigned long timer = lasttimer;
setNextTimeInterval(timer, interval);
setNewTimerAt(getMixedId(CONST_INTERVAL_TIMER, id), timer);
}
void setTimer(unsigned long timerType, unsigned long id, unsigned long msecFromNow) {
setNewTimerAt(getMixedId(timerType, id), millis() + msecFromNow);
}
void setSystemTimer(unsigned long timer, byte plugin, short taskIndex, int Par1, int Par2, int Par3, int Par4, int Par5)
{
// plugin number and par1 form a unique key that can be used to restart a timer
const unsigned long systemTimerId = createSystemTimerId(plugin, Par1);
systemTimerStruct timer_data;
timer_data.TaskIndex = taskIndex;
timer_data.Par1 = Par1;
timer_data.Par2 = Par2;
timer_data.Par3 = Par3;
timer_data.Par4 = Par4;
timer_data.Par5 = Par5;
systemTimers[systemTimerId] = timer_data;
setTimer(SYSTEM_TIMER, systemTimerId, timer);
}
void setNewTimerAt(unsigned long id, unsigned long timer) {
START_TIMER;
msecTimerHandler.registerAt(id, timer);
STOP_TIMER(SET_NEW_TIMER);
}
unsigned long createSystemTimerId(byte plugin, int Par1) {
const unsigned long mask = (1 << TIMER_ID_SHIFT) -1;
const unsigned long mixed = (Par1 << 8) + plugin;
return (mixed & mask);
}
/* // Not (yet) used
void splitSystemTimerId(const unsigned long mixed_id, byte& plugin, int& Par1) {
const unsigned long mask = (1 << TIMER_ID_SHIFT) -1;
plugin = mixed_id & 0xFF;
Par1 = (mixed_id & mask) >> 8;
}
*/
unsigned long getMixedId(unsigned long timerType, unsigned long id) {
return (timerType << TIMER_ID_SHIFT) + id;
}
void handle_schedule() {
unsigned long timer;
const unsigned long mixed_id = msecTimerHandler.getNextId(timer);
if (mixed_id == 0) 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;
switch (timerType) {
case CONST_INTERVAL_TIMER:
setIntervalTimer(id, timer);
process_interval_timer(id);
break;
case SYSTEM_TIMER:
process_system_timer(id);
break;
case TASK_DEVICE_TIMER:
process_task_device_timer(id, timer);
break;
}
}
void process_interval_timer(unsigned long id) {
switch (id) {
case TIMER_20MSEC:
run50TimesPerSecond();
break;
case TIMER_100MSEC:
if(!UseRTOSMultitasking)
run10TimesPerSecond();
break;
case TIMER_1SEC:
runOncePerSecond();
break;
case TIMER_30SEC:
runEach30Seconds();
break;
case TIMER_MQTT:
runPeriodicalMQTT();
break;
case TIMER_STATISTICS:
logTimerStatistics();
break;
}
}
void process_system_timer(unsigned long id) {
START_TIMER;
const systemTimerStruct timer_data = systemTimers[id];
struct EventStruct TempEvent;
TempEvent.TaskIndex = timer_data.TaskIndex;
TempEvent.Par1 = timer_data.Par1;
TempEvent.Par2 = timer_data.Par2;
TempEvent.Par3 = timer_data.Par3;
TempEvent.Par4 = timer_data.Par4;
TempEvent.Par5 = timer_data.Par5;
// TD-er: Not sure if we have to keep original source for notifications.
TempEvent.Source = VALUE_SOURCE_SYSTEM;
const int y = getPluginId(timer_data.TaskIndex);
/*
String log = F("proc_system_timer: Pluginid: ");
log += y;
log += F(" taskIndex: ");
log += timer_data.TaskIndex;
log += F(" sysTimerID: ");
log += id;
addLog(LOG_LEVEL_INFO, log);
*/
if (y >= 0) {
String dummy;
Plugin_ptr[y](PLUGIN_TIMER_IN, &TempEvent, dummy);
}
systemTimers.erase(id);
STOP_TIMER(PROC_SYS_TIMER);
}
void schedule_task_device_timer_at_init(unsigned long task_index) {
unsigned long runAt = millis();
if (!isDeepSleepEnabled()) {
// Deepsleep is not enabled, add some offset based on the task index
// to make sure not all are run at the same time.
// This scheduled time may be overriden by the plugin's own init.
runAt += (task_index * 37) + Settings.MessageDelay;
}
schedule_task_device_timer(task_index, runAt);
}
void schedule_task_device_timer(unsigned long task_index, unsigned long runAt) {
/*
String log = F("schedule_task_device_timer: task: ");
log += task_index;
log += F(" @ ");
log += runAt;
if (Settings.TaskDeviceEnabled[task_index]) {
log += F(" (enabled)");
}
addLog(LOG_LEVEL_INFO, log);
*/
if (task_index >= TASKS_MAX) return;
if (Settings.TaskDeviceEnabled[task_index]) {
setNewTimerAt(getMixedId(TASK_DEVICE_TIMER, task_index), runAt);
}
}
void process_task_device_timer(unsigned long task_index, unsigned long lasttimer) {
unsigned long newtimer = Settings.TaskDeviceTimer[task_index];
if (newtimer != 0) {
newtimer = lasttimer + (newtimer * 1000);
schedule_task_device_timer(task_index, newtimer);
}
START_TIMER;
SensorSendTask(task_index);
STOP_TIMER(SENSOR_SEND_TASK);
}
+56 -37
View File
@@ -60,14 +60,18 @@ String formatMAC(const uint8_t* mac) {
return String(str);
}
String formatToHex(unsigned long value) {
String result = F("0x");
String formatToHex(unsigned long value, const String& prefix) {
String result = prefix;
String hex(value, HEX);
hex.toUpperCase();
result += hex;
return result;
}
String formatToHex(unsigned long value) {
return formatToHex(value, F("0x"));
}
String formatHumanReadable(unsigned long value, unsigned long factor) {
float floatValue(value);
byte steps = 0;
@@ -83,7 +87,7 @@ String formatHumanReadable(unsigned long value, unsigned long factor) {
case 2: result += 'M'; break;
case 3: result += 'G'; break;
case 4: result += 'T'; break;
default:
default:
result += '*';
result += factor;
result += '^';
@@ -135,10 +139,10 @@ String toString(WiFiMode_t mode)
break;
case WIFI_AP_STA:
result = F("AP+STA");
break;
break;
default:
break;
}
}
return result;
}
@@ -231,47 +235,38 @@ String to_json_object_value(const String& object, const String& value) {
/*********************************************************************************************\
Parse a string and get the xth command or parameter
Parse a string and get the xth command or parameter in lower case
\*********************************************************************************************/
String parseString(String& string, byte indexFind)
{
String tmpString = string;
tmpString += ',';
tmpString.replace(' ', ',');
String locateString = "";
byte count = 0;
int index = tmpString.indexOf(',');
while (index > 0)
{
count++;
locateString = tmpString.substring(0, index);
tmpString = tmpString.substring(index + 1);
index = tmpString.indexOf(',');
if (count == indexFind)
{
locateString.toLowerCase();
return locateString;
}
String parseString(const String& string, byte indexFind) {
int startpos = 0;
if (indexFind > 0) {
startpos = getParamStartPos(string, indexFind - 1);
if (startpos < 0) return string;
}
return "";
const int endpos = getParamStartPos(string, indexFind);
String result = (endpos <= 0) ? string.substring(startpos) : string.substring(startpos, endpos - 1);
result.toLowerCase();
return result;
}
/*********************************************************************************************\
Parse a string and get the xth command or parameter
\*********************************************************************************************/
int getParamStartPos(String& string, byte indexFind)
int getParamStartPos(const String& string, byte indexFind)
{
String tmpString = string;
byte count = 0;
tmpString.replace(' ', ',');
for (unsigned int x = 0; x < tmpString.length(); x++)
if (indexFind == 0) return 0;
byte count = 1;
const unsigned int strlength = string.length();
if (strlength <= indexFind) return -1;
for (unsigned int x = 0; x < (strlength - 1); ++x)
{
if (tmpString.charAt(x) == ',')
const char c = string.charAt(x);
if (c == ',' || c == ' ')
{
count++;
if (count == (indexFind - 1))
if (count == indexFind) {
return x + 1;
}
++count;
}
}
return -1;
@@ -386,6 +381,7 @@ void parseSpecialCharacters(String& s, boolean useURLencode)
// Simple macro to create the replacement string only when needed.
#define SMART_REPL(T,S) if (s.indexOf(T) != -1) { repl((T), (S), s, useURLencode);}
#define SMART_REPL_T(T,S) if (s.indexOf(T) != -1) { (S((T), s, useURLencode));}
void parseSystemVariables(String& s, boolean useURLencode)
{
parseSpecialCharacters(s, useURLencode);
@@ -438,8 +434,8 @@ void parseSystemVariables(String& s, boolean useURLencode)
SMART_REPL(F("%lcltime_am%"), getDateTimeString_ampm('-',':',' '))
SMART_REPL(F("%uptime%"), String(wdcounter / 2))
SMART_REPL(F("%unixtime%"), String(getUnixTime()))
SMART_REPL(F("%sunrise%"), getSunriseTimeString(':'))
SMART_REPL(F("%sunset%"), getSunsetTimeString(':'))
SMART_REPL_T(F("%sunset"), replSunSetTimeString)
SMART_REPL_T(F("%sunrise"), replSunRiseTimeString)
repl(F("%tskname%"), ExtraTaskSettings.TaskDeviceName, s, useURLencode);
if (s.indexOf(F("%vname")) != -1) {
@@ -450,6 +446,28 @@ void parseSystemVariables(String& s, boolean useURLencode)
}
}
String getReplacementString(const String& format, String& s) {
int startpos = s.indexOf(format);
int endpos = s.indexOf('%', startpos + 1);
String R = s.substring(startpos, endpos + 1);
String log = F("ReplacementString SunTime: ");
log += R;
log += F(" offset: ");
log += getSecOffset(R);
addLog(LOG_LEVEL_DEBUG, log);
return R;
}
void replSunRiseTimeString(const String& format, String& s, boolean useURLencode) {
String R = getReplacementString(format, s);
repl(R, getSunriseTimeString(':', getSecOffset(R)), s, useURLencode);
}
void replSunSetTimeString(const String& format, String& s, boolean useURLencode) {
String R = getReplacementString(format, s);
repl(R, getSunsetTimeString(':', getSecOffset(R)), s, useURLencode);
}
void parseEventVariables(String& s, struct EventStruct *event, boolean useURLencode)
{
SMART_REPL(F("%id%"), String(event->idx))
@@ -464,6 +482,7 @@ void parseEventVariables(String& s, struct EventStruct *event, boolean useURLenc
}
}
}
#undef SMART_REPL_T
#undef SMART_REPL
bool getConvertArgument(const String& marker, const String& s, float& argument, int& startIndex, int& endIndex) {
+70 -7
View File
@@ -17,6 +17,7 @@ uint32_t syncInterval = 3600; // time sync will be attempted after this many se
uint32_t sysTime = 0;
uint32_t prevMillis = 0;
uint32_t nextSyncTime = 0;
timeStruct tsRise, tsSet;
timeStruct sunRise;
timeStruct sunSet;
@@ -62,7 +63,6 @@ void calcSunRiseAndSet() {
float da = diurnalArc(dec, Settings.Latitude);
float rise = 12 - da - eqt - Settings.Longitude / 15.0;
float set = 12 + da - eqt - Settings.Longitude / 15.0;
timeStruct tsRise, tsSet;
tsRise.Hour = (int)rise;
tsRise.Minute = (rise - (int)rise) * 60.0;
tsSet.Hour = (int)set;
@@ -74,6 +74,25 @@ void calcSunRiseAndSet() {
breakTime(toLocal(makeTime(tsSet)), sunSet);
}
timeStruct getSunRise(int secOffset) {
return addSeconds(tsRise, secOffset, true);
}
timeStruct getSunSet(int secOffset) {
return addSeconds(tsSet, secOffset, true);
}
timeStruct addSeconds(const timeStruct& ts, int seconds, bool toLocalTime) {
unsigned long time = makeTime(ts);
time += seconds;
if (toLocalTime) {
time = toLocal(time);
}
timeStruct result;
breakTime(time, result);
return result;
}
void breakTime(unsigned long timeInput, struct timeStruct &tm) {
uint8_t year;
uint8_t month, monthLength;
@@ -142,6 +161,30 @@ uint32_t getUnixTime() {
return sysTime;
}
int getSecOffset(const String& format) {
int position_minus = format.indexOf('-');
int position_plus = format.indexOf('+');
if (position_minus == -1 && position_plus == -1)
return 0;
int sign_position = _max(position_minus, position_plus);
int position_percent = format.indexOf('%', sign_position);
if (position_percent == -1) {
return 0;
}
String valueStr = getNumerical(format.substring(sign_position, position_percent), true);
if (!isInt(valueStr)) return 0;
int value = valueStr.toInt();
switch (format.charAt(position_percent - 1)) {
case 'm':
case 'M':
return value * 60;
case 'h':
case 'H':
return value * 3600;
}
return value;
}
String getSunriseTimeString(char delimiter) {
return getTimeString(sunRise, delimiter, false, false);
}
@@ -150,6 +193,19 @@ String getSunsetTimeString(char delimiter) {
return getTimeString(sunSet, delimiter, false, false);
}
String getSunriseTimeString(char delimiter, int secOffset) {
if (secOffset == 0)
return getSunriseTimeString(delimiter);
return getTimeString(getSunRise(secOffset), delimiter, false, false);
}
String getSunsetTimeString(char delimiter, int secOffset) {
if (secOffset == 0)
return getSunsetTimeString(delimiter);
return getTimeString(getSunSet(secOffset), delimiter, false, false);
}
unsigned long now() {
// calculate number of seconds passed since last call to now()
bool timeSynced = false;
@@ -331,16 +387,17 @@ unsigned long getNtpTime()
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
log = F("NTP : NTP replied: ");
log += timePassedSince(beginWait);
log += F(" mSec");
addLog(LOG_LEVEL_DEBUG_MORE, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) {
String log = F("NTP : NTP replied: ");
log += timePassedSince(beginWait);
log += F(" mSec");
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
return secsSince1900 - 2208988800UL;
}
delay(10);
}
log = F("NTP : No reply");
addLog(LOG_LEVEL_DEBUG_MORE, log);
addLog(LOG_LEVEL_DEBUG_MORE, F("NTP : No reply"));
return 0;
}
@@ -355,6 +412,7 @@ unsigned long getNtpTime()
// Returned value is positive when "next" is after "prev"
long timeDiff(const unsigned long prev, const unsigned long next)
{
unsigned long start = ESP.getCycleCount();
long signed_diff = 0;
// To cast a value to a signed long, the difference may not exceed half the ULONG_MAX
const unsigned long half_max_unsigned_long = 2147483647u; // = 2^31 -1
@@ -381,6 +439,11 @@ long timeDiff(const unsigned long prev, const unsigned long next)
signed_diff = static_cast<long>((ULONG_MAX - prev) + next + 1u);
}
}
unsigned long end = ESP.getCycleCount();
if (end > start) {
++timediff_calls;
timediff_cpu_cycles_total += (end - start);
}
return signed_diff;
}
+164 -64
View File
@@ -149,15 +149,16 @@ public:
sendContentBlocking(buf);
finalRam = ESP.getFreeHeap();
/*
String log = String("Ram usage: Webserver only: ") + maxServerUsage +
" including Core: " + maxCoreUsage +
" flashStringCalls: " + flashStringCalls +
" flashStringData: " + flashStringData;
addLog(LOG_LEVEL_DEBUG, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
String log = String("Ram usage: Webserver only: ") + maxServerUsage +
" including Core: " + maxCoreUsage +
" flashStringCalls: " + flashStringCalls +
" flashStringData: " + flashStringData;
addLog(LOG_LEVEL_DEBUG, log);
}
*/
} else {
String log = String("Webpage skipped: low memory: ") + finalRam;
addLog(LOG_LEVEL_DEBUG, log);
addLog(LOG_LEVEL_DEBUG, String("Webpage skipped: low memory: ") + finalRam);
lowMemorySkip = false;
}
}
@@ -167,8 +168,7 @@ void sendContentBlocking(String& data) {
checkRAM(F("sendContentBlocking"));
uint32_t freeBeforeSend = ESP.getFreeHeap();
const uint32_t length = data.length();
String log = String("sendcontent free: ") + freeBeforeSend + " chunk size:" + length;
addLog(LOG_LEVEL_DEBUG_DEV, log);
addLog(LOG_LEVEL_DEBUG_DEV, String("sendcontent free: ") + freeBeforeSend + " chunk size:" + length);
freeBeforeSend = ESP.getFreeHeap();
if (TXBuffer.beforeTXRam > freeBeforeSend)
TXBuffer.beforeTXRam = freeBeforeSend;
@@ -355,11 +355,13 @@ boolean clientIPallowed()
String response = F("IP blocked: ");
response += formatIP(client.remoteIP());
WebServer.send(403, "text/html", response);
response += F(" Allowed: ");
response += formatIP(low);
response += F(" - ");
response += formatIP(high);
addLog(LOG_LEVEL_ERROR, response);
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
response += F(" Allowed: ");
response += formatIP(low);
response += F(" - ");
response += formatIP(high);
addLog(LOG_LEVEL_ERROR, response);
}
return false;
}
@@ -727,9 +729,11 @@ void getWebPageTemplateVar(const String& varName )
else
{
String log = F("Templ: Unknown Var : ");
log += varName;
addLog(LOG_LEVEL_ERROR, log);
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
String log = F("Templ: Unknown Var : ");
log += varName;
addLog(LOG_LEVEL_ERROR, log);
}
//no return string - eat var name
}
@@ -747,10 +751,12 @@ void writeDefaultCSS(void)
fs::File f = SPIFFS.open(F("esp.css"), "w");
if (f)
{
String log = F("CSS : Writing default CSS file to SPIFFS (");
log += defaultCSS.length();
log += F(" bytes)");
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("CSS : Writing default CSS file to SPIFFS (");
log += defaultCSS.length();
log += F(" bytes)");
addLog(LOG_LEVEL_INFO, log);
}
defaultCSS= PGMT(pgDefaultCSS);
f.write((const unsigned char*)defaultCSS.c_str(), defaultCSS.length()); //note: content must be in RAM - a write of F("XXX") does not work
f.close();
@@ -939,21 +945,18 @@ void handle_root() {
// disconnect here could result into a crash/reboot...
if (strcasecmp_P(sCommand.c_str(), PSTR("wifidisconnect")) == 0)
{
String log = F("WIFI : Disconnecting...");
addLog(LOG_LEVEL_INFO, log);
addLog(LOG_LEVEL_INFO, F("WIFI : Disconnecting..."));
cmd_within_mainloop = CMD_WIFI_DISCONNECT;
}
if (strcasecmp_P(sCommand.c_str(), PSTR("reboot")) == 0)
{
String log = F(" : Rebooting...");
addLog(LOG_LEVEL_INFO, log);
addLog(LOG_LEVEL_INFO, F(" : Rebooting..."));
cmd_within_mainloop = CMD_REBOOT;
}
if (strcasecmp_P(sCommand.c_str(), PSTR("reset")) == 0)
{
String log = F(" : factory reset...");
addLog(LOG_LEVEL_INFO, log);
addLog(LOG_LEVEL_INFO, F(" : factory reset..."));
cmd_within_mainloop = CMD_REBOOT;
TXBuffer+= F("OK. Please wait > 1 min and connect to Acces point.<BR><BR>PW=configesp<BR>URL=<a href='http://192.168.4.1'>192.168.4.1</a>");
TXBuffer.endStream();
@@ -2280,9 +2283,11 @@ void handle_devices() {
checkRAM(F("handle_devices"));
String log = F("DEBUG: String size:");
log += String(TXBuffer.sentBytes);
addLog(LOG_LEVEL_DEBUG_DEV, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_DEV)) {
String log = F("DEBUG: String size:");
log += String(TXBuffer.sentBytes);
addLog(LOG_LEVEL_DEBUG_DEV, log);
}
sendHeadandTail(F("TmplStd"),_TAIL);
TXBuffer.endStream();
}
@@ -3607,6 +3612,7 @@ void stream_last_json_object_value(const String& object, const String& value) {
void handle_json()
{
const int taskNr = getFormItemInt(F("tasknr"), -1);
const bool showSpecificTask = taskNr > 0;
bool showSystem = true;
bool showWifi = true;
bool showDataAcquisition = true;
@@ -3623,7 +3629,7 @@ void handle_json()
}
}
TXBuffer.startJsonStream();
if (taskNr == -1)
if (!showSpecificTask)
{
TXBuffer += '{';
if (showSystem) {
@@ -3675,7 +3681,7 @@ void handle_json()
byte firstTaskIndex = 0;
byte lastTaskIndex = TASKS_MAX - 1;
if (taskNr > 0 )
if (showSpecificTask)
{
firstTaskIndex = taskNr - 1;
lastTaskIndex = taskNr - 1;
@@ -3686,7 +3692,7 @@ void handle_json()
lastActiveTaskIndex = TaskIndex;
}
if (taskNr == 0 ) TXBuffer += F("\"Sensors\":[\n");
if (!showSpecificTask) TXBuffer += F("\"Sensors\":[\n");
unsigned long ttl_json = 60; // The shortest interval per enabled task (with output values) in seconds
for (byte TaskIndex = firstTaskIndex; TaskIndex <= lastActiveTaskIndex; TaskIndex++)
{
@@ -3714,7 +3720,7 @@ void handle_json()
}
TXBuffer += F("],\n");
}
if (taskNr != 0) {
if (showSpecificTask) {
stream_next_json_object_value(F("TTL"), String(ttl_json * 1000));
}
if (showDataAcquisition) {
@@ -3742,7 +3748,7 @@ void handle_json()
TXBuffer += F("\n");
}
}
if (taskNr == 0) {
if (!showSpecificTask) {
TXBuffer += F("],\n");
stream_last_json_object_value(F("TTL"), String(ttl_json * 1000));
}
@@ -3790,12 +3796,13 @@ void handle_advanced() {
if (dst_end.isValid()) { Settings.DST_End = dst_end.toFlashStoredValue(); }
str2ip(syslogip.c_str(), Settings.Syslog_IP);
Settings.UDPPort = getFormItemInt(F("udpport"));
Settings.SyslogLevel = getFormItemInt(F("sysloglevel"));
Settings.SyslogFacility = getFormItemInt(F("syslogfacility"));
Settings.UseSerial = isFormItemChecked(F("useserial"));
Settings.SerialLogLevel = getFormItemInt(F("serialloglevel"));
Settings.WebLogLevel = getFormItemInt(F("webloglevel"));
Settings.SDLogLevel = getFormItemInt(F("sdloglevel"));
setLogLevelFor(LOG_TO_SYSLOG, getFormItemInt(F("sysloglevel")));
setLogLevelFor(LOG_TO_SERIAL, getFormItemInt(F("serialloglevel")));
setLogLevelFor(LOG_TO_WEBLOG, getFormItemInt(F("webloglevel")));
setLogLevelFor(LOG_TO_SDCARD, getFormItemInt(F("sdloglevel")));
Settings.UseValueLogger = isFormItemChecked(F("valuelogger"));
Settings.BaudRate = getFormItemInt(F("baudrate"));
Settings.UseNTP = isFormItemChecked(F("usentp"));
@@ -4088,7 +4095,6 @@ void handleFileUpload() {
if (!isLoggedIn()) return;
static boolean valid = false;
String log = "";
HTTPUpload& upload = WebServer.upload();
@@ -4100,9 +4106,11 @@ void handleFileUpload() {
if (upload.status == UPLOAD_FILE_START)
{
log = F("Upload: START, filename: ");
log += upload.filename;
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("Upload: START, filename: ");
log += upload.filename;
addLog(LOG_LEVEL_INFO, log);
}
valid = false;
uploadResult = 0;
}
@@ -4139,16 +4147,20 @@ void handleFileUpload() {
}
}
if (uploadFile) uploadFile.write(upload.buf, upload.currentSize);
log = F("Upload: WRITE, Bytes: ");
log += upload.currentSize;
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("Upload: WRITE, Bytes: ");
log += upload.currentSize;
addLog(LOG_LEVEL_INFO, log);
}
}
else if (upload.status == UPLOAD_FILE_END)
{
if (uploadFile) uploadFile.close();
log = F("Upload: END, Size: ");
log += upload.totalSize;
addLog(LOG_LEVEL_INFO, log);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("Upload: END, Size: ");
log += upload.totalSize;
addLog(LOG_LEVEL_INFO, log);
}
}
if (valid)
@@ -4182,8 +4194,11 @@ bool loadFromFS(boolean spiffs, String path) {
else if (path.endsWith(F(".txt"))) dataType = F("application/octet-stream");
else if (path.endsWith(F(".dat"))) dataType = F("application/octet-stream");
else if (path.endsWith(F(".esp"))) return handle_custom(path);
String log = F("HTML : Request file ");
log += path;
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
String log = F("HTML : Request file ");
log += path;
addLog(LOG_LEVEL_DEBUG, log);
}
path = path.substring(1);
if (spiffs)
@@ -4215,8 +4230,6 @@ bool loadFromFS(boolean spiffs, String path) {
#endif
}
statusLED(true);
addLog(LOG_LEVEL_DEBUG, log);
return true;
}
@@ -4689,9 +4702,11 @@ void handle_setup() {
strncpy(SecuritySettings.WifiKey, password.c_str(), sizeof(SecuritySettings.WifiKey));
strncpy(SecuritySettings.WifiSSID, ssid.c_str(), sizeof(SecuritySettings.WifiSSID));
wifiSetupConnect = true;
String reconnectlog = F("WIFI : Credentials Changed, retry connection. SSID: ");
reconnectlog += ssid;
addLog(LOG_LEVEL_INFO, reconnectlog);
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String reconnectlog = F("WIFI : Credentials Changed, retry connection. SSID: ");
reconnectlog += ssid;
addLog(LOG_LEVEL_INFO, reconnectlog);
}
status = 1;
refreshCount = 0;
}
@@ -5222,15 +5237,15 @@ void handle_sysinfo() {
addHelpButton(F("https://dl.espressif.com/doc/esp-idf/latest/api-guides/partition-tables.html"));
TXBuffer += F("</H3></TD></TR>");
TXBuffer += F("<TR><TD>Data Partition Table<TD><tt>");
TXBuffer += getPartitionTableHeader(F(" - "), F("<BR>"));
TXBuffer += getPartitionTable(ESP_PARTITION_TYPE_DATA, F(" - "), F("<BR>"));
TXBuffer += F("</tt>");
TXBuffer += F("<TR><TD>Data Partition Table<TD>");
// TXBuffer += getPartitionTableHeader(F(" - "), F("<BR>"));
// TXBuffer += getPartitionTable(ESP_PARTITION_TYPE_DATA, F(" - "), F("<BR>"));
getPartitionTableSVG(ESP_PARTITION_TYPE_DATA, 0x5856e6);
TXBuffer += F("<TR><TD>App Partition Table<TD><tt>");
TXBuffer += getPartitionTableHeader(F(" - "), F("<BR>"));
TXBuffer += getPartitionTable(ESP_PARTITION_TYPE_APP , F(" - "), F("<BR>"));
TXBuffer += F("</tt>");
TXBuffer += F("<TR><TD>App Partition Table<TD>");
// TXBuffer += getPartitionTableHeader(F(" - "), F("<BR>"));
// TXBuffer += getPartitionTable(ESP_PARTITION_TYPE_APP , F(" - "), F("<BR>"));
getPartitionTableSVG(ESP_PARTITION_TYPE_APP, 0xab56e6);
#endif
TXBuffer += F("</table></form>");
@@ -5286,3 +5301,88 @@ void handle_favicon() {
checkRAM(F("handle_favicon"));
WebServer.send_P(200, PSTR("image/x-icon"), favicon_8b_ico, favicon_8b_ico_len);
}
#ifdef ESP32
void createSvgRectPath(unsigned int color, int xoffset, int yoffset, int size, int height, int range, float svgBarWidth) {
float width = svgBarWidth * size / range;
if (width < 2) width = 2;
TXBuffer += formatToHex(color, F("<path fill=\"#"));
TXBuffer += F("\" d=\"M");
TXBuffer += toString(svgBarWidth * xoffset / range, 2);
TXBuffer += ' ';
TXBuffer += yoffset;
TXBuffer += 'h';
TXBuffer += toString(width, 2);
TXBuffer += 'v';
TXBuffer += height;
TXBuffer += 'H';
TXBuffer += toString(svgBarWidth * xoffset / range, 2);
TXBuffer += F("z\"/>\n");
}
int getPartionCount(byte pType) {
esp_partition_type_t partitionType = static_cast<esp_partition_type_t>(pType);
esp_partition_iterator_t _mypartiterator = esp_partition_find(partitionType, ESP_PARTITION_SUBTYPE_ANY, NULL);
int nrPartitions = 0;
if (_mypartiterator) {
do {
++nrPartitions;
} while ((_mypartiterator = esp_partition_next(_mypartiterator)) != NULL);
}
esp_partition_iterator_release(_mypartiterator);
return nrPartitions;
}
void createSvgTextElement(const String& text, float textXoffset, float textYoffset) {
TXBuffer += F("<text style=\"line-height:1.25\" x=\"");
TXBuffer += toString(textXoffset, 2);
TXBuffer += F("\" y=\"");
TXBuffer += toString(textYoffset, 2);
TXBuffer += F("\" stroke-width=\".3\" font-family=\"sans-serif\" font-size=\"8\" letter-spacing=\"0\" word-spacing=\"0\">\n");
TXBuffer += F("<tspan x=\"");
TXBuffer += toString(textXoffset, 2);
TXBuffer += F("\" y=\"");
TXBuffer += toString(textYoffset, 2);
TXBuffer += F("\">");
TXBuffer += text;
TXBuffer += F("</tspan>\n</text>");
}
void getPartitionTableSVG(byte pType, unsigned int partitionColor) {
int nrPartitions = getPartionCount(pType);
if (nrPartitions == 0) return;
const int barHeight = 16;
const int svgBarWidth = 200;
const int shiftY = 2;
uint32_t realSize = getFlashRealSizeInBytes();
esp_partition_type_t partitionType = static_cast<esp_partition_type_t>(pType);
const esp_partition_t * _mypart;
esp_partition_iterator_t _mypartiterator = esp_partition_find(partitionType, ESP_PARTITION_SUBTYPE_ANY, NULL);
TXBuffer += F("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"500\" height=\"");
TXBuffer += nrPartitions * barHeight + shiftY;
TXBuffer += F("\">");
int partNr = 0;
if (_mypartiterator) {
do {
_mypart = esp_partition_get(_mypartiterator);
float yOffset = partNr * barHeight + shiftY;
createSvgRectPath(0xcdcdcd, 0, yOffset, realSize, barHeight - 2, realSize, svgBarWidth);
createSvgRectPath(partitionColor, _mypart->address, yOffset, _mypart->size, barHeight - 2, realSize, svgBarWidth);
float textXoffset = svgBarWidth + 2;
float textYoffset = yOffset + 0.9 * barHeight;
createSvgTextElement(formatHumanReadable(_mypart->size, 1024), textXoffset, textYoffset);
textXoffset = svgBarWidth + 60;
createSvgTextElement(_mypart->label, textXoffset, textYoffset);
textXoffset = svgBarWidth + 130;
createSvgTextElement(getPartitionType(_mypart->type, _mypart->subtype), textXoffset, textYoffset);
++partNr;
} while ((_mypartiterator = esp_partition_next(_mypartiterator)) != NULL);
}
TXBuffer += F("</svg>\n");
esp_partition_iterator_release(_mypartiterator);
}
#endif
+1 -1
View File
@@ -504,7 +504,7 @@ static const char jsFetchAndParseLog[] PROGMEM = {
"if (logEntriesChunk == null) {"
"logEntriesChunk = '';"
"}"
"for (c = 0; c < data.Log.nrEntries + 1; c++) {"
"for (c = 0; c < data.Log.nrEntries; ++c) {"
"try {"
"logEntry = data.Log.Entries[c].timestamp;"
"} catch (err) {"
+16 -8
View File
@@ -59,8 +59,10 @@ boolean CPlugin_004(byte function, struct EventStruct *event, String& string)
if (!ControllerSettings.connectToHost(client))
{
connectionFailures++;
strcpy_P(log, PSTR("HTTP : connection failed"));
addLog(LOG_LEVEL_ERROR, log);
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
strcpy_P(log, PSTR("HTTP : connection failed"));
addLog(LOG_LEVEL_ERROR, log);
}
return false;
}
statusLED(true);
@@ -107,18 +109,24 @@ boolean CPlugin_004(byte function, struct EventStruct *event, String& string)
String line;
safeReadStringUntil(client, line, '\n');
line.toCharArray(log, 80);
addLog(LOG_LEVEL_DEBUG_MORE, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) {
line.toCharArray(log, 80);
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
if (line.substring(0, 15) == F("HTTP/1.1 200 OK"))
{
strcpy_P(log, PSTR("HTTP : Success!"));
addLog(LOG_LEVEL_DEBUG, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
strcpy_P(log, PSTR("HTTP : Success!"));
addLog(LOG_LEVEL_DEBUG, log);
}
success = true;
}
delay(1);
}
strcpy_P(log, PSTR("HTTP : closing connection"));
addLog(LOG_LEVEL_DEBUG, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
strcpy_P(log, PSTR("HTTP : closing connection"));
addLog(LOG_LEVEL_DEBUG, log);
}
client.flush();
client.stop();
+4 -2
View File
@@ -102,8 +102,10 @@ boolean CPlugin_007(byte function, struct EventStruct *event, String& string)
String line;
safeReadStringUntil(client, line, '\n');
line.toCharArray(log, 80);
addLog(LOG_LEVEL_DEBUG_MORE, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) {
line.toCharArray(log, 80);
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
if (line.substring(0, 15) == F("HTTP/1.1 200 OK"))
{
strcpy_P(log, PSTR("HTTP : Success!"));
+5 -4
View File
@@ -71,7 +71,6 @@ void C010_Send(struct EventStruct *event, byte varIndex, const String& formatted
ControllerSettingsStruct ControllerSettings;
LoadControllerSettings(event->ControllerIndex, (byte*)&ControllerSettings, sizeof(ControllerSettings));
char log[80];
// boolean success = false;
addLog(LOG_LEVEL_DEBUG, String(F("UDP : sending to ")) + ControllerSettings.getHostPortString());
statusLED(true);
@@ -91,8 +90,10 @@ void C010_Send(struct EventStruct *event, byte varIndex, const String& formatted
portUDP.endPacket();
}
msg.toCharArray(log, 80);
addLog(LOG_LEVEL_DEBUG_MORE, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) {
char log[80];
msg.toCharArray(log, 80);
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
}
#endif
+14 -11
View File
@@ -180,9 +180,11 @@ void C013_sendUDP(byte unit, byte* data, byte size)
if (unit != 255)
if (Nodes[unit].ip[0] == 0)
return;
String log = F("C013 : Send UDP message to ");
log += unit;
addLog(LOG_LEVEL_DEBUG_MORE, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) {
String log = F("C013 : Send UDP message to ");
log += unit;
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
statusLED(true);
@@ -197,16 +199,17 @@ void C013_sendUDP(byte unit, byte* data, byte size)
}
void C013_Receive(struct EventStruct *event) {
if (event->Data[1] > 1 && event->Data[1] < 6)
{
String log = (F("C013 : msg "));
for (byte x = 1; x < 6; x++)
if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) {
if (event->Data[1] > 1 && event->Data[1] < 6)
{
log += " ";
log += (int)event->Data[x];
String log = (F("C013 : msg "));
for (byte x = 1; x < 6; x++)
{
log += " ";
log += (int)event->Data[x];
}
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
switch (event->Data[1]) {
+8 -4
View File
@@ -324,11 +324,15 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
success = true;
if (event->Par1 >= 0 && event->Par1 <= PIN_D_MAX)
{
const bool pinStateHigh = event->Par2 != 0;
const uint16_t pinStateValue = pinStateHigh ? 1 : 0;
const uint16_t inversePinStateValue = pinStateHigh ? 0 : 1;
pinMode(event->Par1, OUTPUT);
digitalWrite(event->Par1, event->Par2);
setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_OUTPUT, event->Par2);
setSystemTimer(time_in_msec ? event->Par3 : event->Par3 * 1000,
PLUGIN_ID_001, event->Par1, !event->Par2, 0);
digitalWrite(event->Par1, pinStateValue);
setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_OUTPUT, pinStateValue);
unsigned long timer = time_in_msec ? event->Par3 : event->Par3 * 1000;
// Create a future system timer call to set the GPIO pin back to its normal value.
setSystemTimer(timer, PLUGIN_ID_001, event->TaskIndex, event->Par1, inversePinStateValue);
log = String(F("SW : GPIO ")) + String(event->Par1) +
String(F(" Pulse set for ")) + String(event->Par3) + String(time_in_msec ? F(" msec") : F(" sec"));
addLog(LOG_LEVEL_INFO, log);
+1 -1
View File
@@ -146,7 +146,7 @@ boolean Plugin_009(byte function, struct EventStruct *event, String& string)
{
Plugin_009_Write(event->Par1, event->Par2);
setPinState(PLUGIN_ID_009, event->Par1, PIN_MODE_OUTPUT, event->Par2);
setSystemTimer(event->Par3 * 1000, PLUGIN_ID_009, event->Par1, !event->Par2, 0);
setSystemTimer(event->Par3 * 1000, PLUGIN_ID_009, event->TaskIndex, event->Par1, !event->Par2);
log = String(F("MCP : GPIO ")) + String(event->Par1) + String(F(" Pulse set for ")) + String(event->Par3) + String(F(" S"));
addLog(LOG_LEVEL_INFO, log);
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_009, event->Par1, log, 0));
+1 -1
View File
@@ -123,7 +123,7 @@ boolean Plugin_011(byte function, struct EventStruct *event, String& string)
if (event->Par1 >= 0 && event->Par1 <= 13)
{
Plugin_011_Write(event->Par1, event->Par2);
setSystemTimer(event->Par3 * 1000, PLUGIN_ID_011, event->Par1, !event->Par2, 0);
setSystemTimer(event->Par3 * 1000, PLUGIN_ID_011, event->TaskIndex, event->Par1, !event->Par2);
setPinState(PLUGIN_ID_011, event->Par1, PIN_MODE_OUTPUT, event->Par2);
log = String(F("PME : GPIO ")) + String(event->Par1) + String(F(" Pulse set for ")) + String(event->Par3) + String(F(" S"));
addLog(LOG_LEVEL_INFO, log);
+1 -1
View File
@@ -145,7 +145,7 @@ boolean Plugin_019(byte function, struct EventStruct *event, String& string)
success = true;
Plugin_019_Write(event->Par1, event->Par2);
setPinState(PLUGIN_ID_019, event->Par1, PIN_MODE_OUTPUT, event->Par2);
setSystemTimer(event->Par3 * 1000, PLUGIN_ID_019, event->Par1, !event->Par2, 0);
setSystemTimer(event->Par3 * 1000, PLUGIN_ID_019, event->TaskIndex, event->Par1, !event->Par2);
log = String(F("PCF : GPIO ")) + String(event->Par1) + String(F(" Pulse set for ")) + String(event->Par3) + String(F(" S"));
addLog(LOG_LEVEL_INFO, log);
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_019, event->Par1, log, 0));
+55 -39
View File
@@ -312,26 +312,28 @@ boolean Plugin_028(byte function, struct EventStruct *event, String& string)
} else {
UserVar[event->BaseVarIndex + 2] = sensor.last_press_val;
}
String log;
log.reserve(40); // Prevent re-allocation
log = sensor.getDeviceName();
log += F(" : Address: 0x");
log += String(i2cAddress,HEX);
addLog(LOG_LEVEL_INFO, log);
log = sensor.getDeviceName();
log += F(" : Temperature: ");
log += UserVar[event->BaseVarIndex];
addLog(LOG_LEVEL_INFO, log);
if (sensor.hasHumidity()) {
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log;
log.reserve(40); // Prevent re-allocation
log = sensor.getDeviceName();
log += F(" : Humidity: ");
log += UserVar[event->BaseVarIndex + 1];
log += F(" : Address: 0x");
log += String(i2cAddress,HEX);
addLog(LOG_LEVEL_INFO, log);
log = sensor.getDeviceName();
log += F(" : Temperature: ");
log += UserVar[event->BaseVarIndex];
addLog(LOG_LEVEL_INFO, log);
if (sensor.hasHumidity()) {
log = sensor.getDeviceName();
log += F(" : Humidity: ");
log += UserVar[event->BaseVarIndex + 1];
addLog(LOG_LEVEL_INFO, log);
}
log = sensor.getDeviceName();
log += F(" : Barometric Pressure: ");
log += UserVar[event->BaseVarIndex + 2];
addLog(LOG_LEVEL_INFO, log);
}
log = sensor.getDeviceName();
log += F(" : Barometric Pressure: ");
log += UserVar[event->BaseVarIndex + 2];
addLog(LOG_LEVEL_INFO, log);
success = true;
break;
}
@@ -395,9 +397,11 @@ bool Plugin_028_update_measurements(const uint8_t i2cAddress, float tempOffset)
String log;
log.reserve(120); // Prevent re-allocation
log = sensor.getDeviceName();
log += F(":");
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
log.reserve(120); // Prevent re-allocation
log = sensor.getDeviceName();
log += F(":");
}
boolean logAdded = false;
if (sensor.hasHumidity()) {
// Apply half of the temp offset, to correct the dew point offset.
@@ -409,34 +413,46 @@ bool Plugin_028_update_measurements(const uint8_t i2cAddress, float tempOffset)
}
if (tempOffset > 0.1 || tempOffset < -0.1) {
// There is some offset to apply.
log += F(" Apply temp offset ");
log += tempOffset;
log += F("C");
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
log += F(" Apply temp offset ");
log += tempOffset;
log += F("C");
}
if (sensor.hasHumidity()) {
log += F(" humidity ");
log += sensor.last_hum_val;
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
log += F(" humidity ");
log += sensor.last_hum_val;
}
sensor.last_hum_val = compute_humidity_from_dewpoint(sensor.last_temp_val + tempOffset, sensor.last_dew_temp_val);
log += F("% => ");
log += sensor.last_hum_val;
log += F("%");
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
log += F("% => ");
log += sensor.last_hum_val;
log += F("%");
}
} else {
sensor.last_hum_val = 0.0;
}
log += F(" temperature ");
log += sensor.last_temp_val;
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
log += F(" temperature ");
log += sensor.last_temp_val;
}
sensor.last_temp_val = sensor.last_temp_val + tempOffset;
log += F("C => ");
log += sensor.last_temp_val;
log += F("C");
logAdded = true;
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
log += F("C => ");
log += sensor.last_temp_val;
log += F("C");
logAdded = true;
}
}
if (sensor.hasHumidity()) {
log += F(" dew point ");
log += sensor.last_dew_temp_val;
log += F("C");
logAdded = true;
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
log += F(" dew point ");
log += sensor.last_dew_temp_val;
log += F("C");
logAdded = true;
}
}
if (logAdded)
if (logAdded && loglevelActiveFor(LOG_LEVEL_INFO))
addLog(LOG_LEVEL_INFO, log);
return true;
}
+2 -1
View File
@@ -168,7 +168,8 @@ boolean Plugin_036(byte function, struct EventStruct *event, String& string)
case PLUGIN_WEBFORM_SAVE:
{
//update now
timerSensor[event->TaskIndex] = millis() + (Settings.TaskDeviceTimer[event->TaskIndex] * 1000);
schedule_task_device_timer(event->TaskIndex,
millis() + (Settings.TaskDeviceTimer[event->TaskIndex] * 1000));
frameCounter=0;
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = getFormItemInt(F("plugin_036_adr"));
+7 -5
View File
@@ -167,11 +167,13 @@ boolean Plugin_048(byte function, struct EventStruct *event, String& string) {
Adafruit_StepperMotor *myStepper;
myStepper = AFMS.getStepper(Plugin_048_MotorStepsPerRevolution, param2.toInt());
myStepper->setSpeed(Plugin_048_StepperSpeed);
String log = F("MotorShield: StepsPerRevolution: ");
log += String(Plugin_048_MotorStepsPerRevolution);
log += F(" Stepperspeed: ");
log += String(Plugin_048_StepperSpeed);
addLog(LOG_LEVEL_DEBUG_MORE, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) {
String log = F("MotorShield: StepsPerRevolution: ");
log += String(Plugin_048_MotorStepsPerRevolution);
log += F(" Stepperspeed: ");
log += String(Plugin_048_StepperSpeed);
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
if (param3.equalsIgnoreCase(F("Forward")))
{
+1 -1
View File
@@ -247,7 +247,7 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
//delay first read, because hardware needs to initialize on cold boot
//otherwise we get a weird value or read error
timerSensor[event->TaskIndex] = millis() + 15000;
schedule_task_device_timer(event->TaskIndex, millis() + 15000);
Plugin_049_init = true;
success = true;
+35 -30
View File
@@ -100,7 +100,6 @@ boolean PacketAvailable(void)
}
boolean Plugin_053_process_data(struct EventStruct *event) {
String log;
uint16_t checksum = 0, checksum2 = 0;
uint16_t framelength = 0;
uint16 packet_header = 0;
@@ -113,9 +112,11 @@ boolean Plugin_053_process_data(struct EventStruct *event) {
SerialRead16(&framelength, &checksum);
if (framelength != (PMSx003_SIZE - 4))
{
log = F("PMSx003 : invalid framelength - ");
log += framelength;
addLog(LOG_LEVEL_ERROR, log);
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
String log = F("PMSx003 : invalid framelength - ");
log += framelength;
addLog(LOG_LEVEL_ERROR, log);
}
return false;
}
@@ -123,33 +124,37 @@ boolean Plugin_053_process_data(struct EventStruct *event) {
for (int i = 0; i < 13; i++)
SerialRead16(&data[i], &checksum);
log = F("PMSx003 : pm1.0=");
log += data[0];
log += F(", pm2.5=");
log += data[1];
log += F(", pm10=");
log += data[2];
log += F(", pm1.0a=");
log += data[3];
log += F(", pm2.5a=");
log += data[4];
log += F(", pm10a=");
log += data[5];
addLog(LOG_LEVEL_DEBUG, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
String log = F("PMSx003 : pm1.0=");
log += data[0];
log += F(", pm2.5=");
log += data[1];
log += F(", pm10=");
log += data[2];
log += F(", pm1.0a=");
log += data[3];
log += F(", pm2.5a=");
log += data[4];
log += F(", pm10a=");
log += data[5];
addLog(LOG_LEVEL_DEBUG, log);
}
log = F("PMSx003 : count/0.1L : 0.3um=");
log += data[6];
log += F(", 0.5um=");
log += data[7];
log += F(", 1.0um=");
log += data[8];
log += F(", 2.5um=");
log += data[9];
log += F(", 5.0um=");
log += data[10];
log += F(", 10um=");
log += data[11];
addLog(LOG_LEVEL_DEBUG_MORE, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) {
String log = F("PMSx003 : count/0.1L : 0.3um=");
log += data[6];
log += F(", 0.5um=");
log += data[7];
log += F(", 1.0um=");
log += data[8];
log += F(", 2.5um=");
log += data[9];
log += F(", 5.0um=");
log += data[10];
log += F(", 10um=");
log += data[11];
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
// Compare checksums
SerialRead16(&checksum2, NULL);
+8 -6
View File
@@ -160,13 +160,15 @@ boolean Plugin_054(byte function, struct EventStruct *event, String& string)
if (param == F("log"))
{
String log = F("DMX : ");
for (int16_t i = 0; i < Plugin_054_DMXSize; i++)
{
log += Plugin_054_DMXBuffer[i];
log += F(", ");
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("DMX : ");
for (int16_t i = 0; i < Plugin_054_DMXSize; i++)
{
log += Plugin_054_DMXBuffer[i];
log += F(", ");
}
addLog(LOG_LEVEL_INFO, log);
}
addLog(LOG_LEVEL_INFO, log);
success = true;
}
+11 -7
View File
@@ -215,9 +215,11 @@ boolean Plugin_055(byte function, struct EventStruct *event, String& string)
if (command == F("chime"))
{
int paramPos = getParamStartPos(string, 2);
String param = string.substring(paramPos);
Plugin_055_AddStringFIFO(param);
success = true;
if (paramPos >= 0) {
String param = string.substring(paramPos);
Plugin_055_AddStringFIFO(param);
success = true;
}
}
if (command == F("chimeplay"))
{
@@ -231,10 +233,12 @@ boolean Plugin_055(byte function, struct EventStruct *event, String& string)
{
String name = parseString(string, 2);
int paramPos = getParamStartPos(string, 3);
String param = string.substring(paramPos);
Plugin_055_WriteChime(name, param);
Plugin_055_AddStringFIFO(F("1"));
success = true;
if (paramPos >= 0) {
String param = string.substring(paramPos);
Plugin_055_WriteChime(name, param);
Plugin_055_AddStringFIFO(F("1"));
success = true;
}
}
break;
+28 -22
View File
@@ -1,4 +1,4 @@
#ifdef USES_P057
#ifdef USES_P057
//#######################################################################################################
//#################################### Plugin 057: HT16K33 LED ##########################################
//#######################################################################################################
@@ -157,25 +157,29 @@ boolean Plugin_057(byte function, struct EventStruct *event, String& string)
if (command == F("mprint"))
{
int paramPos = getParamStartPos(lowerString, 2);
String text = lowerString.substring(paramPos);
byte seg = 0;
if (paramPos >= 0) {
String text = lowerString.substring(paramPos);
byte seg = 0;
Plugin_057_M->ClearRowBuffer();
while (text[seg] && seg < 8)
{
// uint16_t value = 0;
char c = text[seg];
Plugin_057_M->SetDigit(seg, c);
seg++;
Plugin_057_M->ClearRowBuffer();
while (text[seg] && seg < 8)
{
// uint16_t value = 0;
char c = text[seg];
Plugin_057_M->SetDigit(seg, c);
seg++;
}
Plugin_057_M->TransmitRowBuffer();
success = true;
}
Plugin_057_M->TransmitRowBuffer();
success = true;
}
else if (command == F("mbr")) {
int paramPos = getParamStartPos(lowerString, 2);
uint8_t brightness = lowerString.substring(paramPos).toInt();
Plugin_057_M->SetBrightness(brightness);
success = true;
if (paramPos >= 0) {
uint8_t brightness = lowerString.substring(paramPos).toInt();
Plugin_057_M->SetBrightness(brightness);
success = true;
}
}
else if (command == F("m") || command == F("mx") || command == F("mnum"))
{
@@ -199,13 +203,15 @@ boolean Plugin_057(byte function, struct EventStruct *event, String& string)
if (param == F("log"))
{
String log = F("MX : ");
for (byte i = 0; i < 8; i++)
{
log += String(Plugin_057_M->GetRow(i), 16);
log += F("h, ");
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("MX : ");
for (byte i = 0; i < 8; i++)
{
log += String(Plugin_057_M->GetRow(i), 16);
log += F("h, ");
}
addLog(LOG_LEVEL_INFO, log);
}
addLog(LOG_LEVEL_INFO, log);
success = true;
}
@@ -323,4 +329,4 @@ boolean Plugin_057(byte function, struct EventStruct *event, String& string)
return success;
}
#endif // USES_P057
#endif // USES_P057
+247 -239
View File
@@ -27,7 +27,7 @@ boolean Plugin_077_init = false;
unsigned long energy_power_calibration = HLW_PREF_PULSE;
unsigned long energy_voltage_calibration = HLW_UREF_PULSE;
unsigned long energy_current_calibration = HLW_IREF_PULSE;
*/
*/
uint8_t cse_receive_flag = 0;
@@ -48,272 +48,280 @@ float energy_power = 0; // 123.1 W
boolean Plugin_077(byte function, struct EventStruct *event, String& string)
{
boolean success = false;
boolean success = false;
switch (function) {
case PLUGIN_DEVICE_ADD:
{
Device[++deviceCount].Number = PLUGIN_ID_077;
Device[deviceCount].VType = SENSOR_TYPE_QUAD;
Device[deviceCount].Ports = 0;
Device[deviceCount].PullUpOption = false;
Device[deviceCount].InverseLogicOption = false;
Device[deviceCount].FormulaOption = true;
Device[deviceCount].ValueCount = 4;
Device[deviceCount].SendDataOption = true;
Device[deviceCount].TimerOption = true;
Device[deviceCount].TimerOptional = true;
Device[deviceCount].GlobalSyncOption = true;
break;
}
case PLUGIN_GET_DEVICENAME:
{
string = F(PLUGIN_NAME_077);
break;
}
case PLUGIN_GET_DEVICEVALUENAMES:
{
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_077));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_077));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_077));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[3], PSTR(PLUGIN_VALUENAME4_077));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
addFormNumericBox(F("U Ref"), F("plugin_077_URef"), Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
addUnit(F("uSec"));
addFormNumericBox(F("I Ref"), F("plugin_077_IRef"), Settings.TaskDevicePluginConfig[event->TaskIndex][1]);
addUnit(F("uSec"));
addFormNumericBox(F("P Ref"), F("plugin_077_PRef"), Settings.TaskDevicePluginConfig[event->TaskIndex][2]);
addUnit(F("uSec"));
addFormNote(F("Use 0 to read values stored on chip / default values"));
success = true;
break;
}
case PLUGIN_WEBFORM_SAVE:
{
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = getFormItemInt(F("plugin_077_URef"));;
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = getFormItemInt(F("plugin_077_IRef"));
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = getFormItemInt(F("plugin_077_PRef"));
success = true;
break;
}
case PLUGIN_INIT:
{
Plugin_077_init = true;
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 0) Settings.TaskDevicePluginConfig[event->TaskIndex][0] = HLW_UREF_PULSE;
if (Settings.TaskDevicePluginConfig[event->TaskIndex][1] == 0) Settings.TaskDevicePluginConfig[event->TaskIndex][1] = HLW_IREF_PULSE;
if (Settings.TaskDevicePluginConfig[event->TaskIndex][2] == 0) Settings.TaskDevicePluginConfig[event->TaskIndex][2] = HLW_PREF_PULSE;
Settings.UseSerial = true; // Enable Serial port
Settings.SerialLogLevel = 0; // disable logging on serial port (used for CSE7766 communication)
Settings.BaudRate = 4800; // set BaudRate for CSE7766
Serial.flush();
Serial.begin(Settings.BaudRate);
success = true;
break;
}
/* currently not needed!
case PLUGIN_TEN_PER_SECOND:
switch (function) {
case PLUGIN_DEVICE_ADD:
{
Device[++deviceCount].Number = PLUGIN_ID_077;
Device[deviceCount].VType = SENSOR_TYPE_QUAD;
Device[deviceCount].Ports = 0;
Device[deviceCount].PullUpOption = false;
Device[deviceCount].InverseLogicOption = false;
Device[deviceCount].FormulaOption = true;
Device[deviceCount].ValueCount = 4;
Device[deviceCount].SendDataOption = true;
Device[deviceCount].TimerOption = true;
Device[deviceCount].TimerOptional = true;
Device[deviceCount].GlobalSyncOption = true;
break;
}
long cf_frequency = 0;
case PLUGIN_GET_DEVICENAME:
{
string = F(PLUGIN_NAME_077);
break;
}
case PLUGIN_GET_DEVICEVALUENAMES:
{
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_077));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_077));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_077));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[3], PSTR(PLUGIN_VALUENAME4_077));
break;
}
case PLUGIN_WEBFORM_LOAD:
{
addFormNumericBox(F("U Ref"), F("plugin_077_URef"), Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
addUnit(F("uSec"));
addFormNumericBox(F("I Ref"), F("plugin_077_IRef"), Settings.TaskDevicePluginConfig[event->TaskIndex][1]);
addUnit(F("uSec"));
addFormNumericBox(F("P Ref"), F("plugin_077_PRef"), Settings.TaskDevicePluginConfig[event->TaskIndex][2]);
addUnit(F("uSec"));
addFormNote(F("Use 0 to read values stored on chip / default values"));
if (CSE_PULSES_NOT_INITIALIZED == cf_pulses_last_time) {
cf_pulses_last_time = cf_pulses; // Init after restart
} else {
if (cf_pulses < cf_pulses_last_time) { // Rolled over after 65535 pulses
cf_frequency = (65536 - cf_pulses_last_time) + cf_pulses;
} else {
cf_frequency = cf_pulses - cf_pulses_last_time;
}
if (cf_frequency) {
cf_pulses_last_time = cf_pulses;
// energy_kWhtoday_delta += (cf_frequency * energy_power_calibration) / 36;
// EnergyUpdateToday();
}
}
success = true;
break;
}
*/
case PLUGIN_READ:
{
// We do not actually read as this is already done by reading the serial output
// Instead we just send the last known state stored in Uservar
addLog(LOG_LEVEL_DEBUG_DEV, F("CSE: plugin read"));
case PLUGIN_WEBFORM_SAVE:
{
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = getFormItemInt(F("plugin_077_URef"));;
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = getFormItemInt(F("plugin_077_IRef"));
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = getFormItemInt(F("plugin_077_PRef"));
success = true;
break;
}
case PLUGIN_INIT:
{
Plugin_077_init = true;
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 0) Settings.TaskDevicePluginConfig[event->TaskIndex][0] = HLW_UREF_PULSE;
if (Settings.TaskDevicePluginConfig[event->TaskIndex][1] == 0) Settings.TaskDevicePluginConfig[event->TaskIndex][1] = HLW_IREF_PULSE;
if (Settings.TaskDevicePluginConfig[event->TaskIndex][2] == 0) Settings.TaskDevicePluginConfig[event->TaskIndex][2] = HLW_PREF_PULSE;
Settings.UseSerial = true; // Enable Serial port
disableSerialLog(); // disable logging on serial port (used for CSE7766 communication)
Settings.BaudRate = 4800; // set BaudRate for CSE7766
Serial.flush();
Serial.begin(Settings.BaudRate);
success = true;
break;
}
/* currently not needed!
case PLUGIN_TEN_PER_SECOND:
{
long cf_frequency = 0;
if (CSE_PULSES_NOT_INITIALIZED == cf_pulses_last_time) {
cf_pulses_last_time = cf_pulses; // Init after restart
} else {
if (cf_pulses < cf_pulses_last_time) { // Rolled over after 65535 pulses
cf_frequency = (65536 - cf_pulses_last_time) + cf_pulses;
} else {
cf_frequency = cf_pulses - cf_pulses_last_time;
}
if (cf_frequency) {
cf_pulses_last_time = cf_pulses;
// energy_kWhtoday_delta += (cf_frequency * energy_power_calibration) / 36;
// EnergyUpdateToday();
}
}
success = true;
break;
}
*/
case PLUGIN_READ:
{
addLog(LOG_LEVEL_DEBUG_DEV, F("CSE: plugin read"));
// sendData(event);
success = true;
break;
}
// Variables set in PLUGIN_SERIAL_IN as soon as there are new values!
// UserVar[event->BaseVarIndex] = energy_voltage;
// UserVar[event->BaseVarIndex + 1] = energy_power;
// UserVar[event->BaseVarIndex + 2] = energy_current;
// UserVar[event->BaseVarIndex + 3] = cf_pulses;
success = true;
break;
}
case PLUGIN_SERIAL_IN:
{
if (Plugin_077_init) {
if (Serial.available() > 0) {
serial_in_byte = Serial.read();
success = true;
}
case PLUGIN_SERIAL_IN:
{
if (Plugin_077_init) {
if (Serial.available() > 0) {
serial_in_byte = Serial.read();
success = true;
if (cse_receive_flag) {
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
if (24 == serial_in_byte_counter) {
addLog(LOG_LEVEL_DEBUG_DEV, F("CSE: packet received"));
CseReceived(event);
cse_receive_flag = 0;
break;
}
} else {
if (0x5A == serial_in_byte) { // 0x5A - Packet header 2
cse_receive_flag = 1;
addLog(LOG_LEVEL_DEBUG_DEV, F("CSE: Header received"));
} else {
serial_in_byte_counter = 0;
}
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
}
serial_in_byte = 0; // Discard
if (cse_receive_flag) {
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
if (24 == serial_in_byte_counter) {
addLog(LOG_LEVEL_DEBUG_DEV, F("CSE: packet received"));
CseReceived(event);
cse_receive_flag = 0;
serial_in_byte_counter = 0;
// new packet received, update values
UserVar[event->BaseVarIndex] = energy_voltage;
UserVar[event->BaseVarIndex + 1] = energy_power;
UserVar[event->BaseVarIndex + 2] = energy_current;
UserVar[event->BaseVarIndex + 3] = cf_pulses;
// break;
}
} else {
if (0x5A == serial_in_byte) { // 0x5A - Packet header 2
cse_receive_flag = 1;
addLog(LOG_LEVEL_DEBUG_DEV, F("CSE: Header received"));
} else {
serial_in_byte_counter = 0;
}
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
}
serial_in_byte = 0; // Discard
UserVar[event->BaseVarIndex] = energy_voltage;
UserVar[event->BaseVarIndex + 1] = energy_power;
UserVar[event->BaseVarIndex + 2] = energy_current;
UserVar[event->BaseVarIndex + 3] = cf_pulses;
// String log = F("Variable: Tag: ");
// log += key;
// addLog(LOG_LEVEL_INFO, log);
// success = true;
}
break;
}
}
return success;
// String log = F("Variable: Tag: ");
// log += key;
// addLog(LOG_LEVEL_INFO, log);
// success = true;
}
}
break;
}
}
return success;
}
void CseReceived(struct EventStruct *event)
{
String log;
uint8_t header = serial_in_buffer[0];
if ((header & 0xFC) == 0xFC) {
addLog(LOG_LEVEL_DEBUG, F("CSE: Abnormal hardware"));
return;
}
uint8_t header = serial_in_buffer[0];
if ((header & 0xFC) == 0xFC) {
addLog(LOG_LEVEL_DEBUG, F("CSE: Abnormal hardware"));
return;
}
// Calculate checksum
uint8_t checksum = 0;
for (byte i = 2; i < 23; i++) checksum += serial_in_buffer[i];
if (checksum != serial_in_buffer[23]) {
addLog(LOG_LEVEL_DEBUG, F("CSE: Checksum Failure"));
return;
}
// Calculate checksum
uint8_t checksum = 0;
for (byte i = 2; i < 23; i++) checksum += serial_in_buffer[i];
if (checksum != serial_in_buffer[23]) {
addLog(LOG_LEVEL_DEBUG, F("CSE: Checksum Failure"));
return;
}
// Get chip calibration data (coefficients) and use as initial defaults
if (HLW_UREF_PULSE == Settings.TaskDevicePluginConfig[event->TaskIndex][0]) {
long voltage_coefficient = 191200; // uSec
if (CSE_NOT_CALIBRATED != header) {
voltage_coefficient = serial_in_buffer[2] << 16 | serial_in_buffer[3] << 8 | serial_in_buffer[4];
}
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = voltage_coefficient / CSE_UREF;
}
if (HLW_IREF_PULSE == Settings.TaskDevicePluginConfig[event->TaskIndex][1]) {
long current_coefficient = 16140; // uSec
if (CSE_NOT_CALIBRATED != header) {
current_coefficient = serial_in_buffer[8] << 16 | serial_in_buffer[9] << 8 | serial_in_buffer[10];
}
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = current_coefficient;
}
if (HLW_PREF_PULSE == Settings.TaskDevicePluginConfig[event->TaskIndex][2]) {
long power_coefficient = 5364000; // uSec
if (CSE_NOT_CALIBRATED != header) {
power_coefficient = serial_in_buffer[14] << 16 | serial_in_buffer[15] << 8 | serial_in_buffer[16];
}
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = power_coefficient / CSE_PREF;
}
// Get chip calibration data (coefficients) and use as initial defaults
if (HLW_UREF_PULSE == Settings.TaskDevicePluginConfig[event->TaskIndex][0]) {
long voltage_coefficient = 191200; // uSec
if (CSE_NOT_CALIBRATED != header) {
voltage_coefficient = serial_in_buffer[2] << 16 | serial_in_buffer[3] << 8 | serial_in_buffer[4];
}
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = voltage_coefficient / CSE_UREF;
}
if (HLW_IREF_PULSE == Settings.TaskDevicePluginConfig[event->TaskIndex][1]) {
long current_coefficient = 16140; // uSec
if (CSE_NOT_CALIBRATED != header) {
current_coefficient = serial_in_buffer[8] << 16 | serial_in_buffer[9] << 8 | serial_in_buffer[10];
}
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = current_coefficient;
}
if (HLW_PREF_PULSE == Settings.TaskDevicePluginConfig[event->TaskIndex][2]) {
long power_coefficient = 5364000; // uSec
if (CSE_NOT_CALIBRATED != header) {
power_coefficient = serial_in_buffer[14] << 16 | serial_in_buffer[15] << 8 | serial_in_buffer[16];
}
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = power_coefficient / CSE_PREF;
}
uint8_t adjustement = serial_in_buffer[20];
voltage_cycle = serial_in_buffer[5] << 16 | serial_in_buffer[6] << 8 | serial_in_buffer[7];
current_cycle = serial_in_buffer[11] << 16 | serial_in_buffer[12] << 8 | serial_in_buffer[13];
power_cycle = serial_in_buffer[17] << 16 | serial_in_buffer[18] << 8 | serial_in_buffer[19];
cf_pulses = serial_in_buffer[21] << 8 | serial_in_buffer[22];
uint8_t adjustement = serial_in_buffer[20];
voltage_cycle = serial_in_buffer[5] << 16 | serial_in_buffer[6] << 8 | serial_in_buffer[7];
current_cycle = serial_in_buffer[11] << 16 | serial_in_buffer[12] << 8 | serial_in_buffer[13];
power_cycle = serial_in_buffer[17] << 16 | serial_in_buffer[18] << 8 | serial_in_buffer[19];
cf_pulses = serial_in_buffer[21] << 8 | serial_in_buffer[22];
log = F("CSE: adjustement ");
log += adjustement;
addLog(LOG_LEVEL_DEBUG_DEV, log);
log = F("CSE: voltage_cycle ");
log += voltage_cycle;
addLog(LOG_LEVEL_DEBUG_DEV, log);
log = F("CSE: current_cycle ");
log += current_cycle;
addLog(LOG_LEVEL_DEBUG_DEV, log);
log = F("CSE: power_cycle ");
log += power_cycle;
addLog(LOG_LEVEL_DEBUG_DEV, log);
log = F("CSE: cf_pulses ");
log += cf_pulses;
addLog(LOG_LEVEL_DEBUG_DEV, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG_DEV)) {
String log = F("CSE: adjustement ");
log += adjustement;
addLog(LOG_LEVEL_DEBUG_DEV, log);
log = F("CSE: voltage_cycle ");
log += voltage_cycle;
addLog(LOG_LEVEL_DEBUG_DEV, log);
log = F("CSE: current_cycle ");
log += current_cycle;
addLog(LOG_LEVEL_DEBUG_DEV, log);
log = F("CSE: power_cycle ");
log += power_cycle;
addLog(LOG_LEVEL_DEBUG_DEV, log);
log = F("CSE: cf_pulses ");
log += cf_pulses;
addLog(LOG_LEVEL_DEBUG_DEV, log);
}
// if (energy_power_on) { // Powered on
// if (energy_power_on) { // Powered on
if (adjustement & 0x40) { // Voltage valid
energy_voltage = (float)(Settings.TaskDevicePluginConfig[event->TaskIndex][0] * CSE_UREF) / (float)voltage_cycle;
}
if (adjustement & 0x10) { // Power valid
if ((header & 0xF2) == 0xF2) { // Power cycle exceeds range
energy_power = 0;
} else {
if (0 == power_cycle_first) power_cycle_first = power_cycle; // Skip first incomplete power_cycle
if (power_cycle_first != power_cycle) {
power_cycle_first = -1;
energy_power = (float)(Settings.TaskDevicePluginConfig[event->TaskIndex][2] * CSE_PREF) / (float)power_cycle;
} else {
energy_power = 0;
}
}
} else {
power_cycle_first = 0;
energy_power = 0; // Powered on but no load
}
if (adjustement & 0x20) { // Current valid
if (0 == energy_power) {
energy_current = 0;
} else {
energy_current = (float)Settings.TaskDevicePluginConfig[event->TaskIndex][1] / (float)current_cycle;
}
}
if (adjustement & 0x40) { // Voltage valid
energy_voltage = (float)(Settings.TaskDevicePluginConfig[event->TaskIndex][0] * CSE_UREF) / (float)voltage_cycle;
}
if (adjustement & 0x10) { // Power valid
if ((header & 0xF2) == 0xF2) { // Power cycle exceeds range
energy_power = 0;
} else {
if (0 == power_cycle_first) power_cycle_first = power_cycle; // Skip first incomplete power_cycle
if (power_cycle_first != power_cycle) {
power_cycle_first = -1;
energy_power = (float)(Settings.TaskDevicePluginConfig[event->TaskIndex][2] * CSE_PREF) / (float)power_cycle;
} else {
energy_power = 0;
}
}
} else {
power_cycle_first = 0;
energy_power = 0; // Powered on but no load
}
if (adjustement & 0x20) { // Current valid
if (0 == energy_power) {
energy_current = 0;
} else {
energy_current = (float)Settings.TaskDevicePluginConfig[event->TaskIndex][1] / (float)current_cycle;
}
}
// } else { // Powered off
// power_cycle_first = 0;
// energy_voltage = 0;
// energy_power = 0;
// energy_current = 0;
// }
// } else { // Powered off
// power_cycle_first = 0;
// energy_voltage = 0;
// energy_power = 0;
// energy_current = 0;
// }
log = F("CSE voltage: ");
log += energy_voltage;
addLog(LOG_LEVEL_DEBUG, log);
log = F("CSE power: ");
log += energy_power;
addLog(LOG_LEVEL_DEBUG, log);
log = F("CSE current: ");
log += energy_current;
addLog(LOG_LEVEL_DEBUG, log);
log = F("CSE piulses: ");
log += cf_pulses;
addLog(LOG_LEVEL_DEBUG, log);
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
String log = F("CSE voltage: ");
log += energy_voltage;
addLog(LOG_LEVEL_DEBUG, log);
log = F("CSE power: ");
log += energy_power;
addLog(LOG_LEVEL_DEBUG, log);
log = F("CSE current: ");
log += energy_current;
addLog(LOG_LEVEL_DEBUG, log);
log = F("CSE piulses: ");
log += cf_pulses;
addLog(LOG_LEVEL_DEBUG, log);
}
}
#endif // USES_P077
+13 -5
View File
@@ -1137,9 +1137,9 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
TempEvent.sensorType = Device[DeviceIndex].VType;
checkRAM(F("PluginCall_s"),x);
START_TIMER;
bool retval = (Plugin_ptr[x](Function, event, str));
bool retval = (Plugin_ptr[x](Function, &TempEvent, str));
STOP_TIMER_TASK(x,Function);
if (retval) return true;
if (retval) return true;
}
}
}
@@ -1168,7 +1168,7 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
//TempEvent.idx = Settings.TaskDeviceID[y]; todo check
TempEvent.sensorType = Device[DeviceIndex].VType;
START_TIMER;
bool retval = (Plugin_ptr[x](Function, event, str));
bool retval = (Plugin_ptr[x](Function, &TempEvent, str));
STOP_TIMER_TASK(x,Function);
if (retval){
checkRAM(F("PluginCallUDP"),x);
@@ -1206,6 +1206,10 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
TempEvent.sensorType = Device[DeviceIndex].VType;
TempEvent.OriginTaskIndex = event->TaskIndex;
checkRAM(F("PluginCall_s"),x);
if (Function == PLUGIN_INIT) {
// Schedule the plugin to be read.
schedule_task_device_timer_at_init(TempEvent.TaskIndex);
}
START_TIMER;
Plugin_ptr[x](Function, &TempEvent, str);
STOP_TIMER_TASK(x,Function);
@@ -1228,17 +1232,21 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
case PLUGIN_GET_DEVICEGPIONAMES:
case PLUGIN_READ:
case PLUGIN_SET_CONFIG:
case PLUGIN_GET_CONFIG:
case PLUGIN_GET_CONFIG:
{
const int x = getPluginId(event->TaskIndex);
if (x >= 0) {
if (Plugin_id[x] != 0 ) {
if (Function == PLUGIN_INIT) {
// Schedule the plugin to be read.
schedule_task_device_timer_at_init(event->TaskIndex);
}
event->BaseVarIndex = event->TaskIndex * VARS_PER_TASK;
checkRAM(F("PluginCall_init"),x);
START_TIMER;
bool retval = Plugin_ptr[x](Function, event, str);
STOP_TIMER_TASK(x,Function);
return retval;
return retval;
}
}
return false;