Compare commits

...
Author SHA1 Message Date
ESPEasy release bot 1c5f8af083 automaticly updated release notes for mega-20180321 2018-03-21 04:00:08 +01:00
TD-er e7a9ee7eee Merge branch 'v2.0' into mega 2018-03-20 23:28:59 +01:00
Unknown 3edfdbf5f7 [wifi] Setup with factory settings could not complete 2018-03-20 23:27:39 +01:00
Gijs NoorlanderandGitHub 27bac2ca00 Merge pull request #1140 from TD-er/bugfix/connect_to_wifi_during_setup
[wifi] Setup with factory settings could not complete
2018-03-20 23:25:57 +01:00
Unknown 373f74e9f8 [wifi] Setup with factory settings could not complete 2018-03-20 23:25:23 +01:00
ESPEasy release bot 1220c565c8 automaticly updated release notes for v2.0-20180320 2018-03-20 04:00:23 +01:00
ESPEasy release bot 1931fe9e53 automaticly updated release notes for mega-20180320 2018-03-20 04:00:10 +01:00
Unknown 0eab6293dc Merge branch 'v2.0' into mega 2018-03-20 00:30:02 +01:00
Unknown f0987dab41 [issue #1097] WiFi connect with deepsleep enabled trigger watchdog reset
Did not allow for enough time to do background tasks while waiting for wifi connect with DeepSleep enabled.
2018-03-20 00:29:24 +01:00
Gijs NoorlanderandGitHub 51bd52603f Merge pull request #1134 from TD-er/bugfix/deepsleep_mqtt
[issue #1097] WiFi connect with deepsleep enabled trigger watchdog reset
2018-03-20 00:27:58 +01:00
Unknown 47f1fa145a [issue #1097] WiFi connect with deepsleep enabled trigger watchdog reset
Did not allow for enough time to do background tasks while waiting for wifi connect with DeepSleep enabled.
2018-03-20 00:26:48 +01:00
Unknown 605055d95a Merge branch 'v2.0' into mega 2018-03-19 22:52:36 +01:00
Unknown af3e353181 Revert "Merge pull request #1116 from TD-er/feature/allow_own_defaults"
This reverts commit 8ccbdcadf0.
2018-03-19 22:51:23 +01:00
es-kaandUnknown c711d6ea51 Fix wiring description for SN75176 transceiver 2018-03-19 22:50:31 +01:00
Gijs NoorlanderandGitHub 20c23a2935 Merge pull request #1133 from TD-er/bugfix/undo_espeasy_globals.h
Revert "Merge pull request #1116 from TD-er/feature/allow_own_defaults"
2018-03-19 22:48:51 +01:00
Gijs Noorlander bbfe254232 Revert "Merge pull request #1116 from TD-er/feature/allow_own_defaults"
This reverts commit 8ccbdcadf0.
2018-03-19 22:47:42 +01:00
Gijs NoorlanderandGitHub 882c888f6d Merge pull request #1132 from es-ka/mega
Fix wiring description for SN75176 transceiver
2018-03-19 22:37:04 +01:00
es-kaandGitHub 0a754f072c Fix wiring description for SN75176 transceiver 2018-03-19 20:00:41 +01:00
ESPEasy release bot 1f084c51cc automaticly updated release notes for v2.0-20180319 2018-03-19 04:00:24 +01:00
ESPEasy release bot 89df0932c5 automaticly updated release notes for mega-20180319 2018-03-19 04:00:11 +01:00
Unknown 429fd3e4d0 Merge branch 'v2.0' into mega 2018-03-19 01:06:32 +01:00
Gijs NoorlanderandGitHub 85e8d98da8 Merge pull request #1121 from TD-er/merge/fixes_20180318_to_v2.0
Merge/fixes 20180318 to v2.0
2018-03-19 01:01:42 +01:00
Unknown 6d52a7e03a [merge] MIssing #endif due to merging. 2018-03-19 00:51:05 +01:00
Gijs Noorlander fa513b52f9 Merge pull request #1118 from TD-er/bugfix/mqtt_publish_after_deep_sleep
[issue #1097] MQTT publish after deep sleep
2018-03-19 00:46:03 +01:00
Unknown f98401524f Merge pull request #1116 from TD-er/feature/allow_own_defaults
[issue #1007] Allow user specific data in separate file
2018-03-19 00:45:52 +01:00
Unknown 4090b4f23c Merge pull request #1113 from TD-er/feature/reduce_impact_wifi_disconnect
[Relaxed WiFi] Perform WiFi initialization in steps
2018-03-19 00:42:58 +01:00
Gijs Noorlander b89c00008d Merge pull request #1114 from TD-er/feature/wifi_details_json
[JSON] Add uint name (#1099) and WiFi information (PR #1113)
2018-03-19 00:39:43 +01:00
Gijs Noorlander d57a617138 Merge pull request #1112 from uzi18/fix-p073
Fix p073 - #1111
2018-03-19 00:39:32 +01:00
Gijs Noorlander cefe6b4b7c Changed so that running all tasks immediately with deep sleep enabled… (#1110)
Changed so that running all tasks immediately with deep sleep enabled only happens on first iteration after wake up
2018-03-19 00:38:30 +01:00
Gijs Noorlander 2432740b41 - add encoder write command #1086 (#1103)
- add encoder write command #1086
2018-03-19 00:35:09 +01:00
Gijs Noorlander 44a934651c Add download button for current rule set (#1102)
Add download button for current rule set
2018-03-19 00:34:52 +01:00
Gijs NoorlanderandGitHub 95fb0d6e6c Merge pull request #1118 from TD-er/bugfix/mqtt_publish_after_deep_sleep
[issue #1097] MQTT publish after deep sleep
2018-03-19 00:29:37 +01:00
Gijs NoorlanderandGitHub 8ccbdcadf0 Merge pull request #1116 from TD-er/feature/allow_own_defaults
[issue #1007] Allow user specific data in separate file
2018-03-19 00:29:08 +01:00
Unknown 433aa6910a [issue #1097] MQTT publish after deep sleep
The MQTTConnect was only called after a while. This is a problem for deepsleep.
So now the MQTT connect is done at the first loop when deep sleep is enabled.
2018-03-19 00:18:29 +01:00
Unknown 2ebc733b63 [issue #1007] Add other defines as suggested by @uzi18 2018-03-18 23:17:57 +01:00
Unknown 21bc1a7814 #ifndef instead of #ifdef 2018-03-18 22:55:30 +01:00
Unknown 53b8009df6 [issue #1007] Allow user specific data in separate file
File will be ignored by git and can be simply included using `-D USE_OWN_DEFAULTS` in the build
2018-03-18 22:46:15 +01:00
Gijs NoorlanderandGitHub 68a8e5982e Merge pull request #1113 from TD-er/feature/reduce_impact_wifi_disconnect
[Relaxed WiFi] Perform WiFi initialization in steps
2018-03-18 21:53:33 +01:00
Gijs NoorlanderandGitHub 08acfeac97 Merge pull request #1114 from TD-er/feature/wifi_details_json
[JSON] Add uint name (#1099) and WiFi information (PR #1113)
2018-03-18 21:52:24 +01:00
Unknown 999a561515 [JSON] Add uint name (#1099) and WiFi information (PR #1113)
As suggested by @Grovkillen on PR #1113.
2018-03-18 21:51:46 +01:00
Gijs NoorlanderandGitHub 3ee1a4ed2e Merge pull request #1112 from uzi18/fix-p073
Fix p073 - #1111
2018-03-18 21:23:11 +01:00
Gijs NoorlanderandGitHub 05801db47c Changed so that running all tasks immediately with deep sleep enabled… (#1110)
Changed so that running all tasks immediately with deep sleep enabled only happens on first iteration after wake up
2018-03-18 21:22:43 +01:00
Gijs NoorlanderandGitHub 7bec632f15 Merge pull request #1109 from s0170071/memtracker
changed memory tracker to uint64_t for the ESP32
2018-03-18 21:21:18 +01:00
Gijs NoorlanderandGitHub 3f8fe11b47 - add encoder write command #1086 (#1103)
- add encoder write command #1086
2018-03-18 21:17:13 +01:00
Gijs NoorlanderandGitHub 4b8f1e4c1b Add download button for current rule set (#1102)
Add download button for current rule set
2018-03-18 21:13:26 +01:00
Unknown 573fd0f320 [Travis error] Some #include test that wasn't meant to be included
... in the commit.
2018-03-18 21:08:22 +01:00
Unknown 4fa5203c5b [Relaxed WiFi] Perform WiFi initialization in steps
Doing WiFi initialization in multiple steps, will reduce boot time a lot.
For deepsleep the Setup is waiting for wifi initialization to complete, but for normal use the wifi connection is initiated during setup and checked on regular intervals to see if it is available.
The same for WiFi reconnect, which will hopefully not affect the performance of the ESP module during reconnects.

Also added a check + event when connected to another accesspoint with different BSSID (MAC address of accesspoint). Also the last used BSSID is used to reconnect to try to connect to the same device over and over, which may be useful with WiFi repeaters.
2018-03-18 20:54:27 +01:00
Bartlomiej Zimon 9c9617f6ed - initialize pointer in P073 2018-03-18 20:30:47 +01:00
Bartlomiej Zimon bbbf6c483f - fix P073 success setting in PLUGIN_WRITE callback 2018-03-18 20:30:18 +01:00
Bartlomiej Zimon 668909e7b3 - fix success setting 2018-03-18 20:16:37 +01:00
Unknown c642848ef2 [WiFi] Try to minimize effect of WiFi interruptions
And send event when connected to a different accesspoint.
Currently the impact on WiFi reconnects is enorm. The ESP stalls, won't react on events, etc.
2018-03-18 02:51:59 +01:00
s0170071 6eea35aa81 Keep uint. Just change the init value. 2018-03-17 22:58:09 +01:00
Panayotis Kouvarakis 738a48213c Changed so that running all tasks immediately with deep sleep enabled only happens on first iteration after wake up 2018-03-17 23:33:21 +02:00
s0170071 d1c093d109 changed memory tracker to uint64_t for the ESP32 2018-03-17 20:15:48 +01:00
Bartlomiej Zimon 00166a1aad - add encoder write #1086 2018-03-16 19:54:24 +01:00
Bartlomiej Zimon 589238324b Add download button for current rule set 2018-03-16 18:15:52 +01:00
ESPEasy release bot 6787bc8c0e automaticly updated release notes for v2.0-20180316 2018-03-16 04:00:23 +01:00
ESPEasy release bot 6845a03741 automaticly updated release notes for mega-20180316 2018-03-16 04:00:11 +01:00
Unknown 6a4284f189 Merge branch 'v2.0' into mega 2018-03-16 00:44:54 +01:00
Gijs NoorlanderandGitHub cf644b45b1 Merge pull request #1095 from TD-er/merge/PR_1092_1093_1094
Merge/pr 1092 1093 1094
2018-03-16 00:43:16 +01:00
Unknown e6fe1c63a9 [issue #951] Changed System#Initialized => System#Wake
Changed System#Initialized  => System#Wake
New event name makes more sense and Initialized may be used later to indicate all needed connections, etc. are ready.
2018-03-16 00:38:00 +01:00
Unknown df978036f0 [issue #993] variable in MQTT subscribe topic
As [noted](https://github.com/letscontrolit/ESPEasy/issues/993#issuecomment-373140135) by @kluszcyn
2018-03-16 00:37:54 +01:00
Unknown 7cb375833d [issue #1057] AM PM display issue
X:XX PM (for hours 1...9)
X:XX AM (for hours 1...9)
XX:XX PM (for hours 10...12)
XX:XX AM (for hours 10...12)

Added for H:MM (without seconds) notations:
- `%systm_hm%`
-`%systm_hm_am%`
2018-03-16 00:37:45 +01:00
Gijs NoorlanderandGitHub 41c57f1ef9 Merge pull request #1094 from TD-er/bugfix/System_Wake_event
[issue #951] Changed System#Initialized  => System#Wake
2018-03-16 00:35:24 +01:00
Unknown 808b40bdba [issue #951] Changed System#Initialized => System#Wake
Changed System#Initialized  => System#Wake
New event name makes more sense and Initialized may be used later to indicate all needed connections, etc. are ready.
2018-03-16 00:34:32 +01:00
Gijs NoorlanderandGitHub 58b20615da Merge pull request #1093 from TD-er/bugfix/993_parse_sysvars
[issue #993] variable in MQTT subscribe topic
2018-03-15 23:57:01 +01:00
Unknown 13026b1cc4 [issue #993] variable in MQTT subscribe topic
As [noted](https://github.com/letscontrolit/ESPEasy/issues/993#issuecomment-373140135) by @kluszcyn
2018-03-15 23:56:01 +01:00
Gijs NoorlanderandGitHub 7f3460e492 Merge pull request #1092 from TD-er/bugfix/am_pm_time
[issue #1057] AM PM display issue
2018-03-15 23:44:18 +01:00
Unknown a222391f81 [issue #1057] AM PM display issue
X:XX PM (for hours 1...9)
X:XX AM (for hours 1...9)
XX:XX PM (for hours 10...12)
XX:XX AM (for hours 10...12)

Added for H:MM (without seconds) notations:
- `%systm_hm%`
-`%systm_hm_am%`
2018-03-15 23:43:14 +01:00
Unknown a8165531d5 Merge branch 'v2.0' into mega 2018-03-15 23:06:07 +01:00
Gijs NoorlanderandGitHub 3218ea9839 Merge pull request #1091 from TD-er/merge/fixes_1073_1079_1081 into v2.0
Merge/fixes 1073 1079 1081 into v2.0
2018-03-15 23:05:06 +01:00
Gijs Noorlander eca8901fca Fixed multi instance problem on SHT3x #433 (#1081)
Fixed multi instance problem on SHT3x #433
2018-03-15 23:02:04 +01:00
Gijs Noorlander 6635eafe91 [issue #1066] Fix Webserver handle_control (#1079)
[issue #1066] Fix Webserver handle_control
2018-03-15 23:01:52 +01:00
Gijs Noorlander fe4d1f952f MCP3221 allow values for calibration (#1073)
MCP3221 allow values for calibration
2018-03-15 23:01:39 +01:00
Gijs NoorlanderandGitHub 1abd31b421 Fixed multi instance problem on SHT3x #433 (#1081)
Fixed multi instance problem on SHT3x #433
2018-03-15 23:00:05 +01:00
Gijs NoorlanderandGitHub 72fe49d905 [issue #1066] Fix Webserver handle_control (#1079)
[issue #1066] Fix Webserver handle_control
2018-03-15 22:58:38 +01:00
Gijs NoorlanderandGitHub 9dd9f3befa MCP3221 allow values for calibration (#1073)
MCP3221 allow values for calibration
2018-03-15 22:57:14 +01:00
Unknown 471d76dbe6 Merge branch 'v2.0' into mega 2018-03-15 22:55:31 +01:00
Gijs NoorlanderandGitHub 4475a225cc Merge pull request #1090 from TD-er/merge/split_globals_v2.0
Merge/split globals v2.0
2018-03-15 22:46:46 +01:00
Gijs NoorlanderandGitHub 8b047490c4 Merge pull request #1089 from TD-er/merge/split_globals_Mega
Merge/split globals mega
2018-03-15 22:46:28 +01:00
Unknown 455f77d0ed Merge branch 'v2.0' into mega 2018-03-15 22:42:50 +01:00
Unknown 836fc4a875 Merge remote-tracking branch 'uzi18/mega' into merge/split_globals 2018-03-15 22:29:30 +01:00
Unknown 2aece1c143 [v2.0 split globals] Base split on v2.0 version of ESPEasy.ino 2018-03-15 22:23:59 +01:00
Bartlomiej ZimonandUnknown 70df225e7e Merge branch 'mega' of github.com:letscontrolit/ESPEasy into mega
# Conflicts:
#	src/ESPEasy.ino
2018-03-15 22:05:36 +01:00
Unknown 19af52a3ef - move all structs from ESPEasy.ino into header file
- add some fix for headers
- add const to rtttl notes array
2018-03-15 22:05:22 +01:00
Gijs NoorlanderandGitHub 3d396575ff Merge pull request #1088 from TD-er/merge/rules_fix__and_globalsync_toV2.0
Merge/rules fix  and globalsync to v2.0
2018-03-15 21:52:41 +01:00
ESPEasy release bot 873f8474b5 automaticly updated release notes for mega-20180315 2018-03-15 04:00:08 +01:00
mvdbroandUnknown 826deaac89 Rules fix 2018-03-14 21:28:24 +01:00
mvdbroandUnknown cce621cff8 #893, part 2 receiving 2018-03-14 21:28:15 +01:00
mvdbroandUnknown 57eb38dbd0 Custom controller GUI option 2018-03-14 21:28:08 +01:00
mvdbroandUnknown fd2451bb07 #893 part1, send messages 2018-03-14 21:27:50 +01:00
mvdbro c94e5cb903 Rules fix 2018-03-14 19:26:29 +01:00
Bartlomiej Zimon 27699f7192 Merge branch 'mega' of github.com:letscontrolit/ESPEasy into mega
# Conflicts:
#	src/ESPEasy.ino
2018-03-14 19:09:46 +01:00
Bartlomiej Zimon 2eff001b14 Merge branch 'mega' of github.com:letscontrolit/ESPEasy into mega 2018-03-14 18:54:24 +01:00
mvdbro bd499c7a94 #893, part 2 receiving 2018-03-14 13:11:16 +01:00
JK 4da1e4fbdd Fixed #433
Not tested!
2018-03-14 12:19:57 +01:00
mvdbro 1d14770ea7 Custom controller GUI option 2018-03-14 10:45:15 +01:00
ESPEasy release bot 8b7574d298 automaticly updated release notes for mega-20180314 2018-03-14 04:00:11 +01:00
Unknown 14d87d95f6 [issue #1066] Fix Webserver handle_control
There wasn't a proper start/end for the streaming webserver.
See discussion on issue #1066
2018-03-14 01:30:49 +01:00
mvdbro 5a15288d80 #893 part1, send messages 2018-03-13 16:36:58 +01:00
Bartlomiej Zimon 869dff12ce - move all structs from ESPEasy.ino into header file
- add some fix for headers
- add const to rtttl notes array
2018-03-13 15:53:42 +01:00
ESPEasy release bot cc0b3dac26 automaticly updated release notes for v2.0-20180313 2018-03-13 04:00:23 +01:00
ESPEasy release bot 4208048fc1 automaticly updated release notes for mega-20180313 2018-03-13 04:00:11 +01:00
Unknown 06a2f47812 Merge branch 'v2.0' into mega 2018-03-12 23:20:59 +01:00
Gijs NoorlanderandGitHub d3434eb4d2 Merge/fix rules trailing spaces (#1065) #1074
Merge/fix rules trailing spaces (#1065)
2018-03-12 23:18:22 +01:00
Bartlomiej ZimonandUnknown bd2665041f - remove double trimm() 2018-03-12 23:15:48 +01:00
Bartlomiej ZimonandUnknown 1fd429a029 - fix for #1065 2018-03-12 23:15:40 +01:00
sassod 7b3a71bcc9 12bit ADC values acceted up to 4095
MCP3221 is a 12bit ADC so accepted values should be up to 40195 not 1024
2018-03-12 19:56:42 +01:00
mvdbroandGitHub 18e612dea2 Merge pull request #1067 from uzi18/mega
- fix for #1065
2018-03-12 19:35:51 +01:00
mvdbro f99593ed62 ESP32 C010 fix 2018-03-12 19:34:40 +01:00
sassod 2f7e96fa5b Merge remote-tracking branch 'refs/remotes/origin/mega' into letscontrolit/mega 2018-03-12 18:51:00 +01:00
Bartlomiej Zimon 25b4392dd5 - remove double trimm() 2018-03-12 12:09:07 +01:00
Bartlomiej Zimon ad4130a547 - fix for #1065 2018-03-12 11:42:00 +01:00
ESPEasy release bot e4d4463eab automaticly updated release notes for v2.0-20180312 2018-03-12 04:00:19 +01:00
ESPEasy release bot 991384822f automaticly updated release notes for mega-20180312 2018-03-12 04:00:07 +01:00
Gijs NoorlanderandGitHub b29f56c6f4 Merge pull request #1063 from TD-er/merge/rule_engine_fix
Rule Engine minor fix and added dev debugging
2018-03-12 00:55:49 +01:00
Unknown 779514481d Rule Engine minor fix and added dev debugging 2018-03-12 00:52:30 +01:00
Unknown 82ed319e59 Merge branch 'v2.0' into mega 2018-03-12 00:46:31 +01:00
Gijs NoorlanderandGitHub 0a752dd26f Merge pull request #1062 from TD-er/merge/issue_1039
Merge/issue 1039
2018-03-12 00:44:02 +01:00
Gijs NoorlanderandGitHub 2e4af86a99 Merge pull request #1061 from TD-er/bugfix/chunking_webserver
[webserver] Improve chunked transfer
2018-03-12 00:42:30 +01:00
Unknown 8112e0e67a [webserver] Improve chunked transfer
Do chunked transfer using full buffer on all data sent to the streaming webserver.
2018-03-12 00:42:08 +01:00
Unknown 89a9f842fd [issue #1039 ] Change CSS to show topmost SSID on large screens
For screens with > 960 pixels width.
To show all accesspoints on AP selection.
2018-03-12 00:41:44 +01:00
Gijs NoorlanderandGitHub b4791d3421 Merge pull request #1060 from TD-er/bugfix/selection_accesspoints
[issue #1039 ] Change CSS to show topmost SSID on large screens
2018-03-12 00:40:13 +01:00
Unknown 885c5394a3 [webserver] Improve chunked transfer
Do chunked transfer using full buffer on all data sent to the streaming webserver.
2018-03-12 00:34:51 +01:00
Unknown e35304e4e7 [issue #1039 ] Change CSS to show topmost SSID on large screens
For screens with > 960 pixels width.
To show all accesspoints on AP selection.
2018-03-12 00:32:46 +01:00
mvdbro 6561d577d4 Rule Engine minor fix and added dev debugging 2018-03-11 10:40:54 +01:00
ESPEasy release bot 92932fddb2 automaticly updated release notes for v2.0-20180311 2018-03-11 04:00:19 +01:00
ESPEasy release bot 02d8834763 automaticly updated release notes for mega-20180311 2018-03-11 04:00:06 +01:00
Gijs NoorlanderandGitHub e82080dc52 Merge pull request #1053 from letscontrolit/v2.0
V2.0
2018-03-11 02:07:27 +01:00
Unknown 89581fd0fb [issue #1039] Topmost SSID are covered on mobile Browser
Added <span> tags with a class around the error, which allow the CSS to position the content below the header.
2018-03-11 01:59:51 +01:00
Gijs NoorlanderandGitHub cfbf972c1b [issue #1039] Topmost SSID are covered on mobile Browser (#1052)
[issue #1039] Topmost SSID are covered on mobile Browser
2018-03-11 01:58:13 +01:00
Unknown e25ea52edc [issue #1039] Topmost SSID are covered on mobile Browser
Added <span> tags with a class around the error, which allow the CSS to position the content below the header.
2018-03-11 01:57:24 +01:00
Unknown 3f84a961ad [DNS lookup] Controllers sometimes try to connect to 0.0.0.0
See issue #824
2018-03-11 01:38:50 +01:00
Gijs NoorlanderandGitHub 7d8e5e5175 [DNS lookup] Controllers sometimes try to connect to 0.0.0.0 (#1051)
[DNS lookup] Controllers sometimes try to connect to 0.0.0.0
2018-03-11 01:37:38 +01:00
Unknown 3d39dec686 [DNS lookup] Controllers sometimes try to connect to 0.0.0.0
See issue #824
2018-03-11 01:36:29 +01:00
Unknown ff656593ec Merge branch 'v2.0' into mega 2018-03-10 23:07:53 +01:00
Unknown 96bfaa27f5 [OLED] fix drawProgressBar
See this PR: https://github.com/ThingPulse/esp8266-oled-ssd1306/pull/178
2018-03-10 23:04:03 +01:00
Unknown bcca0514dd [deepsleep] Make sure the 'shortcut' of running all services when sleep enabled
As pointed out on [the forum by arion_p](https://www.letscontrolit.com/forum/viewtopic.php?p=25771#p25771)
2018-03-10 23:03:55 +01:00
Gijs NoorlanderandGitHub 90b4e3438d [OLED] fix drawProgressBar (#1048)
[OLED] fix drawProgressBar
2018-03-10 22:58:25 +01:00
Gijs NoorlanderandGitHub 139f8905d0 [deepsleep] Use the 'shortcut' of running all when sleep enabled (#1047)
[deepsleep] Use the 'shortcut' of running all when sleep enabled
2018-03-10 22:55:59 +01:00
Unknown 6c1806fae6 [OLED] fix drawProgressBar
See this PR: https://github.com/ThingPulse/esp8266-oled-ssd1306/pull/178
2018-03-10 22:53:18 +01:00
Unknown e6b581e7ff [deepsleep] Make sure the 'shortcut' of running all services when sleep enabled
As pointed out on [the forum by arion_p](https://www.letscontrolit.com/forum/viewtopic.php?p=25771#p25771)
2018-03-10 22:42:04 +01:00
Gijs NoorlanderandGitHub bb9f8fc809 Merge pull request #1046 from TD-er/merge/mega_to_v2.0
Merge/mega to v2.0
2018-03-10 22:03:14 +01:00
Unknown 4d9504bce0 [P073] Remove tm1637_bitDelay()
Not used anymore
2018-03-10 22:01:27 +01:00
Unknown ff3a769033 Update P07 Plugin
added suppor for other version of TM1637 modules (4dgt+colon, 4dgt+dots,6dgt+dots)
2018-03-10 22:01:20 +01:00
Unknown e3de56a7a8 [AM/PM] Am/Pm notation doesn't have '0' hours
11.59 a.m. => 12.00 p.m.
12.59 p.m. => 1.00 p.m.
11.59 p.m. => 12.00 a.m.
2018-03-10 22:01:04 +01:00
Gijs NoorlanderandGitHub 873d639461 Update P073 Plugin - support extra versions of TM1637 modules (@Papperone) (#1043)
Update P073 Plugin - support extra versions of TM1637 modules  (@Papperone)
2018-03-10 21:58:14 +01:00
Gijs NoorlanderandGitHub edb2a6d3f6 [AM/PM] Am/Pm notation doesn't have '0' hours (#1044)
[AM/PM] Am/Pm notation doesn't have '0' hours
2018-03-10 21:56:42 +01:00
Gijs NoorlanderandGitHub 2682b0bd2f [v2.0] Merge/rules process speed improvements (#1045)
[v2.0] Merge/rules process speed improvements
2018-03-10 21:55:25 +01:00
Unknown 5097157a09 Final ruleset speed-up
It's now down from 100 mSec to 19 mSec for 1 fully loaded non matching ruleset.
2018-03-10 21:41:13 +01:00
Unknown 02ea957894 Add read buffer to rule processing to speedup parsing
On a full ruleset (2k), a non matching event takes 100 mSec instead of 170 mSec.
2018-03-10 21:39:51 +01:00
mvdbroandUnknown c2b0d76595 Rule Engine, stop waisting time on non matching rules 2018-03-10 21:38:01 +01:00
Unknown 91b7cbe075 Improve flash read performance 2018-03-10 21:37:47 +01:00
Unknown bff60a2e27 [P073] Remove tm1637_bitDelay()
Not used anymore
2018-03-10 21:28:09 +01:00
Unknown 61831e5962 [AM/PM] Am/Pm notation doesn't have '0' hours
11.59 a.m. => 12.00 p.m.
12.59 p.m. => 1.00 p.m.
11.59 p.m. => 12.00 a.m.
2018-03-10 21:19:35 +01:00
Unknown d105b47d44 Update P07 Plugin
added suppor for other version of TM1637 modules (4dgt+colon, 4dgt+dots,6dgt+dots)
2018-03-10 18:38:33 +01:00
mvdbro 449568bcc4 Final ruleset speed-up
It's now down from 100 mSec to 19 mSec for 1 fully loaded non matching ruleset.
2018-03-10 16:53:02 +01:00
mvdbro 3144077103 Add read buffer to rule processing to speedup parsing
On a full ruleset (2k), a non matching event takes 100 mSec instead of 170 mSec.
2018-03-10 15:48:56 +01:00
mvdbro 8f056be0a8 Rule Engine, stop waisting time on non matching rules 2018-03-10 10:48:03 +01:00
mvdbro e9cdc5693d Improve flash read performance 2018-03-10 08:51:35 +01:00
ESPEasy release bot 64b38df187 automaticly updated release notes for v2.0-20180310 2018-03-10 04:00:20 +01:00
ESPEasy release bot 377c50ec36 automaticly updated release notes for mega-20180310 2018-03-10 04:00:07 +01:00
Gijs NoorlanderandGitHub 76f6dfdc59 Merge Mega -> v2.0: conversions & delay wifi init (#1037)
Merge Mega -> v2.0: conversions  & delay wifi init
2018-03-09 23:20:47 +01:00
Unknown 3a6f7acd15 [Conversions] Use more decimals in conversions and add AM/PM for time.
See comments on #1015
2018-03-09 23:19:19 +01:00
Unknown d65b126f84 Move plugin init before WiFi init
As suggested at PR #1032 by @M0ebiu5
2018-03-09 23:18:10 +01:00
Gijs NoorlanderandGitHub 90a2a799da [Conversions] Use more decimals in conversions and add AM/PM for time. (#1036)
[Conversions] Use more decimals in conversions and add AM/PM for time.
2018-03-09 23:15:48 +01:00
Unknown feb419b6ae [Conversions] Use more decimals in conversions and add AM/PM for time.
See comments on #1015
2018-03-09 23:13:03 +01:00
Gijs NoorlanderandGitHub e83d8468b0 Move plugin init before WiFi init (#1035)
Move plugin init before WiFi init
2018-03-09 22:18:35 +01:00
Unknown 6eabaaa62d Move plugin init before WiFi init
As suggested at PR #1032 by @M0ebiu5
2018-03-09 22:10:25 +01:00
ESPEasy release bot 8299e38b24 automaticly updated release notes for v2.0-20180309 2018-03-09 04:00:22 +01:00
ESPEasy release bot b0169b4aa7 automaticly updated release notes for mega-20180309 2018-03-09 04:00:11 +01:00
Unknown 786ec4714a Merge branch 'v2.0' into mega 2018-03-09 00:37:47 +01:00
Gijs NoorlanderandGitHub 67a28a7f97 Add other simple conversions like Celsius to Fahrenheit (#1033)
[issue #1015] Add other simple conversions like Celsius to Fahrenheit…
2018-03-09 00:35:06 +01:00
Unknown 18b8e61d32 [issue #1015] Add other simple conversions like Celsius to Fahrenheit, etc.
- %c_w_dir%   -  getBearing 
- %c_c2f%   -    String(CelsiusToFahrenheit) 
- %c_ms2Bft%   - String(m_secToBeaufort) 
- %c_cm2imp%   - centimeterToImperialLength 
- %c_mm2imp%   - millimeterToImperialLength 
- %c_m2day%   -  String(minutesToDay) 
- %c_m2dh%   -   minutesToDayHour 
- %c_m2dhm%   -  minutesToDayHourMinute 
- %c_s2dhms%   - secondsToDayHourMinuteSecond
2018-03-09 00:31:27 +01:00
Unknown 5821b0709c [issue #1015] Add other simple conversions like Celsius to Fahrenheit, etc.
- %c_w_dir%   -  getBearing 
- %c_c2f%   -    String(CelsiusToFahrenheit) 
- %c_ms2Bft%   - String(m_secToBeaufort) 
- %c_cm2imp%   - centimeterToImperialLength 
- %c_mm2imp%   - millimeterToImperialLength 
- %c_m2day%   -  String(minutesToDay) 
- %c_m2dh%   -   minutesToDayHour 
- %c_m2dhm%   -  minutesToDayHourMinute 
- %c_s2dhms%   - secondsToDayHourMinuteSecond
2018-03-09 00:29:52 +01:00
Unknown ec783fe03b [Rule Events] Add a number of events to handle in rules and awake timer
Changed the sleep checkbox to allow a number of seconds awake from deep sleep.

Also added the following events:

- MQTT#Connected
- WiFi#Connected
- System#Initialized
- Time#Set    Time set by an update from NTP.
- Time#Initialized  Time set for the first time since boot.
- Login#Failed

See #951
2018-03-08 23:00:33 +01:00
Gijs NoorlanderandGitHub 4d749b19fd [Rule Events] Add a number of events to handle in rules and awake timer (#1032)
[Rule Events] Add a number of events to handle in rules and awake timer
2018-03-08 22:55:19 +01:00
Unknown 6a66440a5f [Rule Events] Add a number of events to handle in rules and awake timer
Changed the sleep checkbox to allow a number of seconds awake from deep sleep.

Also added the following events:

- MQTT#Connected
- WiFi#Connected
- System#Initialized 
- Time#Set    Time set by an update from NTP.
- Time#Initialized  Time set for the first time since boot.
- Login#Failed

See #951
2018-03-08 21:43:52 +01:00
ESPEasy release bot 1b23efe48c automaticly updated release notes for mega-20180308 2018-03-08 04:00:08 +01:00
mvdbro 9a9d39763f Second step towards port monitoring without tasks 2018-03-07 16:17:40 +01:00
mvdbro 9f94ef073c First step towards port monitoring without tasks 2018-03-07 14:13:12 +01:00
ESPEasy release bot 9122565431 automaticly updated release notes for v2.0-20180307 2018-03-07 04:00:21 +01:00
ESPEasy release bot 000d2d7c77 automaticly updated release notes for mega-20180307 2018-03-07 04:00:09 +01:00
Unknown 64a0f79e02 [issue #1012] Removed Content-Length header + improved webserver speed
See: Web interface doesn't work on iOS #1012

The operatore+= String function now chunks long strings
2018-03-07 00:56:23 +01:00
Gijs NoorlanderandGitHub c1b945e6c1 [issue #1012] Removed Content-Length header + improved webserver speed (#1027)
[issue #1012] Removed Content-Length header + improved webserver speed
2018-03-07 00:55:48 +01:00
Unknown dbbe6b65dd [issue #1012] Removed Content-Length header + improved webserver speed
See: Web interface doesn't work on iOS #1012

The operatore+= String function now chunks long strings
2018-03-07 00:54:23 +01:00
Gijs Noorlander 92e4a8da9b [CSS] Quick fix for smaller displays (#1026)
[CSS] Quick fix for smaller displays by @doxikus
2018-03-06 21:53:54 +01:00
Gijs NoorlanderandGitHub 4611ef5d87 [CSS] Quick fix for smaller displays (#1026)
[CSS] Quick fix for smaller displays by @doxikus
2018-03-06 21:52:15 +01:00
Unknown 807cc1796d [CSS] Quick fix for smaller displays
Quick fix, created by @doxikus
2018-03-06 21:50:54 +01:00
ESPEasy release bot 40e2d7ec8e automaticly updated release notes for v2.0-20180306 2018-03-06 04:00:17 +01:00
Gijs NoorlanderandDatuX 7318e87965 Fixes P073 plugin for latest TM1637 based 7 segments displays modules (#996) (#1022)
Fixes P073 plugin for latest TM1637 based 7 segments displays modules
2018-03-05 20:17:51 +01:00
ESPEasy release bot 9c3a28439f automaticly updated release notes for v2.0-20180305 2018-03-05 04:00:20 +01:00
ESPEasy release bot 82933ae170 automaticly updated release notes for mega-20180305 2018-03-05 04:00:08 +01:00
Unknown 503fd3555e Merge branch 'v2.0' into mega 2018-03-05 00:40:22 +01:00
Gijs NoorlanderandGitHub 127627a22c [issue #1003 ] Add conversion of wind direction to string (#1014)
[issue #1003 ] Add conversion of wind direction to string
2018-03-05 00:37:44 +01:00
Gijs NoorlanderandGitHub e59401e24f [issue #528] Set DOUT flash mode for all 1M builds (#1013)
[issue #528] Set DOUT flash mode for all 1M builds
2018-03-05 00:36:39 +01:00
Unknown 769f76d3dc [issue #1003 ] Add conversion of wind direction to string
Also made some clean-up of calls to string replacements.
Improved the lookup function to determine the wind direction (was 11.25 degree off)
Now it is also possible to add simple standard conversions like Celcius-Fahrenheit, m/s - Beaufort, etc.
2018-03-05 00:28:32 +01:00
Unknown 4eb7cf0859 [issue #528] Set DOUT flash mode for all 1M builds
See [this elaborate post on the different flash modes](https://www.esp32.com/viewtopic.php?t=1250)
2018-03-04 22:30:13 +01:00
Edwin Eefting a464f638ad automaticly updated release notes for v2.0-20180304b 2018-03-04 18:20:49 +01:00
Edwin Eefting f31cce4182 Merge branch 'v2.0' into mega 2018-03-04 18:14:58 +01:00
Edwin Eefting a5cfe1beec dont build in silent mode to prevent travis timeouts 2018-03-04 18:14:27 +01:00
Edwin Eefting f36fada375 Merge branch 'v2.0' into mega 2018-03-04 18:12:07 +01:00
soifandDatuX d51bce97f5 fixes typos in the issue template (#1006) 2018-03-04 18:09:34 +01:00
soifandDatuX 0368aa4d43 Add OS specific hidden files (#1005) 2018-03-04 18:09:08 +01:00
mvdbro 3c4aa7564f ESP32 - 32 Tasks -redo commit 2018-03-04 17:34:08 +01:00
mvdbro f46b89f1bd Merge branch 'mega' of https://github.com/letscontrolit/ESPEasy into mega 2018-03-04 17:15:43 +01:00
mvdbro 4e2b78056a ESP32 - 32 Tasks
Full reset needed!
2018-03-04 17:14:35 +01:00
Gijs NoorlanderandGitHub d94ce17fd4 Merge pull request #1009 from TD-er/bugfix/factory_reset_twice
[Webserver] Factory Reset was present twice
2018-03-04 16:27:16 +01:00
Unknown cd2c59ba5b [Webserver] Factory Reset was present twice
See issue #1008
2018-03-04 16:26:07 +01:00
mvdbro b6a6943668 ESP32 fix-2 for P020/P044
This time it actually works.
2018-03-04 12:27:38 +01:00
ESPEasy release bot a8fcb420e7 automaticly updated release notes for v2.0-20180304 2018-03-04 04:00:19 +01:00
ESPEasy release bot e1e894d540 automaticly updated release notes for mega-20180304 2018-03-04 04:00:08 +01:00
Unknown d15311e70a Merge branch 'v2.0' into mega 2018-03-04 00:50:43 +01:00
Gijs NoorlanderandGitHub 3ed6564063 [issue #892 ] Only use sensor type when really needed (#1004)
[issue #892 ] Only use sensor type when really needed
2018-03-04 00:45:52 +01:00
Unknown 5f575c0224 [issue #892 ] Only use sensor type when really needed
Only the Domoticz controllers need the sensor type. The rest just needs the number of sensor values.
2018-03-04 00:37:18 +01:00
Gijs NoorlanderandGitHub 34c1ba158f [issue #993] Add %unit% variable in MQTT subscribe topic (PR #1002)
[issue #993] Add %unit% variable in MQTT subscribe topic
2018-03-03 22:40:18 +01:00
Unknown 04ca424085 [issue #993] Add %unit% variable in MQTT subscribe topic 2018-03-03 22:39:09 +01:00
Gijs Noorlander 7a8f476e05 _P072_HDC1080 allow to send values to the controllers (#999)
_P072_HDC1080 add success and break statement.
it seems that without the break statement and success set to true, the values aren't sent back to the controller(s).
2018-03-03 21:30:22 +01:00
Gijs NoorlanderandGitHub eef8391ffc _P072_HDC1080 allow to send values to the controllers (#999)
_P072_HDC1080 add success and break statement.
it seems that without the break statement and success set to true, the values aren't sent back to the controller(s).
2018-03-03 21:29:12 +01:00
Gijs NoorlanderandGitHub d47751c31f Fixes P073 plugin for latest TM1637 based 7 segments displays modules (#996)
Fixes P073 plugin for latest TM1637 based 7 segments displays modules
2018-03-03 20:40:11 +01:00
Gijs Noorlander e42ab85f4b Merge pull request #1000 from uzi18/test3 (more comparisions in IF condition)
support for more comparisions in IF condition: >=,<=,!=,<>,<,>,= also fix extended conditions when first check is not '>'
2018-03-03 20:38:13 +01:00
Gijs NoorlanderandGitHub b048d3f1f8 Merge pull request #1000 from uzi18/test3 (more comparisions in IF condition)
support for more comparisions in IF condition: >=,<=,!=,<>,<,>,= also fix extended conditions when first check is not '>'
2018-03-03 20:37:07 +01:00
Bartlomiej Zimon f94ab3a04a - support for more comparisions in IF conditions: >=,<=,!=,<>,<,>,=
also fix extended conditions when first check is not >
2018-03-03 16:04:44 +01:00
mvdbro 1b9375f83b ESP32 Dallas DS18B20 fix
This is a quick fix for this sensor only. It seems that ESP32 RTOS needs more or differtent interrupt handling for time critical sensor code.
2018-03-03 14:08:20 +01:00
clumsy-stefanandGitHub a77798d18f add success and break statement
it seems that without the break statement and success set to true, the values aren ot sent back to the controller(s).
2018-03-03 13:05:25 +01:00
ESPEasy release bot 3094cb5260 automaticly updated release notes for v2.0-20180303 2018-03-03 04:00:19 +01:00
ESPEasy release bot ec4dd09968 automaticly updated release notes for mega-20180303 2018-03-03 04:00:08 +01:00
Unknown d68a5fb9d4 Merge branch 'v2.0' into mega 2018-03-03 02:23:03 +01:00
Gijs NoorlanderandGitHub 0e67480f46 Merge pull request #995 from TD-er/bugfix/mqtt_proper_case
Bugfix/mqtt proper case
2018-03-03 02:19:49 +01:00
Unknown c32f2cc89d Add AND/OR to rules & prevent unwanted case changes in strings (#994) 2018-03-03 02:09:41 +01:00
Unknown ad489f0db2 [Issue #827] MQTT not using proper case for %sysname% variable.
Some functions and plugins could change strings to lowercase.
Added some check also to help debugging.
2018-03-03 02:03:20 +01:00
Gijs NoorlanderandGitHub d9267fa9c2 Add Task device type to json by @s0170071 (#991)
Add Task device type to json by @s0170071
2018-03-02 22:40:20 +01:00
Unknown e82fb37870 Add Task device type to json by @s0170071
Taken from his branch, he forgot to PR.
2018-03-02 22:30:55 +01:00
Unknown 635c149f12 Merge branch 'v2.0' into mega 2018-03-02 22:16:37 +01:00
Gijs NoorlanderandGitHub 26f00dcdec [issue #293] json output nan values not double quoted (#990)
[issue #293] json output nan values not double quoted
2018-03-02 22:03:07 +01:00
Unknown b2bb1d039b [issue #293] json output nan values not double quoted
Generate valid JSON output
2018-03-02 21:49:06 +01:00
soif 57e256a5fa Fixes P073 plugin for latest TM1637 based 7 segments displays modules 2018-03-02 21:06:45 +01:00
Unknown c58e975b7e revert json to non-chunking #988 from s0170071/mega
revert json to non-chunking
2018-03-02 20:40:13 +01:00
Gijs NoorlanderandGitHub 7d16ffa4a4 revert json to non-chunking #988 from s0170071/mega
revert json to non-chunking
2018-03-02 20:36:42 +01:00
s0170071 856e370ba0 make handle_json return void 2018-03-02 15:00:48 +01:00
s0170071 4df9e7d065 Add git build and local time 2018-03-02 13:58:05 +01:00
s0170071 edb3857e04 revert json to non-chunking 2018-03-02 13:17:20 +01:00
ESPEasy release bot 08312cbcb7 automaticly updated release notes for v2.0-20180302 2018-03-02 04:00:21 +01:00
ESPEasy release bot fb1cc219ee automaticly updated release notes for mega-20180302 2018-03-02 04:00:10 +01:00
Unknown da7329891d Merge branch 'v2.0' into mega 2018-03-02 02:08:55 +01:00
Gijs NoorlanderandGitHub 953a53bb9a Merge pull request #985 from TD-er/bugfix/json_content-length
backport of "rule wildcard" + improve formatting of Webserver's StreamingBuffer
2018-03-02 01:58:53 +01:00
Unknown e9fac7926f [webserver] Layout of code to improve readability
Indentation was completely off, which made it hard to read.
Also added member json_format, which is set at start of stream.
2018-03-02 01:53:40 +01:00
mvdbroandUnknown 810a0b2aa9 Rule wildcard option on literal events
Added wildcard rule filter on literal string events
Changed "sendcontent free"content logging level to 'DEV'
2018-03-01 23:41:42 +01:00
Unknown 7f897bc856 Merge branch 'v2.0' into mega
Merge initiated from GitKraken directly on Letscontrol_it/ESPEasy
2018-03-01 23:31:00 +01:00
Gijs NoorlanderandGitHub 5d9137d1d2 Merge pull request #976 from TD-er/bugfix/P053_PMSx003DustPlugin
[issue #914] _P053_PMSx003 Dust Sensor looses sync
2018-03-01 23:07:38 +01:00
Gijs Noorlander 8de49cd38e Merge pull request #983 from kahvm/mega
Added support for degree sign on LCD1602/2004
2018-03-01 22:42:58 +01:00
Gijs NoorlanderandGitHub 0092ba92b5 Merge pull request #983 from kahvm/mega
Added support for degree sign on LCD1602/2004
2018-03-01 22:41:54 +01:00
Gijs NoorlanderandGitHub fe1c44f6b3 Merge pull request #980 from uzi18/formatout
Format output marge from mega to v2.0
2018-03-01 22:34:08 +01:00
Gijs NoorlanderandGitHub e39d588530 Merge pull request #975 from TD-er/merge/important_fixes_from_mega
Merge/important fixes from mega
2018-03-01 22:31:36 +01:00
kahvmandGitHub 7a4e3d954d Merge pull request #1 from kahvm/support-degree-sign-lcd1602
Support for degree sign on LCD1602
2018-03-01 22:00:41 +01:00
kahvmandGitHub 9dc4fefa0b Support for degree sign on LCD1602
More: https://www.letscontrolit.com/forum/viewtopic.php?p=11875#p11875
2018-03-01 20:09:50 +01:00
Unknown 4ca318f5a6 [Build error fix] Must-keep-focus-when-pressing-buttons...
Quickly commit + merge is never a good idea when some visitors arrive...
Fixed now.
2018-03-01 20:08:51 +01:00
mvdbro 695bb58d64 Rule wildcard option on literal events
Added wildcard rule filter on literal string events
Changed "sendcontent free"content logging level to 'DEV'
2018-03-01 14:29:10 +01:00
Bartlomiej Zimon 608a7212eb Merge branch 'mega' of github.com:letscontrolit/ESPEasy into test3 2018-03-01 03:02:23 +01:00
Bartłomiej ZimońandBartlomiej Zimon 37a24933f5 add format #O to templates to show OFF/ON instead 0/1 (#949)
* - pcfgpio,port,2 sets pin as input
- fix for #222,#702 - we can mix inputs and outputs now

* - extend conditions with AND/OR, now it is possible to simplify rules

test rules:
on test do
  if [test#a]=0 or [test#b]=0 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test2 do
  if [test#a]=1 and [test#b]=1 and [test#c]=1
    event ok
  else
    event nok
  endif
endon

on test3 do
  if [test#a]=1 and [test#b]=1 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test4 do
  if [test#a]=0
    event ok
  else
    event nok
  endif
endon

* - remove Serial print

* - add format #O to templates to show OFF/ON instead 0/1 - eg.: Pump:[Outputs#pump#O]

* - add formating for active low outputs eg.: #O!
2018-02-28 23:06:01 +01:00
Bartlomiej Zimon a6b447600f Merge branch 'v2.0' of github.com:letscontrolit/ESPEasy into v2.0 2018-02-28 22:43:52 +01:00
Unknown 5fbb900e5b [issue #914] Check first 2 bytes of packet 2018-02-28 22:39:34 +01:00
ESPEasy release bot aa5dee01fb automaticly updated release notes for v2.0-20180228 2018-02-28 04:00:20 +01:00
ESPEasy release bot 4e2a5d3b3d automaticly updated release notes for mega-20180228 2018-02-28 04:00:09 +01:00
Unknown 1a44ed6578 [issue #914] _P053_PMSx003 Dust Sensor looses sync
- Use peek instead of read, to make sure a complete packet is in the buffer.
- Flush buffer after processing a packet.
- Increased software serial buffer to the size of 3 packets.
- Peek (+ read garbage) 10 times per second to get the buffer in sync to start with start byte of packet.
- Decent delete + clean up of software serial allocation when changing settings (prevent memory leak)
- Move log String allocation to inside scope of function, not permanent allocated.
- Split into separate functions to make it better readable.
2018-02-28 02:11:33 +01:00
Bartłomiej ZimońandUnknown e86667e37e fix #964, add timeStringToSeconds and use it to compare time conditions (#965)
* - pcfgpio,port,2 sets pin as input
- fix for #222,#702 - we can mix inputs and outputs now

* - extend conditions with AND/OR, now it is possible to simplify rules

test rules:
on test do
  if [test#a]=0 or [test#b]=0 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test2 do
  if [test#a]=1 and [test#b]=1 and [test#c]=1
    event ok
  else
    event nok
  endif
endon

on test3 do
  if [test#a]=1 and [test#b]=1 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test4 do
  if [test#a]=0
    event ok
  else
    event nok
  endif
endon

* - remove Serial print

* - add format #O to templates to show OFF/ON instead 0/1 - eg.: Pump:[Outputs#pump#O]

* - add formating for active low outputs eg.: #O!

* - fix #964, add timeStringToSeconds and use it to compare time conditions

* - fix number of pages available to browse
2018-02-28 00:00:37 +01:00
s0170071andUnknown 0db1f78421 Add Factory Reset button to web interface (#954) 2018-02-27 23:59:31 +01:00
Bartłomiej ZimońandUnknown 780c34846e add format #O to templates to show OFF/ON instead 0/1 (#949)
* - pcfgpio,port,2 sets pin as input
- fix for #222,#702 - we can mix inputs and outputs now

* - extend conditions with AND/OR, now it is possible to simplify rules

test rules:
on test do
  if [test#a]=0 or [test#b]=0 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test2 do
  if [test#a]=1 and [test#b]=1 and [test#c]=1
    event ok
  else
    event nok
  endif
endon

on test3 do
  if [test#a]=1 and [test#b]=1 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test4 do
  if [test#a]=0
    event ok
  else
    event nok
  endif
endon

* - remove Serial print

* - add format #O to templates to show OFF/ON instead 0/1 - eg.: Pump:[Outputs#pump#O]

* - add formating for active low outputs eg.: #O!
2018-02-27 23:58:50 +01:00
Edwin Eefting a4dcc304a9 Merge branch 'v2.0' into mega 2018-02-27 23:43:36 +01:00
Gijs NoorlanderandDatuX a938bc78c1 [issue #968] Use template parser for OLED commands (#974)
N.B. Now even task values can be used in commands, next to special characters.
2018-02-27 23:43:18 +01:00
Gijs NoorlanderandDatuX d2c7743197 [issue #966] Add %sysweekday% and %sysweekday_s% (#973)
- %sysweekday%  number of the day (Sunday = 1)
- %sysweekday_s%  3 letter String of the weekday (Sun, Mon, Tue, ...)
2018-02-27 23:43:01 +01:00
Bartłomiej ZimońandDatuX f0fc20de57 fix #964, add timeStringToSeconds and use it to compare time conditions (#965)
* - pcfgpio,port,2 sets pin as input
- fix for #222,#702 - we can mix inputs and outputs now

* - extend conditions with AND/OR, now it is possible to simplify rules

test rules:
on test do
  if [test#a]=0 or [test#b]=0 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test2 do
  if [test#a]=1 and [test#b]=1 and [test#c]=1
    event ok
  else
    event nok
  endif
endon

on test3 do
  if [test#a]=1 and [test#b]=1 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test4 do
  if [test#a]=0
    event ok
  else
    event nok
  endif
endon

* - remove Serial print

* - add format #O to templates to show OFF/ON instead 0/1 - eg.: Pump:[Outputs#pump#O]

* - add formating for active low outputs eg.: #O!

* - fix #964, add timeStringToSeconds and use it to compare time conditions

* - fix number of pages available to browse
2018-02-27 23:42:20 +01:00
ESPEasy release bot d35a50be17 automaticly updated release notes for v2.0-20180227 2018-02-27 04:00:22 +01:00
ESPEasy release bot 537d4cd1e9 automaticly updated release notes for mega-20180227 2018-02-27 04:00:11 +01:00
Edwin Eefting 62422f4924 Merge branch 'v2.0' into mega 2018-02-27 00:42:15 +01:00
Edwin Eefting 04de145dbb [test suite] changes from mega to 2.0 2018-02-27 00:41:27 +01:00
Edwin Eefting 21840d0b26 [test suite] changes from mega to 2.0 2018-02-27 00:41:21 +01:00
Gijs NoorlanderandDatuX 076ce0127b [build conflict] Renamed ESP32 version of ping (#963)
Had a conflict with the ESP8266 version of ping.
Let's hope I did not break anything with the ESP32 builds @mvdbro does.
2018-02-27 00:10:17 +01:00
Edwin Eefting 226c0a6f83 Merge branch 'v2.0' into mega 2018-02-26 23:03:48 +01:00
s0170071andDatuX 6ffa8d92a6 Add Factory Reset button to web interface (#954) 2018-02-26 22:54:24 +01:00
Bartłomiej ZimońandDatuX dae2cc2f4a add format #O to templates to show OFF/ON instead 0/1 (#949)
* - pcfgpio,port,2 sets pin as input
- fix for #222,#702 - we can mix inputs and outputs now

* - extend conditions with AND/OR, now it is possible to simplify rules

test rules:
on test do
  if [test#a]=0 or [test#b]=0 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test2 do
  if [test#a]=1 and [test#b]=1 and [test#c]=1
    event ok
  else
    event nok
  endif
endon

on test3 do
  if [test#a]=1 and [test#b]=1 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test4 do
  if [test#a]=0
    event ok
  else
    event nok
  endif
endon

* - remove Serial print

* - add format #O to templates to show OFF/ON instead 0/1 - eg.: Pump:[Outputs#pump#O]

* - add formating for active low outputs eg.: #O!
2018-02-26 22:53:15 +01:00
Gijs NoorlanderandDatuX 555ccbe229 [BuildError] StreamingBuffer code cleanup + fix order member initialize (#961)
The order in which the members are defined should also be the order in which they will be initialized.

Also applied #958
2018-02-26 22:52:27 +01:00
mvdbro d277d22914 Fix ESP32 compile errors 2018-02-26 14:26:17 +01:00
ESPEasy release bot b5e4994392 automaticly updated release notes for v2.0-20180226 2018-02-26 04:00:21 +01:00
ESPEasy release bot cbdddf8c06 automaticly updated release notes for mega-20180226 2018-02-26 04:00:08 +01:00
Gijs NoorlanderandGitHub 8b5d22a081 Merge pull request #948 from TD-er/build/remove_duplicate_library
[softwareSerial] Remove duplicate with only capilization as difference
2018-02-25 21:29:09 +01:00
Unknown 88fc0a8445 [softwareSerial] Remove duplicate with only capilization as difference 2018-02-25 21:27:57 +01:00
Gijs NoorlanderandGitHub ec9187d038 Merge pull request #947 from letscontrolit/v2.0
V2.0 => Mega: Ping library and Webserver@LowMemory
2018-02-25 21:20:37 +01:00
s0170071andUnknown 51ede17d2a Update WebServer.ino 2018-02-25 21:15:33 +01:00
s0170071andUnknown 97ee69b371 V20 Webserver@LowMemory 2018-02-25 21:15:24 +01:00
Unknown f77ce9c8f7 [ping lib] Added ping library
It was linked as a dependency in PlatformIO.ini, but apparently will add complexity to Arduino IDE users.
2018-02-25 21:14:07 +01:00
Edwin Eefting 99cc6f72af Merge branch 'v2.0' into mega 2018-02-25 17:18:59 +01:00
Gijs NoorlanderandDatuX 848f43b704 [2k Webserver] Proper initialisation of StreamingBuffer members. (#941)
Was reported in Travis as build error.
2018-02-25 17:17:47 +01:00
Edwin Eefting 3a5ef5da81 device page doesnt need next/previous page buttons anymore 2018-02-25 17:12:45 +01:00
Edwin Eefting 3527b69718 Merge branch 'v2.0' into mega 2018-02-25 16:57:03 +01:00
Gijs NoorlanderandDatuX 54628bfca9 [timeouts] Improve response when hosts are not reachable (#939)
See #922 and #847

Problem with DNS resolve is that it is quite slow when resulting in a failure and it tends to keep the ESP occupied and make it unresponsive.

Changed the way it is connecting to a controller.
Not sure if http requests are still OK, maybe we should make an exception for those when selected to use DNS.
2018-02-25 14:15:56 +01:00
Gijs NoorlanderandDatuX 72ff745eff [Mega] rename SoftwareSerial lib #930 (#937)
Just a rename of the library directory + some notes in the library description to indicate the differences.
2018-02-25 14:12:59 +01:00
Gijs NoorlanderandDatuX aed566b6db [v2.0] Use ESPeasySoftwareSerial (#936)
This one has virtual destructor and will use less memory.
See issue #930.
2018-02-25 14:12:33 +01:00
Gijs NoorlanderandDatuX 504ea0c813 [v2.0 merge] 2kwebserver_merge_to_mega #929 (#934)
The v2.0 branch merge of the 2k webserver PR.
As test build, please try [these builds](https://www.dropbox.com/s/ky6ldixh6wgzd8k/2k_webserver_build_v2.0_20180221.rar?dl=0)
2018-02-25 14:12:11 +01:00
Gijs NoorlanderandDatuX 4ca5ef3f72 [v2.0] Added Vcc-binaries to deploy process #933 (#935)
PR for the V2.0 branch to add the VCC binaries to the deploy process.
2018-02-25 14:11:34 +01:00
Michael SchröderandDatuX dd9db3b557 Added Vcc-binaries to deploy process (#933) 2018-02-25 14:11:25 +01:00
Bartłomiej ZimońandDatuX 9c531b30bc - extend conditions with AND/OR, now it is possible to simplify rules (#932)
* - pcfgpio,port,2 sets pin as input
- fix for #222,#702 - we can mix inputs and outputs now

* - extend conditions with AND/OR, now it is possible to simplify rules

test rules:
on test do
  if [test#a]=0 or [test#b]=0 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test2 do
  if [test#a]=1 and [test#b]=1 and [test#c]=1
    event ok
  else
    event nok
  endif
endon

on test3 do
  if [test#a]=1 and [test#b]=1 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test4 do
  if [test#a]=0
    event ok
  else
    event nok
  endif
endon

* - remove Serial print
2018-02-25 14:04:55 +01:00
Bartłomiej ZimońandDatuX 67c8477a61 provide System@Sleep event (#875) (#931)
- provide System@Sleep event
- fixes #870 (mqtt not sent before sleep)
- call deepsleep at the end of loop - so we know all is done
2018-02-25 14:01:40 +01:00
Edwin Eefting cd30b81202 Merge branch '2kwebservermergetomega' of https://github.com/s0170071/ESPEasy into mega 2018-02-25 13:55:28 +01:00
s0170071andDatuX 550881faa5 Memtracker (#927)
* preparations for lwip2

* Add CRC32 to settings

* Add CRC to progmem

* Add crc of program memory to stettings and security settings

.. so that there is a warning if the settings are used by another binary than they were written with.

* Moved to md5

* Flash included, moved to MD5 now

* Broken comment

* Stability improvements

free memory went as low as 3000 bytes which made the webserver unresponsive.

* Add binary filename to crc2.py and sysinfo

* Update WebServer.ino

* Memory tracker

displays debug memory trace

WD   : Uptime 3 ConnectFailures 0 FreeMem 15304
Memtrace
0: lowest: 4456  PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 handle_hardware-> 15192 sendWebPage-> 9672 sendWebPageChunkedData-> 5816 sendWebPageChunkedData-> 5128 sendWebPageChunkedData-> 4456 sendWebPageChunkedData-> 4456 
1: lowest: 4456  PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 handle_hardware-> 15192 sendWebPage-> 9672 sendWebPageChunkedData-> 5816 sendWebPageChunkedData-> 5128 sendWebPageChunkedData-> 4456 
2: lowest: 3768  PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 PluginCall_s (35)-> 15328 handle_hardware-> 15192 sendWebPage-> 9672 sendWebPageChunkedData-> 5816 sendWebPageChunkedData-> 5128 sendWebPageChunkedData-> 4456 sendWebPageChunkedData-> 4456 sendWebPageChunkedData-> 3768 
WD   : Uptime 4 ConnectFailures 0 FreeMem 15304

* Update Misc.ino
2018-02-25 13:14:57 +01:00
Gijs NoorlanderandDatuX 3d07466904 [MQTT] LWT "Connected" message doesn't have the retained flag (#925)
See comments of [Superpiffer](https://github.com/letscontrolit/ESPEasy/commit/a93a078c0b8ae4090c22717eacc8bc8ba92ad780#commitcomment-27718045)
2018-02-25 13:10:58 +01:00
s0170071 ed45945f21 Fix compile error when SD card is enabled 2018-02-24 18:03:38 +01:00
s0170071 f13abe8922 Removed double entry on info page 2018-02-24 17:32:44 +01:00
s0170071 34b0a683a9 fix travis 2018-02-24 17:10:52 +01:00
s0170071 9ab10437b5 Merge remote-tracking branch 's0170071/2kwebservermergetomega' into 2kwebservermergetomega 2018-02-24 16:59:54 +01:00
s0170071 b0b7408522 variable timeout 2018-02-24 16:59:46 +01:00
s0170071 b104942db9 Merge remote-tracking branch 's0170071/2kwebservermergetomega' into 2kwebservermergetomega 2018-02-24 16:57:17 +01:00
s0170071 a694b658b1 Merge remote-tracking branch 's0170071/2kwebservermergetomega' into 2kwebservermergetomega 2018-02-24 16:57:07 +01:00
s0170071 cb07a0d342 Merge remote-tracking branch 's0170071/2kwebservermergetomega' into 2kwebservermergetomega 2018-02-24 16:54:06 +01:00
s0170071 1ceaad04ec Merge branch '2kws_dynpayload' into 2kwebservermergetomega 2018-02-24 16:53:56 +01:00
s0170071 5cbf0c1e38 Merge branch '2kws_dynpayload' into 2kwebservermergetomega 2018-02-24 16:48:14 +01:00
Bartlomiej Zimon 4951f294b9 - remove Serial print 2018-02-24 16:34:30 +01:00
s0170071 ef0ef092f0 Merge remote-tracking branch 's0170071/2kws_dynpayload' into 2kws_dynpayload 2018-02-24 16:24:44 +01:00
s0170071ands0170071 46d3ae6a2b Merge branch 'mega' into 2kwebservermergetomega 2018-02-24 16:24:32 +01:00
Bartlomiej Zimon ef1bf646ab Merge branch 'mega' of github.com:letscontrolit/ESPEasy into mega 2018-02-24 10:32:09 +01:00
Bartlomiej Zimon f72a48ffc2 - extend conditions with AND/OR, now it is possible to simplify rules
test rules:
on test do
  if [test#a]=0 or [test#b]=0 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test2 do
  if [test#a]=1 and [test#b]=1 and [test#c]=1
    event ok
  else
    event nok
  endif
endon

on test3 do
  if [test#a]=1 and [test#b]=1 or [test#c]=0
    event ok
  else
    event nok
  endif
endon

on test4 do
  if [test#a]=0
    event ok
  else
    event nok
  endif
endon
2018-02-24 10:19:12 +01:00
ESPEasy release bot da54ddda78 automaticly updated release notes for mega-20180224 2018-02-24 04:00:06 +01:00
Bartłomiej ZimońandBartlomiej Zimon 03ee569510 provide System@Sleep event (#875)
- provide System@Sleep event
- fixes #870 (mqtt not sent before sleep)
- call deepsleep at the end of loop - so we know all is done
2018-02-23 19:57:01 +01:00
mvdbro c24205713d ESP32 fixed P020 and P044 2018-02-23 15:21:48 +01:00
s0170071andGitHub 52d4cb804e Merge branch 'mega' into 2kwebservermergetomega 2018-02-23 15:07:18 +01:00
mvdbro ae077de72b Fix ESP32 compile errors 2018-02-23 14:38:14 +01:00
s0170071 86fa5ec6ae Merge into mega
... and removed obsolete function
2018-02-23 14:07:46 +01:00
s0170071 41c9d68422 Merge remote-tracking branch 'origin/mega' into 2kwebservermergetomega 2018-02-23 14:00:19 +01:00
ESPEasy release bot e713da5d79 automaticly updated release notes for mega-20180223 2018-02-23 04:00:07 +01:00
GHolliandDatuX edc261ca2b * BugFix: According to the data sheet, the offset for the detection range values (command byte 0x99) is 3..4 instead of 6..7 (#921)
Reference: http://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf
* Optimisation of the code
  - Using an enumeration for the commands to send
  - Removing redundancy of the commands stored in flash
  - Creating a function for the checksum calculation
2018-02-22 19:11:35 +01:00
s0170071andDatuX 8f4a52a6f1 Include name of binary file in crc2.py and sysinfo (#918)
* preparations for lwip2

* Add CRC32 to settings

* Add CRC to progmem

* Add crc of program memory to stettings and security settings

.. so that there is a warning if the settings are used by another binary than they were written with.

* Moved to md5

* Flash included, moved to MD5 now

* Broken comment

* Stability improvements

free memory went as low as 3000 bytes which made the webserver unresponsive.

* Add binary filename to crc2.py and sysinfo

* Update WebServer.ino
2018-02-22 18:55:45 +01:00
ESPEasy release bot af519748a6 automaticly updated release notes for v2.0-20180221 2018-02-21 04:00:20 +01:00
ESPEasy release bot c04b80b2f1 automaticly updated release notes for mega-20180221 2018-02-21 04:00:09 +01:00
Edwin Eefting cdbc2498c1 [test suite] corrected PUYA test. added erase/build/flash for all chips. preparations for full automatic hardware regression testing 2018-02-21 02:44:57 +01:00
Edwin Eefting 78997b4329 Merge branch 'v2.0' into mega 2018-02-21 02:11:18 +01:00
Edwin Eefting 2bece45712 apply PUYA patch to all available frameworks 2018-02-21 02:08:06 +01:00
Gijs NoorlanderandDatuX 10c73a001a [issue #899 ] Backport of DHT22 implementation on Mega (#913)
It has quite some changes, but according to [litrinhos](https://github.com/letscontrolit/ESPEasy/issues/899#issuecomment-366940174) it works, instead of the v2.0 implementation.
2018-02-21 01:26:08 +01:00
GHolliandDatuX 790a946cf6 Optimisation: Save RAM (freeing RAM by moving static data from RAM to program memory). (#910) 2018-02-21 00:02:59 +01:00
Stanislav MihicandDatuX 69c5be6489 Frontend (#906)
* Updating template structure, adding viewport meta name for mobile devices, feature ready for responsive layout

* Adding meta viewport, feature ready nad support for mobile devices, responsive layout, update template structure, adding article html5 tag, easier to style interface, find/replace uppercase to lowercase, matter of elegance and preference code readability :-)

* revert to default state and change only template related lines

* final check, revert uppercase

* Last template changes, lost in undo process :-)

* h6 footer TR
2018-02-20 23:54:46 +01:00
ESPEasy release bot 233ca2bf43 automaticly updated release notes for v2.0-20180220 2018-02-20 04:00:19 +01:00
ESPEasy release bot 3de400fc91 automaticly updated release notes for mega-20180220 2018-02-20 04:00:08 +01:00
Edwin Eefting edeea02f71 SENSOR_TYPE_TEMP_BARO changed, was probably implemented incorrectly before 2018-02-20 01:56:40 +01:00
Edwin Eefting 6fae1f79d8 function was moved to StringConverter.inp 2018-02-20 01:20:57 +01:00
Edwin Eefting 1222e04caf Merge branch 'v2.0' into mega 2018-02-20 01:08:29 +01:00
Bartłomiej ZimońandDatuX f38973aad6 - pcfgpio,port,2 sets pin as input (#897)
- fix for #222,#702 - we can mix inputs and outputs now
2018-02-20 00:57:55 +01:00
Gijs NoorlanderandDatuX b31b1d913f [issue #893] Fix globalSync not working when no controllers active (#896)
* [issue #893] Fix globalSync not working when no controllers active

See #893 and [this topic on the forum](https://www.letscontrolit.com/forum/viewtopic.php?p=24851#p24851)

* [issue #893] Global Sync call when no other controllers active
2018-02-20 00:52:43 +01:00
Gijs NoorlanderandDatuX fa3d4af8cb [Cleanup] Move String manipulating functions to single file (#895)
Makes it easier to re-use functions and improve them.
2018-02-20 00:52:18 +01:00
Gijs NoorlanderandDatuX 29320aab90 [isue #877] Add VCC enable firmware file to release list (#894)
* [isue #877] Add VCC enable firmware file to release list

Added one for the testing build.
Not sure if we should add one for every build, since these flags will lead to an explosion of release versions. 
But at least we will test builds with FEATURE_ADC_VCC define enabled more often.

* Add define FEATURE_ADC_VCC to the PUYA build

Since it is so hard to make a puya version on your own.
2018-02-20 00:50:56 +01:00
Gijs NoorlanderandGitHub 3bc8609611 Merge pull request #905 from TD-er/bugfix/DHTinit_sequence_wrong
[issue #899] DHT22 readings not received
2018-02-20 00:16:51 +01:00
Gijs NoorlanderandGitHub c43d6b3769 Merge pull request #904 from TD-er/feature/log_event_name
[Event Log] Add event name to event processing time log
2018-02-20 00:16:19 +01:00
Gijs NoorlanderandGitHub e9e2ea32ed Merge pull request #903 from TD-er/bugfix/OpenHAB_MQTT_topic_parser_fix
[issue #847] Fix last letter of command is cut in OpenHAB MQTT
2018-02-20 00:15:51 +01:00
Unknown 24b7d1f438 [issue #899] DHT22 readings not received
Applied fix as suggested here: https://github.com/adafruit/DHT-sensor-library/issues/48
2018-02-20 00:04:13 +01:00
Unknown 4febf08501 [Event Log] Add event name to event processing time log
As suggested on the forum by [Methusalem](https://www.letscontrolit.com/forum/viewtopic.php?p=24887#p24887)
2018-02-19 23:31:19 +01:00
Unknown 7f4eae19f4 [issue #847] Fix last letter of command is cut in OpenHAB MQTT
Thanks [jivkopavlovski](https://github.com/letscontrolit/ESPEasy/commit/f23d9fa3d3def506e1401c2208c8a19a1d5d1da2#commitcomment-27660279) for pointing this out (and testing ofcourse)
2018-02-19 22:57:57 +01:00
ESPEasy release bot c13952d04c automaticly updated release notes for v2.0-20180219 2018-02-19 04:00:19 +01:00
ESPEasy release bot 3032463917 automaticly updated release notes for mega-20180219 2018-02-19 04:00:09 +01:00
Bartlomiej Zimon f5e84a155e - pcfgpio,port,2 sets pin as input
- fix for #222,#702 - we can mix inputs and outputs now
2018-02-19 01:38:52 +01:00
Edwin Eefting bbb97bfc7e Merge branch 'v2.0' into mega 2018-02-18 19:23:09 +01:00
Gijs NoorlanderandDatuX e51f7683a5 [issue #890] Split overlap for both Domoticz controllers to helper (#891)
* [issue #890] Split overlap for both Domoticz controllers to helper

Both Domoticz controllers had quite some overlap in code.
And where they differ, one of them was faulty and/or already fixed.

Now this overlap is split into a Domoticz helper file to keep code duplication to a minimum.

* [issue #890] Fix some wierd data corruption

Do not store references in a Json object, but just the string :)

* [Domoticz] Add WiFi strength and battery info
2018-02-18 13:18:23 +01:00
Gijs NoorlanderandDatuX e747756dd2 [Build Mega] Fix for Build Mega 20180217 (#889) 2018-02-18 13:17:02 +01:00
Gijs NoorlanderandDatuX 1ad6fd6ea0 [issue #885] MAC address as system variable (#887)
%mac% will be replaced by the MAC-address of the ESP board.
%mac_int% will show the integer representation of the last 24 bits (MAC address without the OUI part) for use in rules.
2018-02-18 13:16:42 +01:00
ESPEasy release bot d2ec15a4bf automaticly updated release notes for v2.0-20180218 2018-02-18 04:00:11 +01:00
Gijs NoorlanderandDatuX f23d9fa3d3 [issue #847 ] OpenHAB MQTT rewrite topic parser (#886)
* [issue #847 ] OpenHAB MQTT rewrite topic parser

When OpenHAB MQTT controller was selected, the web interface becomes unresponsive when the controller tab was selected.
Also the ESP almost freezes when MQTT messages were sent.

This is an attempt to make them work faster.
Also a lot of string manipulation, copies and resizes are now no longer needed and the received values are checked to be valid int or float before used.

* signed unsigned warning
2018-02-17 13:18:52 +01:00
s0170071 6df5840db9 Fixed String redeclaration 2018-02-17 09:45:40 +01:00
s0170071 5f79e4b922 Merge Webserver 2018-02-17 09:43:46 +01:00
s0170071 e058507b9a Merge remote-tracking branch 'origin/mega' into 2kRamWebserver 2018-02-17 09:26:32 +01:00
ESPEasy release bot 3cea522ec4 automaticly updated release notes for v2.0-20180217 2018-02-17 04:00:18 +01:00
ESPEasy release bot 5c4defdf6e automaticly updated release notes for mega-20180217 2018-02-17 04:00:07 +01:00
Edwin Eefting e58ea2a3fe Merge branch 'v2.0' into mega 2018-02-16 21:43:23 +01:00
Gijs NoorlanderandDatuX a93a078c0b [issue #869] Added 'LWT' to last will topic and improved CPU load (#883)
* [issue #869] Added 'LWT' to last will topic and improved CPU load

See #869 for discussion on Last Will Topic.
Also changed the way it tried to reconnect to make it return a lot faster when connection is not (yet) possible and call the PubSubClient::loop() at a much slower pace to reduce CPU usage. (See #847)
This higher CPU load was probably introduced when fixing #683.

* [MQTT] Fix error reporting success status with longer payloads

Applied PR https://github.com/knolleary/pubsubclient/pull/360/files

* made MQTT_CALLBACK_SIGNATURE for esp32 functional

Applied PR https://github.com/knolleary/pubsubclient/pull/336
2018-02-16 21:32:53 +01:00
Gijs NoorlanderandDatuX 0e0e7be95a [OLED Framed] ESP Easy logo (#876) 2018-02-16 21:29:44 +01:00
Bartłomiej ZimońandDatuX 2b7a61469f provide System@Sleep event (#875)
- provide System@Sleep event
- fixes #870 (mqtt not sent before sleep)
- call deepsleep at the end of loop - so we know all is done
2018-02-16 21:28:52 +01:00
Gijs NoorlanderandDatuX ce02c9e039 [issue #853] Favicon.ico (#874)
* [issue #853] Favicon.ico

Added a very small favicon.ico of the ESPeasy logo. (1150 Bytes, 16x16)

* [Favicon] Added instructions to change icon.

In the comments. Just use 'xxd' from the (Linux) commandline.
2018-02-16 21:27:58 +01:00
Gijs NoorlanderandDatuX 1e9dc1d14c [issue 866] Try to stop logging to serial when serial is not read. (#868)
First attempt, not clear yet how to detect it.
See #866

Also preparation for future improvement on logging. (to detect whether there is some logging active so Strings may not have to be prepared.
2018-02-16 21:26:18 +01:00
s0170071andGitHub 75f1c6c140 Update .gitignore 2018-02-14 20:56:44 +01:00
ESPEasy release bot 9a6f7360da automaticly updated release notes for v2.0-20180214 2018-02-14 04:00:21 +01:00
s0170071 4e537461f2 Fix travis
unsigned int -> int comparison
2018-02-13 21:59:18 +01:00
s0170071 dc7bb12581 4->12 Devices per page
that was easy :-)
2018-02-13 21:53:04 +01:00
s0170071andGitHub 0c80cdc119 Merge branch 'mega' into 2kRamWebserver 2018-02-13 21:36:05 +01:00
s0170071 37210031b7 Cleanup and +1k Ram
- on 2.4.0 git /low mem LWIP ram goes never below 20k, during TX core dives down to 18,7k (each main menu clicked once, plain new config.)
- Fixed json output
- cleanup of send function#
- un-split css, transfer to buffer byte by byte (prevents 1.7k temporary string)
- removed commented-out function
2018-02-13 21:28:10 +01:00
s0170071 baa1df620f Travis... 2018-02-12 16:55:24 +01:00
s0170071 a310811919 fix Travis
uninitialized variable.
2018-02-12 13:46:36 +01:00
s0170071 e9dd5da690 Add Ram usage debug message
usually shows: 
Ram usage: Webserver only: 1048 including Core: 3120
2018-02-12 11:48:01 +01:00
s0170071 f9c25489d1 fix download page
don't stream this one.
2018-02-12 09:26:00 +01:00
s0170071 46ee928b07 navMenuIndex
fixed order. Needs to be set before stream starts.
2018-02-12 08:11:15 +01:00
s0170071 3af102f2ad Unused variable 2018-02-12 07:07:12 +01:00
s0170071 ca53ec0263 fix travis
unused variable
2018-02-12 06:48:46 +01:00
s0170071 5ca7c073f1 fix travis 2018-02-12 06:34:19 +01:00
s0170071 3f68154819 Merge branch 'webserverminmem' into mega 2018-02-11 22:24:17 +01:00
s0170071 7b1c4483bb Merge remote-tracking branch 's0170071/webserverminmem' into webserverminmem 2018-02-11 22:23:50 +01:00
s0170071 572d9c0714 2k Webserver 2018-02-11 22:23:38 +01:00
s0170071 48643cf87e Merge remote-tracking branch 's0170071/webserverminmem' into webserverminmem 2018-02-09 12:28:17 +01:00
s0170071 9ea594afeb Optimized memory usage
memory never goes below 10k now. 
Added wait for memory return on header send, 
Added wait for memory return on chunk end send,
removed duplicate of data stashing with  getWebPageTemplateVar
2018-02-09 12:27:45 +01:00
s0170071 49a783c381 "Content-Type","text/html" 2018-02-08 20:11:07 +01:00
s0170071 c9b81f7ab9 Wait for memory be like before send chunked
goes not below 9680 bytes now
2018-02-08 19:57:16 +01:00
s0170071 91c6e3af61 Does Travis like extern "C" ? 2018-02-08 17:31:26 +01:00
s0170071 faeb921bcf Merge remote-tracking branch 's0170071/webserverminmem' into webserverminmem 2018-02-08 17:13:01 +01:00
s0170071 9928f56ad3 try fix travis 2018-02-08 17:12:53 +01:00
s0170071andGitHub 61d27084c1 trigger travis re-compile
trigger travis re-compile to see if the compile failure was due to a quick re-submission.
2018-02-08 10:04:07 +01:00
s0170071 e5393a9fa4 Adapted timeout 2018-02-07 22:08:43 +01:00
s0170071 1cbc49021a tcp_cleanup for LWIP1 & 2 2018-02-07 22:04:39 +01:00
s0170071 84f389b44e Timeout 100ms 2018-02-07 17:29:16 +01:00
s0170071 765775e22f Adjusted to min 7k free 2018-02-07 17:21:28 +01:00
s0170071 02c97c4513 Webserver min memory
memory went as low as 3k, so wait for it to return ...
2018-02-07 17:15:23 +01:00
sassod eee55a92d9 Merge remote-tracking branch 'refs/remotes/letscontrolit/mega' into mega 2017-10-11 07:21:45 +02:00
sassod 21398fbf8a Merge remote-tracking branch 'refs/remotes/letscontrolit/mega' into mega 2017-09-23 20:05:30 +02:00
85 changed files with 7831 additions and 3984 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
### Steps to reproduce
How can we trigger this problem?
Does the problem presist after powering off and on? (just resetting isnt enough sometimes)
Does the problem persists after powering off and on? (just resetting isn't enough sometimes)
### Expected behavior
Tell us what should happen?
+11
View File
@@ -1,7 +1,18 @@
## OS Specific Hidden Files ####
# MacOSX Finder *****
.DS_Store
# Fuse FileSystem ***
.fuse_hidden*
## PlatformIO ##################
.pioenvs
.clang_complete
.gcc-flags.json
.piolibdeps
## Project #####################
lib/readme.txt
src/Custom.h
+1 -1
View File
@@ -27,7 +27,7 @@ install:
script:
# - cppcheck --enable=warning src/*.ino -q --force -I src --include=src/ESPEasy.ino --error-exitcode=1
# - ./memanalyzer.py ~/.platformio/packages/toolchain-xtensa/bin/xtensa-lx106-elf-objdump
- PLATFORMIO_BUILD_FLAGS="-D CONTINUOUS_INTEGRATION" platformio run -s
- PLATFORMIO_BUILD_FLAGS="-D CONTINUOUS_INTEGRATION" platformio run
# patch platformio core libs for PUYA bug (https://github.com/letscontrolit/ESPEasy/issues/650)
- cd patches; ./check_puya_patch; cd ..
+3 -1
View File
@@ -12,11 +12,13 @@ for ENV in \
normal_ESP8285_1024 \
test_ESP8266_1024\
test_ESP8266_4096\
test_ESP8266_4096_VCC\
test_ESP8285_1024\
dev_ESP8266_1024\
dev_ESP8266_4096\
dev_ESP8285_1024\
dev_ESP8266PUYA_1024;\
dev_ESP8266PUYA_1024\
dev_ESP8266PUYA_1024_VCC;\
do
echo
echo "### Deploying environment $ENV for version $VERSION"
+24 -4
View File
@@ -1,10 +1,12 @@
import sys
import binascii
import struct
import md5
MD5DUMMY = "MD5_MD5_MD5_MD5_BoundariesOfTheSegmentsGoHere..."
import os
MD5DUMMY = "MD5_MD5_MD5_MD5_BoundariesOfTheSegmentsGoHere..." #48 chars
FILENAMEDUMMY = "ThisIsTheDummyPlaceHolderForTheBinaryFilename..." #48 chars
MemorySegmentStart,MemorySegmentEnd,MemoryContent=[],[],[]
##################################################################
@@ -14,12 +16,15 @@ def showSegments (fileContent,offset):
global MemorySegmentStart, MemorySegmentEnd, MemoryContent
header = struct.unpack("ii", fileContent[offset:offset+8])
herestr =""
herestr2 =""
MemorySegmentStart.append(struct.pack("I",header[0]))
MemorySegmentEnd.append(struct.pack("I",header[0]+header[1]))
MemoryContent.append(fileContent[offset+8:offset+8+header[1]])
if fileContent.find( MD5DUMMY, offset+8, offset+8+header[1]) >0 :
herestr= " <-- CRC is here."
print ("SEGMENT "+ str(len(MemorySegmentStart)-1)+ ": memory position: " + hex(header[0])+" to " + hex(header[0]+header[1]) + " length: " + hex(header[1])+herestr)
if fileContent.find( FILENAMEDUMMY, offset+8, offset+8+header[1]) >0 :
herestr2= " <-- filename is here."
print ("SEGMENT "+ str(len(MemorySegmentStart)-1)+ ": memory position: " + hex(header[0])+" to " + hex(header[0]+header[1]) + " length: " + hex(header[1])+herestr+herestr2)
#print ("first byte positoin in file: " + hex( offset+8))
#print ("last byte postion in file: " + hex(offset+8+header[1]-1))
return (8+offset+ header[1]); # return start of next segment
@@ -82,6 +87,17 @@ while len(startArray) < 16 :
if (len(endArray) + len (startArray)) != 32 :
print("ERROR: please make sure you add / remove padding if you change the semgents.")
BinaryFileName = "";
if fileContent.find( FILENAMEDUMMY) < 0:
print("ERROR: FILENAMEDUMMY dummy not found in binary")
else:
BinaryFileName=os.path.basename(FileName) +"\0"
if len(BinaryFileName) >48: # check that filename is <48 chars
BinaryFileName=BinaryFileName[0:48] # truncate if necessary. 49th char in ESP is zero already
else:
BinaryFileName= BinaryFileName.ljust(48,'\0'); # pad with zeros.
if fileContent.find( MD5DUMMY) < 0:
print("ERROR: MD5 dummy not found in binary")
else:
@@ -91,6 +107,10 @@ else:
md5hash = m.digest()
print("MD5 hash: "+ m.hexdigest())
print("\nwriting output file:\n" + FileName)
fileContent=fileContent.replace(MD5DUMMY,md5hash+startArray+endArray)
fileContent=fileContent.replace(FILENAMEDUMMY,BinaryFileName)
with open(FileName, mode='wb') as file: # b is important -> binary
file.write(fileContent.replace(MD5DUMMY,md5hash+startArray+endArray))
file.write(fileContent)
#k=input("press close to exit")
+622
View File
@@ -1,3 +1,625 @@
-------------------------------------------------
Changes in release mega-20180321 (since mega-20180320)
-------------------------------------------------
Release date: Wed Mar 21 04:00:08 CET 2018
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180320
Unknown (2):
[wifi] Setup with factory settings could not complete
[wifi] Setup with factory settings could not complete
-------------------------------------------------
Changes in release mega-20180320 (since mega-20180319)
-------------------------------------------------
Release date: Tue Mar 20 04:00:10 CET 2018
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180319
Gijs Noorlander (1):
Revert "Merge pull request #1116 from TD-er/feature/allow_own_defaults"
Unknown (3):
Revert "Merge pull request #1116 from TD-er/feature/allow_own_defaults"
[issue #1097] WiFi connect with deepsleep enabled trigger watchdog reset
[issue #1097] WiFi connect with deepsleep enabled trigger watchdog reset
es-ka (2):
Fix wiring description for SN75176 transceiver
Fix wiring description for SN75176 transceiver
-------------------------------------------------
Changes in release mega-20180319 (since mega-20180316)
-------------------------------------------------
Release date: Mon Mar 19 04:00:11 CET 2018
Bartlomiej Zimon (5):
Add download button for current rule set
- add encoder write #1086
- fix success setting
- fix P073 success setting in PLUGIN_WRITE callback
- initialize pointer in P073
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180316
Gijs Noorlander (6):
Add download button for current rule set (#1102)
- add encoder write command #1086 (#1103)
Changed so that running all tasks immediately with deep sleep enabled… (#1110)
Merge pull request #1112 from uzi18/fix-p073
Merge pull request #1114 from TD-er/feature/wifi_details_json
Merge pull request #1118 from TD-er/bugfix/mqtt_publish_after_deep_sleep
Panayotis Kouvarakis (1):
Changed so that running all tasks immediately with deep sleep enabled only happens on first iteration after wake up
Unknown (11):
[WiFi] Try to minimize effect of WiFi interruptions
[Relaxed WiFi] Perform WiFi initialization in steps
[Travis error] Some #include test that wasn't meant to be included
[JSON] Add uint name (#1099) and WiFi information (PR #1113)
[issue #1007] Allow user specific data in separate file
#ifndef instead of #ifdef
[issue #1007] Add other defines as suggested by @uzi18
[issue #1097] MQTT publish after deep sleep
Merge pull request #1113 from TD-er/feature/reduce_impact_wifi_disconnect
Merge pull request #1116 from TD-er/feature/allow_own_defaults
[merge] MIssing #endif due to merging.
s0170071 (2):
changed memory tracker to uint64_t for the ESP32
Keep uint. Just change the init value.
-------------------------------------------------
Changes in release mega-20180316 (since mega-20180315)
-------------------------------------------------
Release date: Fri Mar 16 04:00:11 CET 2018
Bartlomiej Zimon (3):
- move all structs from ESPEasy.ino into header file - add some fix for headers - add const to rtttl notes array
Merge branch 'mega' of github.com:letscontrolit/ESPEasy into mega
Merge branch 'mega' of github.com:letscontrolit/ESPEasy into mega
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180313
Gijs Noorlander (3):
MCP3221 allow values for calibration (#1073)
[issue #1066] Fix Webserver handle_control (#1079)
Fixed multi instance problem on SHT3x #433 (#1081)
JK (1):
Fixed #433
Unknown (9):
[issue #1066] Fix Webserver handle_control
- move all structs from ESPEasy.ino into header file
[v2.0 split globals] Base split on v2.0 version of ESPEasy.ino
[issue #1057] AM PM display issue
[issue #993] variable in MQTT subscribe topic
[issue #951] Changed System#Initialized => System#Wake
[issue #1057] AM PM display issue
[issue #993] variable in MQTT subscribe topic
[issue #951] Changed System#Initialized => System#Wake
mvdbro (4):
#893 part1, send messages
Custom controller GUI option
#893, part 2 receiving
Rules fix
sassod (1):
12bit ADC values acceted up to 4095
-------------------------------------------------
Changes in release mega-20180315 (since mega-20180314)
-------------------------------------------------
Release date: Thu Mar 15 04:00:08 CET 2018
mvdbro (3):
Custom controller GUI option
#893, part 2 receiving
Rules fix
-------------------------------------------------
Changes in release mega-20180314 (since mega-20180313)
-------------------------------------------------
Release date: Wed Mar 14 04:00:11 CET 2018
mvdbro (1):
#893 part1, send messages
-------------------------------------------------
Changes in release mega-20180313 (since mega-20180312)
-------------------------------------------------
Release date: Tue Mar 13 04:00:11 CET 2018
Bartlomiej Zimon (4):
- fix for #1065
- remove double trimm()
- fix for #1065
- remove double trimm()
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180312
Unknown (1):
Rule Engine minor fix and added dev debugging
mvdbro (1):
ESP32 C010 fix
-------------------------------------------------
Changes in release mega-20180312 (since mega-20180311)
-------------------------------------------------
Release date: Mon Mar 12 04:00:07 CET 2018
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180311
Unknown (4):
[issue #1039 ] Change CSS to show topmost SSID on large screens
[webserver] Improve chunked transfer
[issue #1039 ] Change CSS to show topmost SSID on large screens
[webserver] Improve chunked transfer
mvdbro (1):
Rule Engine minor fix and added dev debugging
-------------------------------------------------
Changes in release mega-20180311 (since mega-20180310)
-------------------------------------------------
Release date: Sun Mar 11 04:00:06 CET 2018
ESPEasy release bot (2):
automaticly updated release notes for v2.0-20180309
automaticly updated release notes for v2.0-20180310
Unknown (19):
Move plugin init before WiFi init
[Conversions] Use more decimals in conversions and add AM/PM for time.
Update P07 Plugin
[AM/PM] Am/Pm notation doesn't have '0' hours
[P073] Remove tm1637_bitDelay()
Improve flash read performance
Add read buffer to rule processing to speedup parsing
Final ruleset speed-up
[AM/PM] Am/Pm notation doesn't have '0' hours
Update P07 Plugin
[P073] Remove tm1637_bitDelay()
[deepsleep] Make sure the 'shortcut' of running all services when sleep enabled
[OLED] fix drawProgressBar
[deepsleep] Make sure the 'shortcut' of running all services when sleep enabled
[OLED] fix drawProgressBar
[DNS lookup] Controllers sometimes try to connect to 0.0.0.0
[DNS lookup] Controllers sometimes try to connect to 0.0.0.0
[issue #1039] Topmost SSID are covered on mobile Browser
[issue #1039] Topmost SSID are covered on mobile Browser
mvdbro (5):
Improve flash read performance
Rule Engine, stop waisting time on non matching rules
Add read buffer to rule processing to speedup parsing
Final ruleset speed-up
Rule Engine, stop waisting time on non matching rules
-------------------------------------------------
Changes in release mega-20180310 (since mega-20180309)
-------------------------------------------------
Release date: Sat Mar 10 04:00:07 CET 2018
Unknown (2):
Move plugin init before WiFi init
[Conversions] Use more decimals in conversions and add AM/PM for time.
-------------------------------------------------
Changes in release mega-20180309 (since mega-20180308)
-------------------------------------------------
Release date: Fri Mar 9 04:00:11 CET 2018
ESPEasy release bot (3):
automaticly updated release notes for v2.0-20180305
automaticly updated release notes for v2.0-20180306
automaticly updated release notes for v2.0-20180307
Gijs Noorlander (2):
Fixes P073 plugin for latest TM1637 based 7 segments displays modules (#996) (#1022)
[CSS] Quick fix for smaller displays (#1026)
Unknown (5):
[issue #1012] Removed Content-Length header + improved webserver speed
[Rule Events] Add a number of events to handle in rules and awake timer
[Rule Events] Add a number of events to handle in rules and awake timer
[issue #1015] Add other simple conversions like Celsius to Fahrenheit, etc.
[issue #1015] Add other simple conversions like Celsius to Fahrenheit, etc.
-------------------------------------------------
Changes in release mega-20180308 (since mega-20180307)
-------------------------------------------------
Release date: Thu Mar 8 04:00:08 CET 2018
mvdbro (2):
First step towards port monitoring without tasks
Second step towards port monitoring without tasks
-------------------------------------------------
Changes in release mega-20180307 (since mega-20180305)
-------------------------------------------------
Release date: Wed Mar 7 04:00:09 CET 2018
Unknown (2):
[CSS] Quick fix for smaller displays
[issue #1012] Removed Content-Length header + improved webserver speed
-------------------------------------------------
Changes in release mega-20180305 (since mega-20180304)
-------------------------------------------------
Release date: Mon Mar 5 04:00:08 CET 2018
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180304
Edwin Eefting (2):
dont build in silent mode to prevent travis timeouts
automaticly updated release notes for v2.0-20180304b
Unknown (3):
[Webserver] Factory Reset was present twice
[issue #528] Set DOUT flash mode for all 1M builds
[issue #1003 ] Add conversion of wind direction to string
mvdbro (3):
ESP32 fix-2 for P020/P044
ESP32 - 32 Tasks
ESP32 - 32 Tasks -redo commit
soif (2):
Add OS specific hidden files (#1005)
fixes typos in the issue template (#1006)
-------------------------------------------------
Changes in release mega-20180304 (since mega-20180303)
-------------------------------------------------
Release date: Sun Mar 4 04:00:08 CET 2018
Bartlomiej Zimon (4):
- pcfgpio,port,2 sets pin as input - fix for #222,#702 - we can mix inputs and outputs now
- extend conditions with AND/OR, now it is possible to simplify rules
- remove Serial print
- support for more comparisions in IF conditions: >=,<=,!=,<>,<,>,= also fix extended conditions when first check is not >
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180303
Gijs Noorlander (2):
Merge pull request #1000 from uzi18/test3 (more comparisions in IF condition)
_P072_HDC1080 allow to send values to the controllers (#999)
Unknown (2):
[issue #993] Add %unit% variable in MQTT subscribe topic
[issue #892 ] Only use sensor type when really needed
clumsy-stefan (1):
add success and break statement
mvdbro (1):
ESP32 Dallas DS18B20 fix
soif (1):
Fixes P073 plugin for latest TM1637 based 7 segments displays modules
-------------------------------------------------
Changes in release mega-20180303 (since mega-20180302)
-------------------------------------------------
Release date: Sat Mar 3 04:00:08 CET 2018
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180302
Unknown (5):
revert json to non-chunking #988 from s0170071/mega
[issue #293] json output nan values not double quoted
Add Task device type to json by @s0170071
[Issue #827] MQTT not using proper case for %sysname% variable.
Add AND/OR to rules & prevent unwanted case changes in strings (#994)
s0170071 (3):
revert json to non-chunking
Add git build and local time
make handle_json return void
-------------------------------------------------
Changes in release mega-20180302 (since mega-20180228)
-------------------------------------------------
Release date: Fri Mar 2 04:00:10 CET 2018
Bartłomiej Zimoń (4):
provide System@Sleep event (#875)
add format #O to templates to show OFF/ON instead 0/1 (#949)
fix #964, add timeStringToSeconds and use it to compare time conditions (#965)
add format #O to templates to show OFF/ON instead 0/1 (#949)
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180228
Gijs Noorlander (1):
Merge pull request #983 from kahvm/mega
Unknown (4):
[issue #914] _P053_PMSx003 Dust Sensor looses sync
[issue #914] Check first 2 bytes of packet
[Build error fix] Must-keep-focus-when-pressing-buttons...
[webserver] Layout of code to improve readability
kahvm (1):
Support for degree sign on LCD1602
mvdbro (2):
Rule wildcard option on literal events
Rule wildcard option on literal events
s0170071 (1):
Add Factory Reset button to web interface (#954)
-------------------------------------------------
Changes in release mega-20180228 (since mega-20180227)
-------------------------------------------------
Release date: Wed Feb 28 04:00:09 CET 2018
Bartłomiej Zimoń (1):
fix #964, add timeStringToSeconds and use it to compare time conditions (#965)
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180227
Gijs Noorlander (2):
[issue #966] Add %sysweekday% and %sysweekday_s% (#973)
[issue #968] Use template parser for OLED commands (#974)
-------------------------------------------------
Changes in release mega-20180227 (since mega-20180226)
-------------------------------------------------
Release date: Tue Feb 27 04:00:11 CET 2018
Bartłomiej Zimoń (1):
add format #O to templates to show OFF/ON instead 0/1 (#949)
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180226
Edwin Eefting (2):
[test suite] changes from mega to 2.0
[test suite] changes from mega to 2.0
Gijs Noorlander (2):
[BuildError] StreamingBuffer code cleanup + fix order member initialize (#961)
[build conflict] Renamed ESP32 version of ping (#963)
mvdbro (1):
Fix ESP32 compile errors
s0170071 (1):
Add Factory Reset button to web interface (#954)
-------------------------------------------------
Changes in release mega-20180226 (since mega-20180224)
-------------------------------------------------
Release date: Mon Feb 26 04:00:08 CET 2018
Bartłomiej Zimoń (2):
provide System@Sleep event (#875) (#931)
- extend conditions with AND/OR, now it is possible to simplify rules (#932)
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180221
Edwin Eefting (1):
device page doesnt need next/previous page buttons anymore
Gijs Noorlander (7):
[MQTT] LWT "Connected" message doesn't have the retained flag (#925)
[v2.0] Added Vcc-binaries to deploy process #933 (#935)
[v2.0 merge] 2kwebserver_merge_to_mega #929 (#934)
[v2.0] Use ESPeasySoftwareSerial (#936)
[Mega] rename SoftwareSerial lib #930 (#937)
[timeouts] Improve response when hosts are not reachable (#939)
[2k Webserver] Proper initialisation of StreamingBuffer members. (#941)
Michael Schröder (1):
Added Vcc-binaries to deploy process (#933)
Unknown (2):
[ping lib] Added ping library
[softwareSerial] Remove duplicate with only capilization as difference
s0170071 (33):
Webserver min memory
Adjusted to min 7k free
Timeout 100ms
tcp_cleanup for LWIP1 & 2
Adapted timeout
trigger travis re-compile
try fix travis
Does Travis like extern "C" ?
Wait for memory be like before send chunked
"Content-Type","text/html"
Optimized memory usage
2k Webserver
fix travis
fix travis
Unused variable
navMenuIndex
fix download page
Add Ram usage debug message
fix Travis
Travis...
Cleanup and +1k Ram
4->12 Devices per page
Fix travis
Update .gitignore
Merge Webserver
Fixed String redeclaration
Merge into mega
fix travis
Removed double entry on info page
Fix compile error when SD card is enabled
Memtracker (#927)
V20 Webserver@LowMemory
Update WebServer.ino
-------------------------------------------------
Changes in release mega-20180224 (since mega-20180223)
-------------------------------------------------
Release date: Sat Feb 24 04:00:06 CET 2018
mvdbro (2):
Fix ESP32 compile errors
ESP32 fixed P020 and P044
-------------------------------------------------
Changes in release mega-20180223 (since mega-20180221)
-------------------------------------------------
Release date: Fri Feb 23 04:00:07 CET 2018
GHolli (1):
* BugFix: According to the data sheet, the offset for the detection range values (command byte 0x99) is 3..4 instead of 6..7 (#921)
s0170071 (1):
Include name of binary file in crc2.py and sysinfo (#918)
-------------------------------------------------
Changes in release mega-20180221 (since mega-20180220)
-------------------------------------------------
Release date: Wed Feb 21 04:00:09 CET 2018
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180220
Edwin Eefting (3):
SENSOR_TYPE_TEMP_BARO changed, was probably implemented incorrectly before
apply PUYA patch to all available frameworks
[test suite] corrected PUYA test. added erase/build/flash for all chips. preparations for full automatic hardware regression testing
GHolli (1):
Optimisation: Save RAM (freeing RAM by moving static data from RAM to program memory). (#910)
Gijs Noorlander (1):
[issue #899 ] Backport of DHT22 implementation on Mega (#913)
Stanislav Mihic (1):
Frontend (#906)
-------------------------------------------------
Changes in release mega-20180220 (since mega-20180219)
-------------------------------------------------
Release date: Tue Feb 20 04:00:08 CET 2018
Bartłomiej Zimoń (1):
- pcfgpio,port,2 sets pin as input (#897)
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180219
Edwin Eefting (1):
function was moved to StringConverter.inp
Gijs Noorlander (3):
[isue #877] Add VCC enable firmware file to release list (#894)
[Cleanup] Move String manipulating functions to single file (#895)
[issue #893] Fix globalSync not working when no controllers active (#896)
Unknown (3):
[issue #847] Fix last letter of command is cut in OpenHAB MQTT
[Event Log] Add event name to event processing time log
[issue #899] DHT22 readings not received
-------------------------------------------------
Changes in release mega-20180219 (since mega-20180217)
-------------------------------------------------
Release date: Mon Feb 19 04:00:09 CET 2018
ESPEasy release bot (2):
automaticly updated release notes for v2.0-20180217
automaticly updated release notes for v2.0-20180218
Gijs Noorlander (4):
[issue #847 ] OpenHAB MQTT rewrite topic parser (#886)
[issue #885] MAC address as system variable (#887)
[Build Mega] Fix for Build Mega 20180217 (#889)
[issue #890] Split overlap for both Domoticz controllers to helper (#891)
-------------------------------------------------
Changes in release mega-20180217 (since mega-20180214)
-------------------------------------------------
Release date: Sat Feb 17 04:00:07 CET 2018
Bartłomiej Zimoń (1):
provide System@Sleep event (#875)
ESPEasy release bot (1):
automaticly updated release notes for v2.0-20180214
Gijs Noorlander (4):
[issue 866] Try to stop logging to serial when serial is not read. (#868)
[issue #853] Favicon.ico (#874)
[OLED Framed] ESP Easy logo (#876)
[issue #869] Added 'LWT' to last will topic and improved CPU load (#883)
-------------------------------------------------
Changes in release mega-20180214 (since mega-20180213)
-------------------------------------------------
+74
View File
@@ -0,0 +1,74 @@
/*
Name: PingTest.ino
Created: 05/08/2017 10:20:19
Author: pbecc
*/
#undef PROVA_
#include <WiFi.h>
#include "esp32_ping.h"
// the setup function runs once when you press reset or power the board
const char ssid[] = "TP-LINK_C20B"; // your network SSID (name)
const char password[] = "paolo-48"; // your network password
void setup() {
Serial.begin(115200);
Serial.print("Connecting t ");
Serial.println(ssid);
// WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Pinging address: 192.168.1.1");
}
// the loop function runs over and over again until power down or reset
void loop() {
int ia[4] = { 192,168,1,1 };
int i = 0;
while (Serial.available()) {
char c = Serial.read();
delay(100);
int val = 0;
while (c != '.' && c != 10 && c!=255) {
if (c >= '0'&& c<='9') {
val = val*10+(c-'0');
}
c = Serial.read();
}
ia[i++] =val ;
}
IPAddress adr = IPAddress(ia[0], ia[1], ia[2], ia[3]);
Serial.printf("Ping : %d . %d . %d . %d ->", ia[0], ia[1], ia[2], ia[3]);
if (ping_start(adr, 4, 0, 0, 5))
Serial.println("OK");
else
Serial.println("FAILED");
delay(10000);
}
int readnu(char s) {
char c = Serial.read();
Serial.print(c);
int digit = 1,val=0;
while (c != s && c != 10&&c>0) {
if(c>'0') val += digit*(c - '0');
digit *= 10;
c=Serial.read();
Serial.print(int(c));
}
Serial.println(digit);
return digit;
}
+4
View File
@@ -0,0 +1,4 @@
# ESP32_ping
Ping library for ESP32
WORK IN PROGRESS
+366
View File
@@ -0,0 +1,366 @@
/*
* ESP32 Ping library
*
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for any purpose and without fee is hereby
* granted, provided that the above copyright notice appear in all
* copies and that both that the copyright notice and this
* permission notice and warranty disclaimer appear in supporting
* documentation, and that the name of the author not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
*
* The author disclaim all warranties with regard to this
* software, including all implied warranties of merchantability
* and fitness. In no event shall the author be liable for any
* special, indirect or consequential damages or any damages
* whatsoever resulting from loss of use, data or profits, whether
* in an action of contract, negligence or other tortious action,
* arising out of or in connection with the use or performance of
* this software.
*
* --------------------------------------------------------------------------------
* Ping Library is based on the following source code:
*
* Lua RTOS, ping utility
*
*
* Author: Jaume Oliv (jolive@iberoxarxa.com / jolive@whitecatboard.org)
*
* --------------------------------------------------------------------------------
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*/
#ifdef ESP32
#include <Arduino.h>
#include <math.h>
#include <float.h>
#include <signal.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "esp32_ping.h"
#include "lwip/inet_chksum.h"
#include "lwip/ip.h"
#include "lwip/ip4.h"
#include "lwip/err.h"
#include "lwip/icmp.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
static uint16_t ping_seq_num;
static uint8_t stopped = 0;
/*
* Statistics
*/
static uint32_t transmitted = 0;
static uint32_t received = 0;
static float min_time = 0;
static float max_time = 0;
static float mean_time = 0;
static float last_mean_time = 0;
static float var_time = 0;
#define PING_ID 0xAFAF
#define PING_DEFAULT_COUNT 10
#define PING_DEFAULT_INTERVAL 1
#define PING_DEFAULT_SIZE 32
#define PING_DEFAULT_TIMEOUT 1
/*
* Helper functions
*
*/
static void ping_prepare_echo(struct icmp_echo_hdr *iecho, uint16_t len) {
size_t i;
size_t data_len = len - sizeof(struct icmp_echo_hdr);
ICMPH_TYPE_SET(iecho, ICMP_ECHO);
ICMPH_CODE_SET(iecho, 0);
iecho->chksum = 0;
iecho->id = PING_ID;
iecho->seqno = htons(++ping_seq_num);
/* fill the additional data buffer with some data */
for (i = 0; i < data_len; i++) {
((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
}
iecho->chksum = inet_chksum(iecho, len);
}
static err_t ping_send(int s, ip4_addr_t *addr, int size) {
struct icmp_echo_hdr *iecho;
struct sockaddr_in to;
size_t ping_size = sizeof(struct icmp_echo_hdr) + size;
int err;
iecho = (struct icmp_echo_hdr *)mem_malloc((mem_size_t)ping_size);
if (!iecho) {
return ERR_MEM;
}
ping_prepare_echo(iecho, (uint16_t)ping_size);
to.sin_len = sizeof(to);
to.sin_family = AF_INET;
inet_addr_from_ipaddr(&to.sin_addr, addr);
if ((err = sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to)))) {
transmitted++;
}
return (err ? ERR_OK : ERR_VAL);
}
static void ping_recv(int s) {
char buf[64];
int fromlen, len;
struct sockaddr_in from;
struct ip_hdr *iphdr;
struct icmp_echo_hdr *iecho = NULL;
char ipa[16];
struct timeval begin;
struct timeval end;
uint64_t micros_begin;
uint64_t micros_end;
float elapsed;
// Register begin time
gettimeofday(&begin, NULL);
// Send
while ((len = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0) {
if (len >= (int)(sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr))) {
// Register end time
gettimeofday(&end, NULL);
/// Get from IP address
ip4_addr_t fromaddr;
inet_addr_to_ipaddr(&fromaddr, &from.sin_addr);
strcpy(ipa, inet_ntoa(fromaddr));
// Get echo
iphdr = (struct ip_hdr *)buf;
iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));
// Print ....
if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) {
received++;
// Get elapsed time in milliseconds
micros_begin = begin.tv_sec * 1000000;
micros_begin += begin.tv_usec;
micros_end = end.tv_sec * 1000000;
micros_end += end.tv_usec;
elapsed = (float)(micros_end - micros_begin) / (float)1000.0;
// Update statistics
// Mean and variance are computed in an incremental way
if (elapsed < min_time) {
min_time = elapsed;
}
if (elapsed > max_time) {
max_time = elapsed;
}
last_mean_time = mean_time;
mean_time = (((received - 1) * mean_time) + elapsed) / received;
if (received > 1) {
var_time = var_time + ((elapsed - last_mean_time) * (elapsed - mean_time));
}
// Print ...
log_d("%d bytes from %s: icmp_seq=%d time=%.3f ms\r\n", len, ipa,
ntohs(iecho->seqno), elapsed
);
return;
}
else {
// TODO
}
}
}
if (len < 0) {
log_d("Request timeout for icmp_seq %d\r\n", ping_seq_num);
}
}
/*
static void stop_action(int i) {
signal(i, SIG_DFL);
stopped = 1;
}
+/
/*
* Operation functions
*
*/
void ping(const char *name, int count, int interval, int size, int timeout) {
// Resolve name
hostent * target = gethostbyname(name);
IPAddress adr = *target->h_addr_list[0];
if (target->h_length == 0) {
// TODO: error not found target?????
return;
}
ping_start(adr, count, interval, size, timeout);
}
bool ping_start(struct ping_option *ping_o) {
return ping_start(ping_o->ip,ping_o->count,0,0,0);
}
bool ping_start(IPAddress adr, int count=0, int interval=0, int size=0, int timeout=0) {
// driver_error_t *error;
struct sockaddr_in address;
ip4_addr_t ping_target;
int s;
// Get default values if argument are not provided
if (count == 0) {
count = PING_DEFAULT_COUNT;
}
if (interval == 0) {
interval = PING_DEFAULT_INTERVAL;
}
if (size == 0) {
size = PING_DEFAULT_SIZE;
}
if (timeout == 0) {
timeout = PING_DEFAULT_TIMEOUT;
}
// Create socket
if ((s = socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) {
// TODO: error
return false;
}
address.sin_addr.s_addr = adr;
ping_target.addr = address.sin_addr.s_addr;
// Setup socket
struct timeval tout;
// Timeout
tout.tv_sec = timeout;
tout.tv_usec = 0;
if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tout, sizeof(tout)) < 0) {
closesocket(s);
// TODO: error
return false;
}
stopped = 0;
transmitted = 0;
received = 0;
min_time = 1.E+9;// FLT_MAX;
max_time = 0.0;
mean_time = 0.0;
var_time = 0.0;
// Register signal for stop ping
//signal(SIGINT, stop_action);
// Begin ping ...
char ipa[16];
strcpy(ipa, inet_ntoa(ping_target));
log_i("PING %s: %d data bytes\r\n", ipa, size);
ping_seq_num = 0;
while ((ping_seq_num < count) && (!stopped)) {
if (ping_send(s, &ping_target, size) == ERR_OK) {
ping_recv(s);
}
delay( interval*1000L);
}
closesocket(s);
log_i("%d packets transmitted, %d packets received, %.1f%% packet loss\r\n",
transmitted,
received,
((((float)transmitted - (float)received) / (float)transmitted) * 100.0)
);
if (received) {
ping_resp pingresp;
log_i("round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\r\n", min_time, mean_time, max_time, sqrt(var_time / received));
pingresp.total_count = 10;
pingresp.timeout_count = 10;
pingresp.total_bytes = 1;
pingresp.total_time = mean_time;
pingresp.ping_err = 0;
return true;
// ping_o->sent_function(ping_o, (uint8*)&pingresp);
}
return false;
}
bool ping_regist_recv(struct ping_option *ping_opt, ping_recv_function ping_recv)
{
if (ping_opt == NULL)
return false;
ping_opt->recv_function = ping_recv;
return true;
}
bool ping_regist_sent(struct ping_option *ping_opt, ping_sent_function ping_sent)
{
if (ping_opt == NULL)
return false;
ping_opt->sent_function = ping_sent;
return true;
}
#endif
+36
View File
@@ -0,0 +1,36 @@
#ifndef _PING_
#define _PING_
#include <Arduino.h>
#ifdef ESP32
typedef void(*ping_recv_function)(void* arg, void *pdata);
typedef void(*ping_sent_function)(void* arg, void *pdata);
struct ping_option {
uint32_t count;
uint32_t ip;
uint32_t coarse_time;
ping_recv_function recv_function;
ping_sent_function sent_function;
void* reverse;
};
struct ping_resp {
uint32_t total_count;
uint32_t resp_time;
uint32_t seqno;
uint32_t timeout_count;
uint32_t bytes;
uint32_t total_bytes;
uint32_t total_time;
int8_t ping_err;
};
bool ping_start(struct ping_option *ping_opt);
void ping(const char *name, int count, int interval, int size, int timeout);
bool ping_start(IPAddress adr, int count, int interval, int size, int timeout);
#endif
#endif
+456
View File
@@ -0,0 +1,456 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
+40
View File
@@ -0,0 +1,40 @@
# ESP8266Ping
Let the ESP8266 ping a remote machine.
With this library an ESP8266 can ping a remote machine and know if it's reachable.
It provide some basic measurements on ping messages (avg response time).
## Usage
First, include the library in your sketch along with WiFi library:
```Arduino
#include <ESP8266WiFi.h>
#include <ESP8266Ping.h>
```
Next, simply call the `Ping.ping()` function
```Arduino
IPAddress ip (192, 168, 0, 1); // The remote ip to ping
bool ret = Ping.ping(ip);
```
`ret` will be true if the remote responded to pings, false if not reachable.
The library supports hostname too, just pass a string instead of the ip address:
```Arduino
bool ret = Ping.ping("www.google.com");
```
Additionally, the function accept a second integer parameter `count` that specify how many pings has to be sent:
```Arduino
bool ret = Ping.ping(ip_or_host, 10);
```
After `Ping.ping()` has been called, the average response time (in milliseconds) can be retrieved with
```Arduino
int avg_time_ms = Ping.averageTime();
```
@@ -0,0 +1,43 @@
/*
* This example show how to ping a remote machine using it's hostname
*/
#include <ESP8266WiFi.h>
#include <ESP8266Ping.h>
const char* ssid = "ssid";
const char* password = "passphrase";
const char* remote_host = "www.google.com";
void setup() {
Serial.begin(115200);
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.println("Connecting to WiFi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println();
Serial.print("WiFi connected with ip ");
Serial.println(WiFi.localIP());
Serial.print("Pinging host ");
Serial.println(remote_host);
if(Ping.ping(remote_host)) {
Serial.println("Success!!");
} else {
Serial.println("Error :(");
}
}
void loop() { }
@@ -0,0 +1,44 @@
/*
* With this library an ESP8266 can ping a remote machine and know if it's reachable.
* It provides some basic measurements on ping messages (avg response time).
*/
#include <ESP8266WiFi.h>
#include <ESP8266Ping.h>
const char* ssid = "ssid";
const char* password = "passphrase";
const IPAddress remote_ip(192, 168, 0, 1);
void setup() {
Serial.begin(115200);
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.println("Connecting to WiFi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println();
Serial.print("WiFi connected with ip ");
Serial.println(WiFi.localIP());
Serial.print("Pinging ip ");
Serial.println(remote_ip);
if(Ping.ping(remote_ip)) {
Serial.println("Success!!");
} else {
Serial.println("Error :(");
}
}
void loop() { }
+26
View File
@@ -0,0 +1,26 @@
#######################################
# Syntax Coloring Map For ESP8266Ping
#######################################
#######################################
# Library (KEYWORD3)
#######################################
ESP8266Ping KEYWORD3
#######################################
# Datatypes (KEYWORD1)
#######################################
Ping KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
ping KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
@@ -0,0 +1,9 @@
name=ESPEasy_ESP8266Ping
version=1.0
author=Daniele Colanardi
maintainer=Daniele Colanardi <dancol90@gmail.com>
sentence=Let the ESP8266 ping a remote machine.
paragraph=With this library an ESP8266 can ping a remote machine and know if it's reachable. It provide some basic measurements on ping messages (avg response time). Lib name renamed to avoid conflicts in Arduino IDE.
category=Communication
url=
architectures=esp8266
+61
View File
@@ -0,0 +1,61 @@
/*
ESP8266Ping - Ping library for ESP8266
Copyright (c) 2015 Daniele Colanardi. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef ESP8266Ping_H
#define ESP8266Ping_H
#if defined(ESP8266)
#include <Arduino.h>
#include <ESP8266WiFi.h>
extern "C" {
#include <ping.h>
}
#ifdef ENABLE_DEBUG_PING
#define DEBUG_PING(...) Serial.printf(__VA_ARGS__)
#else
#define DEBUG_PING(...)
#endif
class PingClass {
public:
PingClass();
bool ping(IPAddress dest, byte count = 5);
bool ping(const char* host, byte count = 5);
int averageTime();
protected:
static void _ping_sent_cb(void *opt, void *pdata);
static void _ping_recv_cb(void *opt, void *pdata);
IPAddress _dest;
ping_option _options;
static byte _expected_count, _errors, _success;
static int _avg_time;
};
#include "ESP8266Ping.impl.h"
PingClass Ping;
#endif
#endif
@@ -0,0 +1,112 @@
/*
ESP8266Ping - Ping library for ESP8266
Copyright (c) 2015 Daniele Colanardi. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
extern "C" void esp_schedule();
extern "C" void esp_yield();
PingClass::PingClass() {}
bool PingClass::ping(IPAddress dest, byte count) {
_expected_count = count;
_errors = 0;
_success = 0;
_avg_time = 0;
memset(&_options, 0, sizeof(struct ping_option));
// Repeat count (how many time send a ping message to destination)
_options.count = count;
// Time interval between two ping (seconds??)
_options.coarse_time = 1;
// Destination machine
_options.ip = dest;
// Callbacks
_options.recv_function = reinterpret_cast<ping_recv_function>(&PingClass::_ping_recv_cb);
_options.sent_function = NULL; //reinterpret_cast<ping_sent_function>(&_ping_sent_cb);
// Let's go!
if(ping_start(&_options)) {
// Suspend till the process end
esp_yield();
}
return (_success > 0);
}
bool PingClass::ping(const char* host, byte count) {
IPAddress remote_addr;
if (WiFi.hostByName(host, remote_addr))
return ping(remote_addr, count);
return false;
}
int PingClass::averageTime() {
return _avg_time;
}
void PingClass::_ping_recv_cb(void *opt, void *resp) {
// Cast the parameters to get some usable info
ping_resp* ping_resp = reinterpret_cast<struct ping_resp*>(resp);
//ping_option* ping_opt = reinterpret_cast<struct ping_option*>(opt);
// Error or success?
if (ping_resp->ping_err == -1)
_errors++;
else {
_success++;
_avg_time += ping_resp->resp_time;
}
// Some debug info
DEBUG_PING(
"DEBUG: ping reply\n"
"\ttotal_count = %d \n"
"\tresp_time = %d \n"
"\tseqno = %d \n"
"\ttimeout_count = %d \n"
"\tbytes = %d \n"
"\ttotal_bytes = %d \n"
"\ttotal_time = %d \n"
"\tping_err = %d \n",
ping_resp->total_count, ping_resp->resp_time, ping_resp->seqno,
ping_resp->timeout_count, ping_resp->bytes, ping_resp->total_bytes,
ping_resp->total_time, ping_resp->ping_err
);
// Is it time to end?
// Don't using seqno because it does not increase on error
if (_success + _errors == _expected_count) {
_avg_time = _avg_time / _expected_count;
DEBUG_PING("Avg resp time %d ms\n", _avg_time);
// Done, return to main functiom
esp_schedule();
}
}
byte PingClass::_expected_count = 0;
byte PingClass::_errors = 0;
byte PingClass::_success = 0;
int PingClass::_avg_time = 0;
@@ -22,6 +22,10 @@ SOFTWARE.
See more at http://blog.squix.ch
*/
#ifndef DIALOG_PLAIN_FONT_H
#define DIALOG_PLAIN_FONT_H
// OLED library version >= 3.0.0
// Created by http://oleddisplay.squix.ch/ Consider a donation
// In case of problems make sure that you are using the font file with the correct version!
@@ -481,3 +485,6 @@ const char Dialog_plain_12[] PROGMEM = {
0x00,0x00,0xFC,0x7F,0x40,0x04,0x20,0x08,0x20,0x08,0x60,0x0C,0xC0,0x07, // 254
0x00,0x00,0xE0,0x40,0x04,0x47,0x00,0x38,0x84,0x07,0xE0 // 255
};
#endif
+1 -1
View File
@@ -349,7 +349,7 @@ void OLEDDisplay::drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16
drawHorizontalLine(xRadius, y + height, width - doubleRadius + 1);
drawCircleQuads(x + width - radius, yRadius, radius, 0b00001001);
uint16_t maxProgressWidth = (width - doubleRadius - 1) * progress / 100;
uint16_t maxProgressWidth = (width - doubleRadius + 1) * progress / 100;
fillCircle(xRadius, yRadius, innerRadius);
fillRect(xRadius + 1, y + 2, maxProgressWidth, height - 3);
@@ -1,31 +1,24 @@
#define WiFi_Logo_width 60
#define WiFi_Logo_height 36
const char WiFi_Logo_bits[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF,
0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00,
0xC0, 0xFF, 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C,
0xFC, 0x77, 0x08, 0x00, 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00,
0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C,
0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00,
0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C,
0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00,
0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C,
0x1C, 0x70, 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00,
0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F,
0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00,
0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF,
0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00,
0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#ifndef OLED_SSD1306_SH1106_IMAGES_H
#define OLED_SSD1306_SH1106_IMAGES_H
#define espeasy_logo_width 36
#define espeasy_logo_height 36
const char espeasy_logo_bits[] PROGMEM= {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x60, 0x40, 0xc0, 0x00, 0x00, 0x70, 0xf0, 0xe0,
0x01, 0x00, 0x78, 0xf8, 0xf0, 0x01, 0x00, 0x3c, 0x7c, 0xf8, 0x00, 0x00,
0x1e, 0x3e, 0x7c, 0x00, 0x00, 0x0f, 0x1f, 0x3e, 0x00, 0x80, 0x87, 0x0f,
0x1f, 0x00, 0xc0, 0xc3, 0x87, 0x0f, 0x00, 0xe0, 0xe1, 0xc3, 0x07, 0x00,
0xf0, 0xf0, 0xe1, 0xc3, 0x00, 0x78, 0xf8, 0xf0, 0xe1, 0x01, 0x30, 0x7c,
0xf8, 0xf0, 0x00, 0x00, 0x3e, 0x7c, 0x78, 0x00, 0x00, 0x1f, 0x3e, 0x3c,
0x00, 0x80, 0x0f, 0x1f, 0x1e, 0x00, 0xc0, 0x87, 0x0f, 0x0f, 0x00, 0xe0,
0xc3, 0x87, 0x07, 0x00, 0xf0, 0xe1, 0xc3, 0x03, 0x00, 0xf0, 0xf0, 0xe1,
0x01, 0x00, 0x78, 0xf8, 0xf0, 0x00, 0x00, 0x30, 0x7c, 0x78, 0x00, 0x00,
0x00, 0x3e, 0x3c, 0x00, 0x00, 0x00, 0x1f, 0x1e, 0x00, 0x00, 0x80, 0x0f,
0x0f, 0x78, 0x00, 0xc0, 0x87, 0x07, 0xfc, 0x00, 0xe0, 0xc3, 0x03, 0xfc,
0x01, 0xf0, 0xe1, 0x01, 0xfc, 0x01, 0xf8, 0xf0, 0x00, 0xfc, 0x00, 0x78,
0x70, 0x00, 0x78, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
const char activeSymbole[] PROGMEM = {
B00000000,
@@ -49,3 +42,4 @@ const char inactiveSymbole[] PROGMEM = {
B00000000
};
#endif
+1 -1
View File
@@ -420,7 +420,7 @@ boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsig
lastOutActivity = millis();
return rc == tlen + 4 + plength;
return rc == tlen + 3 + llen + plength;
}
boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) {
+1 -1
View File
@@ -73,7 +73,7 @@
#define MQTTQOS1 (1 << 1)
#define MQTTQOS2 (2 << 1)
#ifdef ESP8266
#if defined(ESP8266) || defined(ESP32)
#include <functional>
#define MQTT_CALLBACK_SIGNATURE std::function<void(char*, uint8_t*, unsigned int)> callback
#else
+8 -5
View File
@@ -1,9 +1,12 @@
#!/bin/bash
DIR=~/.platformio/packages/framework-arduinoespressif8266
PATCH=puya.patch
#not applied yet? (in upstream or otherwise)
if ! grep FLASH_QUIRK_WRITE_0_TO_1 $DIR/cores/esp8266/Esp.cpp >/dev/null; then
patch -p1 -d $DIR < $PATCH
fi
for DIR in ~/.platformio/packages/framework-arduinoespressif8266*/; do
#not applied yet? (in upstream or otherwise)
if ! grep FLASH_QUIRK_WRITE_0_TO_1 $DIR/cores/esp8266/Esp.cpp >/dev/null; then
echo "Patching $DIR"
patch -p1 -d $DIR < $PATCH
fi
done
+37
View File
@@ -22,11 +22,14 @@
[common]
build_flags = -D BUILD_GIT='"${env.TRAVIS_TAG}"'
lib_deps = ""
#normal version with stable plugins, 1024k version
[env:normal_ESP8266_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
board_flash_mode = dout
framework = arduino
board = esp12e
upload_speed=460800
@@ -35,6 +38,7 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld
[env:normal_ESP8266_1024_DOUT]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
board_flash_mode = dout
framework = arduino
board = esp12e
@@ -45,6 +49,7 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld
#normal version with stable plugins, 4096k version
[env:normal_ESP8266_4096]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp12e
upload_speed=460800
@@ -54,6 +59,8 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.4m1m.ld
#normal version with stable plugins, 4096k version for esp8285
[env:normal_ESP8285_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
board_flash_mode = dout
framework = arduino
board = esp8285
upload_speed=460800
@@ -64,6 +71,8 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld -DESP8285
#version with additional plugins (and dependend code) that are in test-stadium 1024k
[env:test_ESP8266_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
board_flash_mode = dout
framework = arduino
board = esp12e
upload_speed=460800
@@ -72,14 +81,25 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld -D PLUGIN_BUILD
#version with additional plugins (and dependend code) that are in test-stadium 4096k
[env:test_ESP8266_4096]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp12e
upload_speed=460800
build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.4m1m.ld -D PLUGIN_BUILD_TESTING
[env:test_ESP8266_4096_VCC]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp12e
upload_speed=460800
build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.4m1m.ld -D PLUGIN_BUILD_TESTING -D FEATURE_ADC_VCC=true
#version with additional plugins (and dependend code) that are in test-stadium 4096k for esp8285
[env:test_ESP8285_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
board_flash_mode = dout
framework = arduino
board = esp8285
upload_speed=460800
@@ -89,6 +109,8 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld -D PLUGIN_BUILD
#version with additional plugins (and dependend code) that is in development (probably broken or incomplete) 1024k
[env:dev_ESP8266_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
board_flash_mode = dout
framework = arduino
board = esp12e
upload_speed=460800
@@ -97,6 +119,7 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld -D PLUGIN_BUILD
#version with additional plugins (and dependend code) that is in development (probably broken or incomplete) 4096k
[env:dev_ESP8266_4096]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp12e
upload_speed=460800
@@ -115,6 +138,8 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.4m1m.ld -D PLUGIN_BUILD_
#version with additional plugins (and dependend code) that is in development (probably broken or incomplete) 4096k for esp8285
[env:dev_ESP8285_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
board_flash_mode = dout
framework = arduino
board = esp8285
upload_speed=460800
@@ -125,7 +150,19 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld -D PLUGIN_BUILD
#special patched version for PUYA flash chips, see https://github.com/letscontrolit/ESPEasy/issues/650
[env:dev_ESP8266PUYA_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
board_flash_mode = dout
framework = arduino
board = esp12e
upload_speed=460800
build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld -D PLUGIN_BUILD_TESTING -D PLUGIN_BUILD_DEV -D FLASH_QUIRK_WRITE_0_TO_1
#special patched version for PUYA flash chips, see https://github.com/letscontrolit/ESPEasy/issues/650
[env:dev_ESP8266PUYA_1024_VCC]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
board_flash_mode = dout
framework = arduino
board = esp12e
upload_speed=460800
build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld -D PLUGIN_BUILD_TESTING -D PLUGIN_BUILD_DEV -D FLASH_QUIRK_WRITE_0_TO_1 -D FEATURE_ADC_VCC=true
+8
View File
@@ -42,6 +42,7 @@ bool safeReadStringUntil(Stream &input, String &str, char terminator, unsigned i
#define INPUT_COMMAND_SIZE 80
void ExecuteCommand(byte source, const char *Line)
{
checkRAM(F("ExecuteCommand"));
String status = "";
boolean success = false;
char TmpStr1[80];
@@ -584,6 +585,13 @@ void ExecuteCommand(byte source, const char *Line)
{
success = true;
ResetFactory();
#if defined(ESP8266)
ESP.reset();
#endif
#if defined(ESP32)
ESP.restart();
#endif
}
if (strcasecmp_P(Command, PSTR("Save")) == 0)
+54 -59
View File
@@ -3,13 +3,11 @@
//********************************************************************************
void sendData(struct EventStruct *event)
{
LoadTaskSettings(event->TaskIndex);
checkRAM(F("sendData"));
LoadTaskSettings(event->TaskIndex);
if (Settings.UseRules)
createRuleEvents(event->TaskIndex);
if (Settings.GlobalSync && Settings.TaskDeviceGlobalSync[event->TaskIndex])
SendUDPTaskData(0, event->TaskIndex, event->TaskIndex);
if (Settings.UseValueLogger && Settings.InitSPI && Settings.Pin_sd_cs >= 0)
SendValueLogger(event->TaskIndex);
@@ -62,11 +60,7 @@ void sendData(struct EventStruct *event)
boolean validUserVar(struct EventStruct *event) {
for (int i = 0; i < VARS_PER_TASK; ++i) {
const float f(UserVar[event->BaseVarIndex + i]);
if (f == NAN) return false; //("NaN");
if (f == INFINITY) return false; //("INFINITY");
if (-f == INFINITY)return false; //("-INFINITY");
if (isnan(f)) return false; //("isnan");
if (isinf(f)) return false; //("isinf");
if (!isValidFloat(f)) return false;
}
return true;
}
@@ -120,13 +114,14 @@ void callback(char* c_topic, byte* b_payload, unsigned int length) {
/*********************************************************************************************\
* Connect to MQTT message broker
\*********************************************************************************************/
void MQTTConnect(int controller_idx)
bool MQTTConnect(int controller_idx)
{
if (!WiFiConnected(100)) return;
if (MQTTclient.connected())
MQTTclient.disconnect();
ControllerSettingsStruct ControllerSettings;
LoadControllerSettings(controller_idx, (byte*)&ControllerSettings, sizeof(ControllerSettings));
if (!ControllerSettings.checkHostReachable(true))
return false;
if (MQTTclient.connected())
MQTTclient.disconnect();
if (ControllerSettings.UseDNS) {
MQTTclient.setServer(ControllerSettings.getHost().c_str(), ControllerSettings.Port);
} else {
@@ -137,62 +132,61 @@ void MQTTConnect(int controller_idx)
// MQTT needs a unique clientname to subscribe to broker
String clientid = F("ESPClient_");
clientid += WiFi.macAddress();
String subscribeTo = "";
String LWTTopic = ControllerSettings.Subscribe;
LWTTopic.replace(F("/#"), F("/status"));
LWTTopic.replace(F("%sysname%"), Settings.Name);
parseSystemVariables(LWTTopic, false);
LWTTopic += F("/LWT"); // Extend the topic for status updates of connected/disconnected status.
for (byte x = 1; x < 3; x++)
{
String log = "";
boolean MQTTresult = false;
boolean MQTTresult = false;
uint8_t willQos = 0;
boolean willRetain = true;
if ((SecuritySettings.ControllerUser[controller_idx] != 0) && (SecuritySettings.ControllerPassword[controller_idx] != 0))
MQTTresult = MQTTclient.connect(clientid.c_str(), SecuritySettings.ControllerUser[controller_idx], SecuritySettings.ControllerPassword[controller_idx], LWTTopic.c_str(), 0, 0, "Connection Lost");
else
MQTTresult = MQTTclient.connect(clientid.c_str(), LWTTopic.c_str(), 0, 0, "Connection Lost");
yield();
if (MQTTresult)
{
MQTTclient_should_reconnect = false;
log = F("MQTT : Connected to broker with client ID: ");
log += clientid;
addLog(LOG_LEVEL_INFO, log);
subscribeTo = ControllerSettings.Subscribe;
subscribeTo.replace(F("%sysname%"), Settings.Name);
MQTTclient.subscribe(subscribeTo.c_str());
log = F("Subscribed to: ");
log += subscribeTo;
addLog(LOG_LEVEL_INFO, log);
MQTTclient.publish(LWTTopic.c_str(), "Connected", 1);
statusLED(true);
return; // end loop if succesfull
}
else
{
log = F("MQTT : ClientID ");
log += clientid;
log +=" failed to connected to broker";
addLog(LOG_LEVEL_ERROR, log);
}
delay(500);
if ((SecuritySettings.ControllerUser[controller_idx] != 0) && (SecuritySettings.ControllerPassword[controller_idx] != 0)) {
MQTTresult = MQTTclient.connect(clientid.c_str(), SecuritySettings.ControllerUser[controller_idx], SecuritySettings.ControllerPassword[controller_idx],
LWTTopic.c_str(), willQos, willRetain, "Connection Lost");
} else {
MQTTresult = MQTTclient.connect(clientid.c_str(), LWTTopic.c_str(), willQos, willRetain, "Connection Lost");
}
yield();
if (!MQTTresult) {
addLog(LOG_LEVEL_ERROR, F("MQTT : Failed to connect to broker"));
return false;
}
MQTTclient_should_reconnect = false;
String log = F("MQTT : Connected to broker with client ID: ");
log += clientid;
addLog(LOG_LEVEL_INFO, log);
String subscribeTo = ControllerSettings.Subscribe;
parseSystemVariables(subscribeTo, false);
MQTTclient.subscribe(subscribeTo.c_str());
log = F("Subscribed to: ");
log += subscribeTo;
addLog(LOG_LEVEL_INFO, log);
if (MQTTclient.publish(LWTTopic.c_str(), "Connected", 1)) {
if (Settings.UseRules)
{
String event = F("MQTT#Connected");
rulesProcessing(event);
}
statusLED(true);
return true; // end loop if succesfull
}
return false;
}
/*********************************************************************************************\
* Check connection MQTT message broker
\*********************************************************************************************/
void MQTTCheck(int controller_idx)
bool MQTTCheck(int controller_idx)
{
byte ProtocolIndex = getProtocolIndex(Settings.Protocol[controller_idx]);
if (Protocol[ProtocolIndex].usesMQTT)
{
if (MQTTclient_should_reconnect || !WiFiConnected(100) || !MQTTclient.connected())
if (MQTTclient_should_reconnect || !WiFiConnected(10) || !MQTTclient.connected())
{
if (MQTTclient_should_reconnect) {
addLog(LOG_LEVEL_ERROR, F("MQTT : Intentional reconnect"));
@@ -200,11 +194,13 @@ void MQTTCheck(int controller_idx)
addLog(LOG_LEVEL_ERROR, F("MQTT : Connection lost"));
connectionFailures += 2;
}
MQTTConnect(controller_idx);
}
else if (connectionFailures)
return MQTTConnect(controller_idx);
} else if (connectionFailures) {
connectionFailures--;
}
}
// When no MQTT protocol is enabled, all is fine.
return true;
}
@@ -234,7 +230,6 @@ boolean MQTTpublish(int controller_idx, const char* topic, const char* payload,
if (MQTTclient.publish(topic, payload, retained))
return true;
addLog(LOG_LEVEL_DEBUG, F("MQTT : publish failed"));
MQTTConnect(controller_idx);
return false;
}
@@ -249,7 +244,7 @@ void MQTTStatus(String& status)
LoadControllerSettings(enabledMqttController, (byte*)&ControllerSettings, sizeof(ControllerSettings));
String pubname = ControllerSettings.Subscribe;
pubname.replace(F("/#"), F("/status"));
pubname.replace(F("%sysname%"), Settings.Name);
parseSystemVariables(pubname, false);
MQTTpublish(enabledMqttController, pubname.c_str(), status.c_str(),Settings.MQTTRetainFlag);
}
}
+129
View File
@@ -0,0 +1,129 @@
/*********************************************************************************************\
Convert bearing in degree to bearing string
\*********************************************************************************************/
String getBearing(int degrees)
{
const __FlashStringHelper* bearing[] = {
F("N"),
F("NNE"),
F("NE"),
F("ENE"),
F("E"),
F("ESE"),
F("SE"),
F("SSE"),
F("S"),
F("SSW"),
F("SW"),
F("WSW"),
F("W"),
F("WNW"),
F("NW"),
F("NNW")
};
int nr_directions = (int) (sizeof(bearing)/sizeof(bearing[0]));
float stepsize = (360.0 / nr_directions);
if (degrees < 0) { degrees += 360; } // Allow for bearing -360 .. 359
int bearing_idx=int((degrees + (stepsize / 2.0)) / stepsize) % nr_directions;
if (bearing_idx < 0)
return("");
else
return(bearing[bearing_idx]);
}
float CelsiusToFahrenheit(float celsius) {
return celsius * (9.0 / 5.0) + 32;
}
int m_secToBeaufort(float m_per_sec) {
if (m_per_sec < 0.3) return 0;
if (m_per_sec < 1.6) return 1;
if (m_per_sec < 3.4) return 2;
if (m_per_sec < 5.5) return 3;
if (m_per_sec < 8.0) return 4;
if (m_per_sec < 10.8) return 5;
if (m_per_sec < 13.9) return 6;
if (m_per_sec < 17.2) return 7;
if (m_per_sec < 20.8) return 8;
if (m_per_sec < 24.5) return 9;
if (m_per_sec < 28.5) return 10;
if (m_per_sec < 32.6) return 11;
return 12;
}
String centimeterToImperialLength(float cm) {
return millimeterToImperialLength(cm * 10.0);
}
String millimeterToImperialLength(float mm) {
float inches = mm / 25.4;
int feet = inches /12;
inches = inches - (feet * 12);
String result;
result.reserve(10);
if (feet != 0) {
result += feet;
result += '\'';
}
result += toString(inches,1);
result += '"';
return result;
}
float minutesToDay(int minutes) {
return minutes / 1440.0;
}
String minutesToDayHour(int minutes) {
int days = minutes / 1440;
int hours = (minutes % 1440) / 60;
char TimeString[6]; //5 digits plus the null char
sprintf_P(TimeString, PSTR("%d%c%02d%c"), days, 'd', hours, 'h');
return TimeString;
}
String minutesToDayHourMinute(int minutes) {
int days = minutes / 1440;
int hours = (minutes % 1440) / 60;
int mins = (minutes % 1440) % 60;
char TimeString[20];
sprintf_P(TimeString, PSTR("%d%c%02d%c%02d%c"), days, 'd', hours, 'h', mins, 'm');
return TimeString;
}
String secondsToDayHourMinuteSecond(int seconds) {
int sec = seconds % 60;
int minutes = seconds / 60;
int days = minutes / 1440;
int hours = (minutes % 1440) / 60;
int mins = (minutes % 1440) % 60;
char TimeString[20];
sprintf_P(TimeString, PSTR("%d%c%02d%c%02d%c%02d"), days, 'd', hours, ':', mins, ':', sec);
return TimeString;
}
/********************************************************************************************\
In memory convert float to long
\*********************************************************************************************/
unsigned long float2ul(float f)
{
unsigned long ul;
memcpy(&ul, &f, 4);
return ul;
}
/********************************************************************************************\
In memory convert long to float
\*********************************************************************************************/
float ul2float(unsigned long ul)
{
float f;
memcpy(&f, &ul, 4);
return f;
}
File diff suppressed because it is too large Load Diff
+78 -984
View File
File diff suppressed because it is too large Load Diff
+8
View File
@@ -1,3 +1,6 @@
#ifndef ESPEASY_TIMETYPES_H_
#define ESPEASY_TIMETYPES_H_
#include <stdint.h>
struct timeStruct {
@@ -59,3 +62,8 @@ struct TimeChangeRule {
void applyTimeZone(uint32_t curTime = 0);
void setTimeZone(const TimeChangeRule& dstStart, const TimeChangeRule& stdStart, uint32_t curTime = 0);
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);
#endif /* ESPEASY_TIMETYPES_H_ */
+612 -590
View File
File diff suppressed because it is too large Load Diff
+38 -170
View File
@@ -7,7 +7,6 @@
#endif
/*********************************************************************************************\
Syslog client
\*********************************************************************************************/
@@ -37,35 +36,6 @@ void syslog(const char *message)
}
/*********************************************************************************************\
Structs for UDP messaging
\*********************************************************************************************/
struct infoStruct
{
byte header = 255;
byte ID = 3;
byte sourcelUnit;
byte destUnit;
byte sourceTaskIndex;
byte destTaskIndex;
byte deviceNumber;
char taskName[26];
char ValueNames[VARS_PER_TASK][26];
};
struct dataStruct
{
byte header = 255;
byte ID = 5;
byte sourcelUnit;
byte destUnit;
byte sourceTaskIndex;
byte destTaskIndex;
float Values[VARS_PER_TASK];
};
//TODO: add sysinfoStruct
/*********************************************************************************************\
Check UDP messages (ESPEasy propiertary protocol)
\*********************************************************************************************/
@@ -109,22 +79,10 @@ void checkUDP()
}
else
{
if (packetBuffer[1] > 1 && packetBuffer[1] < 6)
{
String log = (F("UDP : Sensor msg "));
for (byte x = 1; x < 6; x++)
{
log += " ";
log += (int)packetBuffer[x];
}
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
// binary data!
switch (packetBuffer[1])
{
//TODO: use a nice struct for it
case 1: // sysinfo message
{
byte mac[6];
@@ -161,70 +119,13 @@ void checkUDP()
break;
}
case 2: // sensor info pull request
{
SendUDPTaskInfo(packetBuffer[2], packetBuffer[5], packetBuffer[4]);
break;
}
case 3: // sensor info
{
if (Settings.GlobalSync)
{
struct infoStruct infoReply;
memcpy((byte*)&infoReply, (byte*)&packetBuffer, sizeof(infoStruct));
// to prevent flash wear out (bugs in communication?) we can only write to an empty task
// so it will write only once and has to be cleared manually through webgui
if (Settings.TaskDeviceNumber[infoReply.destTaskIndex] == 0)
{
Settings.TaskDeviceNumber[infoReply.destTaskIndex] = infoReply.deviceNumber;
Settings.TaskDeviceDataFeed[infoReply.destTaskIndex] = 1; // remote feed
for (byte x=0; x < CONTROLLER_MAX; x++)
Settings.TaskDeviceSendData[x][infoReply.destTaskIndex] = false;
strcpy(ExtraTaskSettings.TaskDeviceName, infoReply.taskName);
for (byte x = 0; x < VARS_PER_TASK; x++)
strcpy( ExtraTaskSettings.TaskDeviceValueNames[x], infoReply.ValueNames[x]);
SaveTaskSettings(infoReply.destTaskIndex);
SaveSettings();
}
}
break;
}
case 4: // sensor data pull request
{
SendUDPTaskData(packetBuffer[2], packetBuffer[5], packetBuffer[4]);
break;
}
case 5: // sensor data
{
if (Settings.GlobalSync)
{
struct dataStruct dataReply;
memcpy((byte*)&dataReply, (byte*)&packetBuffer, sizeof(dataStruct));
// only if this task has a remote feed, update values
if (Settings.TaskDeviceDataFeed[dataReply.destTaskIndex] != 0)
{
for (byte x = 0; x < VARS_PER_TASK; x++)
{
UserVar[dataReply.destTaskIndex * VARS_PER_TASK + x] = dataReply.Values[x];
}
if (Settings.UseRules)
createRuleEvents(dataReply.destTaskIndex);
}
}
break;
}
default:
{
struct EventStruct TempEvent;
TempEvent.Data = (byte*)packetBuffer;
TempEvent.Par1 = remoteIP[3];
PluginCall(PLUGIN_UDP_IN, &TempEvent, dummyString);
CPluginCall(CPLUGIN_UDP_IN, &TempEvent);
break;
}
}
@@ -237,73 +138,6 @@ void checkUDP()
}
/*********************************************************************************************\
Send task info using UDP message
\*********************************************************************************************/
void SendUDPTaskInfo(byte destUnit, byte sourceTaskIndex, byte destTaskIndex)
{
if (!WiFiConnected(100)) {
return;
}
struct infoStruct infoReply;
infoReply.sourcelUnit = Settings.Unit;
infoReply.sourceTaskIndex = sourceTaskIndex;
infoReply.destTaskIndex = destTaskIndex;
LoadTaskSettings(infoReply.sourceTaskIndex);
infoReply.deviceNumber = Settings.TaskDeviceNumber[infoReply.sourceTaskIndex];
strcpy(infoReply.taskName, ExtraTaskSettings.TaskDeviceName);
for (byte x = 0; x < VARS_PER_TASK; x++)
strcpy(infoReply.ValueNames[x], ExtraTaskSettings.TaskDeviceValueNames[x]);
byte firstUnit = 1;
byte lastUnit = UNIT_MAX - 1;
if (destUnit != 0)
{
firstUnit = destUnit;
lastUnit = destUnit;
}
for (byte x = firstUnit; x <= lastUnit; x++)
{
infoReply.destUnit = x;
sendUDP(x, (byte*)&infoReply, sizeof(infoStruct));
delay(10);
}
delay(50);
}
/*********************************************************************************************\
Send task data using UDP message
\*********************************************************************************************/
void SendUDPTaskData(byte destUnit, byte sourceTaskIndex, byte destTaskIndex)
{
if (!WiFiConnected(100)) {
return;
}
struct dataStruct dataReply;
dataReply.sourcelUnit = Settings.Unit;
dataReply.sourceTaskIndex = sourceTaskIndex;
dataReply.destTaskIndex = destTaskIndex;
for (byte x = 0; x < VARS_PER_TASK; x++)
dataReply.Values[x] = UserVar[dataReply.sourceTaskIndex * VARS_PER_TASK + x];
byte firstUnit = 1;
byte lastUnit = UNIT_MAX - 1;
if (destUnit != 0)
{
firstUnit = destUnit;
lastUnit = destUnit;
}
for (byte x = firstUnit; x <= lastUnit; x++)
{
dataReply.destUnit = x;
sendUDP(x, (byte*) &dataReply, sizeof(dataStruct));
delay(10);
}
delay(50);
}
/*********************************************************************************************\
Send event using UDP message
\*********************************************************************************************/
@@ -752,15 +586,21 @@ void SSDP_update() {
_server->flush();
}
}
#endif
// Check WiFi connection. Maximum timeout 2000 msec.
// Check WiFi connection. Maximum timeout 500 msec.
bool WiFiConnected(uint32_t timeout_ms) {
uint32_t timer = millis() + (timeout_ms > 2000 ? 2000 : timeout_ms);
uint32_t min_delay = timeout_ms / 10;
uint32_t timer = millis() + (timeout_ms > 500 ? 500 : timeout_ms);
uint32_t min_delay = timeout_ms / 20;
if (min_delay < 10) {
yield(); // Allow at least once time for backgroundtasks
min_delay = 10;
}
if (!wifiConnected) {
// Apparently something needs network, perform check to see if it is ready now.
if (tryConnectWiFi())
checkWifiJustConnected();
}
while (WiFi.status() != WL_CONNECTED) {
if (timeOutReached(timer)) {
return false;
@@ -769,4 +609,32 @@ bool WiFiConnected(uint32_t timeout_ms) {
}
return true;
}
bool hostReachable(const IPAddress& ip) {
// Only do 1 ping at a time to return early
byte retry = 3;
while (retry > 0) {
#if defined(ESP8266)
if (Ping.ping(ip, 1)) return true;
#endif
#if defined(ESP32)
if (ping_start(ip, 4, 0, 0, 5)) return true;
#endif
delay(50);
--retry;
}
String log = F("Host unreachable: ");
log += ip;
addLog(LOG_LEVEL_ERROR, log);
return false;
}
bool hostReachable(const String& hostname) {
IPAddress remote_addr;
if (WiFi.hostByName(hostname.c_str(), remote_addr))
return hostReachable(remote_addr);
String log = F("Hostname cannot be resolved: ");
log += hostname;
addLog(LOG_LEVEL_ERROR, log);
return false;
}
+383
View File
@@ -0,0 +1,383 @@
/********************************************************************************************\
Convert a char string to integer
\*********************************************************************************************/
//FIXME: change original code so it uses String and String.toInt()
unsigned long str2int(char *string)
{
unsigned long temp = atof(string);
return temp;
}
/********************************************************************************************\
Check if valid float and convert string to float.
\*********************************************************************************************/
bool string2float(const String& string, float& floatvalue) {
if (!isFloat(string)) return false;
floatvalue = atof(string.c_str());
return true;
}
/********************************************************************************************\
Convert a char string to IP byte array
\*********************************************************************************************/
boolean str2ip(const String& string, byte* IP) {
return str2ip(string.c_str(), IP);
}
boolean str2ip(const char *string, byte* IP)
{
IPAddress tmpip; // Default constructor => set to 0.0.0.0
if (*string == 0 || tmpip.fromString(string)) {
// Eiher empty string or a valid IP addres, so copy value.
for (byte i = 0; i < 4; ++i)
IP[i] = tmpip[i];
return true;
}
return false;
}
// Call this by first declaring a char array of size 20, like:
// char strIP[20];
// formatIP(ip, strIP);
void formatIP(const IPAddress& ip, char (&strIP)[20]) {
sprintf_P(strIP, PSTR("%u.%u.%u.%u"), ip[0], ip[1], ip[2], ip[3]);
}
String formatIP(const IPAddress& ip) {
char strIP[20];
formatIP(ip, strIP);
return String(strIP);
}
void formatMAC(const uint8_t* mac, char (&strMAC)[20]) {
sprintf_P(strMAC, PSTR("%02X:%02X:%02X:%02X:%02X:%02X"), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
/*********************************************************************************************\
Workaround for removing trailing white space when String() converts a float with 0 decimals
\*********************************************************************************************/
String toString(float value, byte decimals)
{
String sValue = String(value, decimals);
sValue.trim();
return sValue;
}
/*********************************************************************************************\
Format a value to the set number of decimals
\*********************************************************************************************/
String formatUserVar(struct EventStruct *event, byte rel_index)
{
float f(UserVar[event->BaseVarIndex + rel_index]);
if (!isValidFloat(f)) {
String log = F("Invalid float value for TaskIndex: ");
log += event->TaskIndex;
log += F(" varnumber: ");
log += rel_index;
addLog(LOG_LEVEL_DEBUG, log);
f = 0;
}
return toString(f, ExtraTaskSettings.TaskDeviceValueDecimals[rel_index]);
}
/*********************************************************************************************\
Wrap a string with given pre- and postfix string.
\*********************************************************************************************/
String wrap_String(const String& string, const String& wrap) {
String result;
result.reserve(string.length() + 2* wrap.length());
result = wrap;
result += string;
result += wrap;
return result;
}
/*********************************************************************************************\
Format an object value pair for use in JSON.
\*********************************************************************************************/
String to_json_object_value(const String& object, const String& value) {
String result;
result.reserve(object.length() + value.length() + 6);
result = wrap_String(object, F("\""));
result += F(":");
if (value.length() == 0 || !isFloat(value)) {
result += wrap_String(value, F("\""));
} else {
result += value;
}
return result;
}
/*********************************************************************************************\
Parse a string and get the xth command or parameter
\*********************************************************************************************/
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;
}
}
return "";
}
/*********************************************************************************************\
Parse a string and get the xth command or parameter
\*********************************************************************************************/
int getParamStartPos(String& string, byte indexFind)
{
String tmpString = string;
byte count = 0;
tmpString.replace(" ", ",");
for (unsigned int x = 0; x < tmpString.length(); x++)
{
if (tmpString.charAt(x) == ',')
{
count++;
if (count == (indexFind - 1))
return x + 1;
}
}
return -1;
}
//escapes special characters in strings for use in html-forms
void htmlEscape(String & html)
{
html.replace("&", "&amp;");
html.replace("\"", "&quot;");
html.replace("'", "&#039;");
html.replace("<", "&lt;");
html.replace(">", "&gt;");
}
/********************************************************************************************\
replace other system variables like %sysname%, %systime%, %ip%
\*********************************************************************************************/
void parseControllerVariables(String& s, struct EventStruct *event, boolean useURLencode) {
parseSystemVariables(s, useURLencode);
parseEventVariables(s, event, useURLencode);
parseStandardConversions(s, useURLencode);
}
void repl(const String& key, const String& val, String& s, boolean useURLencode)
{
if (useURLencode) {
s.replace(key, URLEncode(val.c_str()));
} else {
s.replace(key, val);
}
}
void parseSpecialCharacters(String& s, boolean useURLencode)
{
bool no_accolades = s.indexOf('{') == -1 || s.indexOf('}') == -1;
bool no_html_entity = s.indexOf('&') == -1 || s.indexOf(';') == -1;
if (no_accolades && no_html_entity)
return; // Nothing to replace
{
// Degree
const char degree[3] = {0xc2, 0xb0, 0}; // Unicode degree symbol
const char degreeC[4] = {0xe2, 0x84, 0x83, 0}; // Unicode degreeC symbol
const char degree_C[4] = {0xc2, 0xb0, 'C', 0}; // Unicode degree symbol + captial C
repl(F("{D}"), degree, s, useURLencode);
repl(F("&deg;"), degree, s, useURLencode);
repl(degreeC, degree_C, s, useURLencode);
}
{
// Angle quotes
const char laquo[3] = {0xc2, 0xab, 0}; // Unicode left angle quotes symbol
const char raquo[3] = {0xc2, 0xbb, 0}; // Unicode right angle quotes symbol
repl(F("{<<}"), laquo, s, useURLencode);
repl(F("&laquo;"), laquo, s, useURLencode);
repl(F("{>>}"), raquo, s, useURLencode);
repl(F("&raquo;"), raquo, s, useURLencode);
}
{
// Greek letter Mu
const char mu[3] = {0xc2, 0xb5, 0}; // Unicode greek letter mu
repl(F("{u}"), mu, s, useURLencode);
repl(F("&micro;"), mu, s, useURLencode);
}
{
// Currency
const char euro[4] = {0xe2, 0x82, 0xac, 0}; // Unicode euro symbol
const char yen[3] = {0xc2, 0xa5, 0}; // Unicode yen symbol
const char pound[3] = {0xc2, 0xa3, 0}; // Unicode pound symbol
const char cent[3] = {0xc2, 0xa2, 0}; // Unicode cent symbol
repl(F("{E}"), euro, s, useURLencode);
repl(F("&euro;"), euro, s, useURLencode);
repl(F("{Y}"), yen, s, useURLencode);
repl(F("&yen;"), yen, s, useURLencode);
repl(F("{P}"), pound, s, useURLencode);
repl(F("&pound;"), pound, s, useURLencode);
repl(F("{c}"), cent, s, useURLencode);
repl(F("&cent;"), cent, s, useURLencode);
}
{
// Math symbols
const char sup1[3] = {0xc2, 0xb9, 0}; // Unicode sup1 symbol
const char sup2[3] = {0xc2, 0xb2, 0}; // Unicode sup2 symbol
const char sup3[3] = {0xc2, 0xb3, 0}; // Unicode sup3 symbol
const char frac14[3] = {0xc2, 0xbc, 0}; // Unicode frac14 symbol
const char frac12[3] = {0xc2, 0xbd, 0}; // Unicode frac12 symbol
const char frac34[3] = {0xc2, 0xbe, 0}; // Unicode frac34 symbol
const char plusmn[3] = {0xc2, 0xb1, 0}; // Unicode plusmn symbol
const char times[3] = {0xc3, 0x97, 0}; // Unicode times symbol
const char divide[3] = {0xc3, 0xb7, 0}; // Unicode divide symbol
repl(F("{^1}"), sup1, s, useURLencode);
repl(F("&sup1;"), sup1, s, useURLencode);
repl(F("{^2}"), sup2, s, useURLencode);
repl(F("&sup2;"), sup2, s, useURLencode);
repl(F("{^3}"), sup3, s, useURLencode);
repl(F("&sup3;"), sup3, s, useURLencode);
repl(F("{1_4}"), frac14, s, useURLencode);
repl(F("&frac14;"), frac14, s, useURLencode);
repl(F("{1_2}"), frac12, s, useURLencode);
repl(F("&frac12;"), frac12, s, useURLencode);
repl(F("{3_4}"), frac34, s, useURLencode);
repl(F("&frac34;"), frac34, s, useURLencode);
repl(F("{+-}"), plusmn, s, useURLencode);
repl(F("&plusmn;"), plusmn, s, useURLencode);
repl(F("{x}"), times, s, useURLencode);
repl(F("&times;"), times, s, useURLencode);
repl(F("{..}"), divide, s, useURLencode);
repl(F("&divide;"), divide, s, 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);}
void parseSystemVariables(String& s, boolean useURLencode)
{
parseSpecialCharacters(s, useURLencode);
if (s.indexOf('%') == -1)
return; // Nothing to replace
#if FEATURE_ADC_VCC
repl(F("%vcc%"), String(vcc), s, useURLencode);
#endif
repl(F("%CR%"), F("\r"), s, useURLencode);
repl(F("%LF%"), F("\n"), s, useURLencode);
SMART_REPL(F("%ip%"),WiFi.localIP().toString())
SMART_REPL(F("%rssi%"), String((WiFi.status() == WL_CONNECTED) ? WiFi.RSSI() : 0))
SMART_REPL(F("%ssid%"), (WiFi.status() == WL_CONNECTED) ? WiFi.SSID() : F("--"))
SMART_REPL(F("%unit%"), String(Settings.Unit))
SMART_REPL(F("%mac%"), String(WiFi.macAddress()))
#if defined(ESP8266)
SMART_REPL(F("%mac_int%"), String(ESP.getChipId())) // Last 24 bit of MAC address as integer, to be used in rules.
#endif
if (s.indexOf(F("%sys")) != -1) {
SMART_REPL(F("%sysload%"), String(100 - (100 * loopCounterLast / loopCounterMax)))
SMART_REPL(F("%systm_hm%"), getTimeString(':', false))
SMART_REPL(F("%systm_hm_am%"), getTimeString_ampm(':', false))
SMART_REPL(F("%systime%"), getTimeString(':'))
SMART_REPL(F("%systime_am%"), getTimeString_ampm(':'))
repl(F("%sysname%"), Settings.Name, s, useURLencode);
// valueString is being used by the macro.
char valueString[5];
#define SMART_REPL_TIME(T,F,V) if (s.indexOf(T) != -1) { sprintf_P(valueString, (F), (V)); repl((T),valueString, s, useURLencode);}
SMART_REPL_TIME(F("%syshour%"), PSTR("%02d"), hour())
SMART_REPL_TIME(F("%sysmin%"), PSTR("%02d"), minute())
SMART_REPL_TIME(F("%syssec%"),PSTR("%02d"), second())
SMART_REPL_TIME(F("%sysday%"), PSTR("%02d"), day())
SMART_REPL_TIME(F("%sysmonth%"),PSTR("%02d"), month())
SMART_REPL_TIME(F("%sysyear%"), PSTR("%04d"), year())
SMART_REPL_TIME(F("%sysyears%"),PSTR("%02d"), year()%100)
SMART_REPL(F("%sysweekday%"), String(weekday()))
SMART_REPL(F("%sysweekday_s%"), weekday_str())
#undef SMART_REPL_TIME
}
SMART_REPL(F("%lcltime%"), getDateTimeString('-',':',' '))
SMART_REPL(F("%lcltime_am%"), getDateTimeString_ampm('-',':',' '))
SMART_REPL(F("%uptime%"), String(wdcounter / 2))
repl(F("%tskname%"), ExtraTaskSettings.TaskDeviceName, s, useURLencode);
if (s.indexOf("%vname") != -1) {
repl(F("%vname1%"), ExtraTaskSettings.TaskDeviceValueNames[0], s, useURLencode);
repl(F("%vname2%"), ExtraTaskSettings.TaskDeviceValueNames[1], s, useURLencode);
repl(F("%vname3%"), ExtraTaskSettings.TaskDeviceValueNames[2], s, useURLencode);
repl(F("%vname4%"), ExtraTaskSettings.TaskDeviceValueNames[3], s, useURLencode);
}
}
void parseEventVariables(String& s, struct EventStruct *event, boolean useURLencode)
{
SMART_REPL(F("%id%"), String(event->idx))
if (s.indexOf("%val") != -1) {
if (event->sensorType == SENSOR_TYPE_LONG) {
SMART_REPL(F("%val1%"), String((unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16)))
} else {
SMART_REPL(F("%val1%"), formatUserVar(event, 0))
SMART_REPL(F("%val2%"), formatUserVar(event, 1))
SMART_REPL(F("%val3%"), formatUserVar(event, 2))
SMART_REPL(F("%val4%"), formatUserVar(event, 3))
}
}
}
#undef SMART_REPL
bool getConvertArgument(const String& marker, const String& s, float& argument, int& startIndex, int& endIndex) {
startIndex = s.indexOf(marker);
if (startIndex == -1) return false;
int startIndexArgument = startIndex + marker.length();
if (s.charAt(startIndexArgument) != '(') {
return false;
}
++startIndexArgument;
endIndex = s.indexOf(')', startIndexArgument);
if (endIndex == -1) return false;
String argumentString = s.substring(startIndexArgument, endIndex);
if (argumentString.length() == 0 || !isFloat(argumentString)) return false;
argument = argumentString.toFloat();
++endIndex; // Must also strip ')' from the original string.
return true;
}
// Parse conversions marked with "%conv_marker%(float)"
// Must be called last, since all sensor values must be converted, processed, etc.
void parseStandardConversions(String& s, boolean useURLencode) {
if (s.indexOf(F("%c_")) == -1)
return; // Nothing to replace
float arg = 0.0;
int startIndex = 0;
int endIndex = 0;
// These replacements should be done in a while loop per marker,
// since they also replace the numerical parameter.
// The marker may occur more than once per string, but with different parameters.
#define SMART_CONV(T,FUN) while (getConvertArgument((T), s, arg, startIndex, endIndex)) { repl(s.substring(startIndex, endIndex), (FUN), s, useURLencode); }
SMART_CONV(F("%c_w_dir%"), getBearing(arg))
SMART_CONV(F("%c_c2f%"), toString(CelsiusToFahrenheit(arg), 1))
SMART_CONV(F("%c_ms2Bft%"), String(m_secToBeaufort(arg)))
SMART_CONV(F("%c_cm2imp%"), centimeterToImperialLength(arg))
SMART_CONV(F("%c_mm2imp%"), millimeterToImperialLength(arg))
SMART_CONV(F("%c_m2day%"), toString(minutesToDay(arg), 2))
SMART_CONV(F("%c_m2dh%"), minutesToDayHour(arg))
SMART_CONV(F("%c_m2dhm%"), minutesToDayHourMinute(arg))
SMART_CONV(F("%c_s2dhms%"), secondsToDayHourMinuteSecond(arg))
#undef SMART_CONV
}
+115 -64
View File
@@ -74,6 +74,13 @@ void setTime(unsigned long t) {
sysTime = (uint32_t)t;
nextSyncTime = (uint32_t)t + syncInterval;
prevMillis = millis(); // restart counting from now (thanks to Korman for this fix)
if (Settings.UseRules)
{
static bool firstUpdate = true;
String event = firstUpdate ? F("Time#Initialized") : F("Time#Set");
firstUpdate = false;
rulesProcessing(event);
}
}
unsigned long now() {
@@ -89,7 +96,8 @@ unsigned long now() {
setTime(t);
applyTimeZone(t);
} else {
nextSyncTime = sysTime + syncInterval;
// Unable to sync, retry again in a minute
nextSyncTime = sysTime + 60;
}
}
uint32_t localSystime = toLocal(sysTime);
@@ -141,11 +149,19 @@ byte second()
return tm.Second;
}
// day of week, sunday is day 1
int weekday()
{
return tm.Wday;
}
String weekday_str()
{
const int wday(weekday() - 1); // here: Count from Sunday = 0
const String weekDays = F("SunMonTueWedThuFriSat");
return weekDays.substring(wday * 3, wday * 3 + 3);
}
void initTime()
{
nextSyncTime = 0;
@@ -161,9 +177,10 @@ void checkTime()
PrevMinutes = tm.Minute;
if (Settings.UseRules)
{
String weekDays = F("AllSunMonTueWedThuFriSat");
String event = F("Clock#Time=");
event += weekDays.substring(weekday() * 3, weekday() * 3 + 3);
String event;
event.reserve(21);
event = F("Clock#Time=");
event += weekday_str();
event += ",";
if (hour() < 10)
event += "0";
@@ -183,65 +200,62 @@ unsigned long getNtpTime()
if (!Settings.UseNTP || !WiFiConnected(100)) {
return 0;
}
IPAddress timeServerIP;
const char* ntpServerName = "pool.ntp.org";
// Have to do a lookup eacht time, since the NTP pool always returns another IP
if (Settings.NTPHost[0] != 0)
WiFi.hostByName(Settings.NTPHost, timeServerIP);
else
WiFi.hostByName(ntpServerName, timeServerIP);
if (!hostReachable(timeServerIP))
return 0;
WiFiUDP udp;
udp.begin(123);
for (byte x = 1; x < 4; x++)
{
String log = F("NTP : NTP sync request:");
log += x;
addLog(LOG_LEVEL_DEBUG_MORE, log);
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
IPAddress timeServerIP;
const char* ntpServerName = "pool.ntp.org";
String log = F("NTP : NTP send to ");
log += timeServerIP.toString();
addLog(LOG_LEVEL_DEBUG_MORE, log);
if (Settings.NTPHost[0] != 0)
WiFi.hostByName(Settings.NTPHost, timeServerIP);
else
WiFi.hostByName(ntpServerName, timeServerIP);
while (udp.parsePacket() > 0) ; // discard any previously received packets
log = F("NTP : NTP send to ");
log += timeServerIP.toString();
addLog(LOG_LEVEL_DEBUG_MORE, log);
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
udp.beginPacket(timeServerIP, 123); //NTP requests are to port 123
udp.write(packetBuffer, NTP_PACKET_SIZE);
udp.endPacket();
while (udp.parsePacket() > 0) ; // discard any previously received packets
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
udp.beginPacket(timeServerIP, 123); //NTP requests are to port 123
udp.write(packetBuffer, NTP_PACKET_SIZE);
udp.endPacket();
uint32_t beginWait = millis();
while (!timeOutReached(beginWait + 1000)) {
int size = udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
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);
return secsSince1900 - 2208988800UL;
}
uint32_t beginWait = millis();
while (!timeOutReached(beginWait + 1000)) {
int size = udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
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);
return secsSince1900 - 2208988800UL;
}
log = F("NTP : No reply");
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
log = F("NTP : No reply");
addLog(LOG_LEVEL_DEBUG_MORE, log);
return 0;
}
@@ -376,16 +390,40 @@ String getDateString()
// returns the current Time separated by the given delimiter
// time format example with ':' delimiter: 23:59:59 (HH:MM:SS)
String getTimeString(const timeStruct& ts, char delimiter)
String getTimeString(const timeStruct& ts, char delimiter, bool am_pm, bool show_seconds)
{
char TimeString[20]; //19 digits plus the null char
sprintf_P(TimeString, PSTR("%02d%c%02d%c%02d"), ts.Hour, delimiter, ts.Minute, delimiter, ts.Second);
if (am_pm) {
uint8_t hour(ts.Hour % 12);
if (hour == 0) { hour = 12; }
const char a_or_p = ts.Hour < 12 ? 'A' : 'P';
if (show_seconds) {
sprintf_P(TimeString, PSTR("%d%c%02d%c%02d %cM"),
hour, delimiter, ts.Minute, delimiter, ts.Second, a_or_p);
} else {
sprintf_P(TimeString, PSTR("%d%c%02d %cM"),
hour, delimiter, ts.Minute, a_or_p);
}
} else {
if (show_seconds) {
sprintf_P(TimeString, PSTR("%02d%c%02d%c%02d"),
ts.Hour, delimiter, ts.Minute, delimiter, ts.Second);
} else {
sprintf_P(TimeString, PSTR("%d%c%02d"),
ts.Hour, delimiter, ts.Minute);
}
}
return TimeString;
}
String getTimeString(char delimiter)
String getTimeString(char delimiter, bool show_seconds /*=true*/)
{
return getTimeString(tm, delimiter);
return getTimeString(tm, delimiter, false, show_seconds);
}
String getTimeString_ampm(char delimiter, bool show_seconds /*=true*/)
{
return getTimeString(tm, delimiter, true, show_seconds);
}
// returns the current Time without delimiter
@@ -395,26 +433,35 @@ String getTimeString()
return getTimeString('\0');
}
String getTimeString_ampm()
{
return getTimeString_ampm('\0');
}
// returns the current Date and Time separated by the given delimiter
// if called like this: getDateTimeString('\0', '\0', '\0');
// it will give back this: 20161231235959 (YYYYMMDDHHMMSS)
String getDateTimeString(const timeStruct& ts, char dateDelimiter, char timeDelimiter, char dateTimeDelimiter)
String getDateTimeString(const timeStruct& ts, char dateDelimiter, char timeDelimiter, char dateTimeDelimiter, bool am_pm)
{
String ret = getDateString(ts, dateDelimiter);
if (dateTimeDelimiter != '\0')
ret += dateTimeDelimiter;
ret += getTimeString(ts, timeDelimiter);
ret += getTimeString(ts, timeDelimiter, am_pm, true);
return ret;
}
String getDateTimeString(char dateDelimiter, char timeDelimiter, char dateTimeDelimiter) {
return getDateTimeString(tm, dateDelimiter, timeDelimiter, dateTimeDelimiter);
return getDateTimeString(tm, dateDelimiter, timeDelimiter, dateTimeDelimiter, false);
}
String getDateTimeString_ampm(char dateDelimiter, char timeDelimiter, char dateTimeDelimiter) {
return getDateTimeString(tm, dateDelimiter, timeDelimiter, dateTimeDelimiter, true);
}
/********************************************************************************************\
Convert a string like "Sun,12:30" into a 32 bit integer
\*********************************************************************************************/
unsigned long string2TimeLong(String &str)
unsigned long string2TimeLong(const String &str)
{
// format 0000WWWWAAAABBBBCCCCDDDD
// WWWW=weekday, AAAA=hours tens digit, BBBB=hours, CCCC=minutes tens digit DDDD=minutes
@@ -423,8 +470,12 @@ unsigned long string2TimeLong(String &str)
char TmpStr1[10];
int w, x, y;
unsigned long a;
str.toLowerCase();
str.toCharArray(command, 20);
{
// Within a scope so the tmpString is only used for copy.
String tmpString(str);
tmpString.toLowerCase();
tmpString.toCharArray(command, 20);
}
unsigned long lngTime = 0;
if (GetArgv(command, TmpStr1, 1))
+2 -2
View File
@@ -97,7 +97,7 @@ void logTimeZoneInfo() {
if (m_dstLoc != 0) {
timeStruct tmp;
breakTime(m_dstLoc, tmp);
log += getDateTimeString(tmp, '-', ':', ' ');
log += getDateTimeString(tmp, '-', ':', ' ', false);
}
log += F(" offset: ");
log += m_dst.offset;
@@ -108,7 +108,7 @@ void logTimeZoneInfo() {
if (m_stdLoc != 0) {
timeStruct tmp;
breakTime(m_stdLoc, tmp);
log += getDateTimeString(tmp, '-', ':', ' ');
log += getDateTimeString(tmp, '-', ':', ' ', false);
}
log += F(" offset: ");
log += m_std.offset;
+1738 -1283
View File
File diff suppressed because it is too large Load Diff
+249 -104
View File
@@ -80,10 +80,9 @@ void WifiAPMode(boolean state)
//********************************************************************************
// Configure network and connect to Wifi SSID and SSID2
// Set Wifi config
//********************************************************************************
boolean WifiConnect(byte connectAttempts)
{
void prepareWiFi() {
String log = "";
char hostname[40];
strncpy(hostname, WifiGetHostname().c_str(), sizeof(hostname));
@@ -106,127 +105,266 @@ boolean WifiConnect(byte connectAttempts)
const IPAddress dns = Settings.DNS;
WiFi.config(ip, gw, subnet, dns);
}
}
//try to connect to one of the access points
if (WifiConnectSSID(SecuritySettings.WifiSSID, SecuritySettings.WifiKey, connectAttempts) ||
WifiConnectSSID(SecuritySettings.WifiSSID2, SecuritySettings.WifiKey2, connectAttempts))
{
// fix octet?
if (Settings.IP_Octet != 0 && Settings.IP_Octet != 255)
{
IPAddress ip = WiFi.localIP();
IPAddress gw = WiFi.gatewayIP();
IPAddress subnet = WiFi.subnetMask();
ip[3] = Settings.IP_Octet;
log = F("IP : Fixed IP octet:");
log += ip;
addLog(LOG_LEVEL_INFO, log);
WiFi.config(ip, gw, subnet);
//********************************************************************************
// Configure network and connect to Wifi SSID and SSID2
//********************************************************************************
boolean WifiConnect(byte connectAttempts)
{
prepareWiFi();
if (anyValidWifiSettings()) {
//try to connect to one of the access points
bool connected = WifiConnectAndWait(connectAttempts);
if (!connected) {
if (selectNextWiFiSettings()) {
connected = WifiConnectAndWait(connectAttempts);
}
}
if (connected) {
return(true);
}
#ifdef FEATURE_MDNS
String log = F("WIFI : ");
if (MDNS.begin(WifiGetHostname().c_str(), WiFi.localIP())) {
log += F("mDNS started, with name: ");
log += WifiGetHostname();
log += F(".local");
}
else{
log += F("mDNS failed");
}
addLog(LOG_LEVEL_INFO, log);
#endif
return(true);
}
addLog(LOG_LEVEL_ERROR, F("WIFI : Could not connect to AP!"));
//everything failed, activate AP mode (will deactivate automatically after a while if its connected again)
WifiAPMode(true);
return(false);
}
//********************************************************************************
// Start connect to WiFi and check later to see if connected.
//********************************************************************************
void WiFiConnectRelaxed() {
prepareWiFi();
wifiConnected = false;
wifi_connect_attempt = 0;
if (anyValidWifiSettings()) {
tryConnectWiFi();
return;
}
addLog(LOG_LEVEL_ERROR, F("WIFI : Could not connect to AP, no valid WiFi settings!"));
//everything failed, activate AP mode (will deactivate automatically after a while if its connected again)
WifiAPMode(true);
}
//********************************************************************************
// Manage WiFi credentials
//********************************************************************************
const char* getLastWiFiSettingsSSID() {
return lastWiFiSettings == 0 ? SecuritySettings.WifiSSID : SecuritySettings.WifiSSID2;
}
const char* getLastWiFiSettingsPassphrase() {
return lastWiFiSettings == 0 ? SecuritySettings.WifiKey : SecuritySettings.WifiKey2;
}
bool anyValidWifiSettings() {
if (wifiSettingsValid(SecuritySettings.WifiSSID, SecuritySettings.WifiKey))
return true;
if (wifiSettingsValid(SecuritySettings.WifiSSID2, SecuritySettings.WifiKey2))
return true;
addLog(LOG_LEVEL_ERROR, F("WIFI : No valid WiFi settings!"));
return false;
}
bool selectNextWiFiSettings() {
lastWiFiSettings = (lastWiFiSettings + 1) % 2;
if (!wifiSettingsValid(getLastWiFiSettingsSSID(), getLastWiFiSettingsPassphrase())) {
// other settings are not correct, switch back.
lastWiFiSettings = (lastWiFiSettings + 1) % 2;
return false; // Nothing changed.
}
return true;
}
bool wifiSettingsValid(const char* ssid, const char* pass) {
if (ssid[0] == 0 || (strcasecmp(ssid, "ssid") == 0)) {
return false;
}
if (pass[0] == 0) return false;
return true;
}
bool wifiConnectTimeoutReached() {
if (wifi_connect_attempt == 0) return true;
// wait until it connects + add some device specific random offset to prevent
// all nodes overloading the accesspoint when turning on at the same time.
const unsigned int randomOffset_in_sec = wifi_connect_attempt == 1 ? 0 : 1000 * ((ESP.getChipId() & 0xF));
return timeOutReached(wifi_connect_timer + 7000 + randomOffset_in_sec);
}
//********************************************************************************
// Simply start the WiFi connection sequence
//********************************************************************************
bool tryConnectWiFi() {
if (wifiSetup && !wifiSetupConnect)
return false;
if (WiFi.status() == WL_CONNECTED)
return(true); //already connected, need to disconnect first
if (!wifiConnectTimeoutReached())
return true; // timeout not reached yet, thus no need to retry again.
if (wifi_connect_attempt != 0 && ((wifi_connect_attempt % 3) == 0)) {
// Change to other wifi settings.
if (selectNextWiFiSettings())
WiFi.disconnect();
}
if (wifi_connect_attempt > 6) {
//everything failed, activate AP mode (will deactivate automatically after a while if its connected again)
WifiAPMode(true);
}
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);
wifi_connect_timer = millis();
switch (wifi_connect_attempt) {
case 0:
if (lastBSSID[0] == 0)
WiFi.begin(ssid, passphrase);
else
WiFi.begin(ssid, passphrase, 0, &lastBSSID[0]);
break;
default:
WiFi.begin(ssid, passphrase);
}
++wifi_connect_attempt;
switch (WiFi.status()) {
case WL_NO_SSID_AVAIL: {
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);
return false;
}
case WL_CONNECTED:
checkWifiJustConnected();
break;
default:
break;
}
return true; // Sent
}
//********************************************************************************
// Connect to Wifi specific SSID
//********************************************************************************
boolean WifiConnectSSID(char WifiSSID[], char WifiKey[], byte connectAttempts)
boolean WifiConnectAndWait(byte connectAttempts)
{
String log;
//already connected, need to disconnect first
if (WiFi.status() == WL_CONNECTED)
return(true);
//no ssid specified
if ((WifiSSID[0] == 0) || (strcasecmp(WifiSSID, "ssid") == 0))
return(false);
for (byte tryConnect = 1; tryConnect <= connectAttempts; tryConnect++)
wifiConnected = false;
wifi_connect_attempt = 0;
for (byte tryConnect = 0; tryConnect < connectAttempts; tryConnect++)
{
log = F("WIFI : Connecting ");
log += WifiSSID;
log += F(" attempt #");
log += tryConnect;
addLog(LOG_LEVEL_INFO, log);
if (tryConnect == 1)
WiFi.begin(WifiSSID, WifiKey);
else
WiFi.begin();
//wait until it connects
for (byte x = 0; x < 200; x++)
{
if (!WiFiConnected(50))
{
statusLED(false);
// No delay needed, since the WiFi check has a delay
}
else
break;
}
if (WiFi.status() == WL_CONNECTED)
{
if (Settings.UseNTP) {
initTime();
}
log = F("WIFI : Connected! IP: ");
log += formatIP(WiFi.localIP());
log += F(" (");
log += WifiGetHostname();
log += F(")");
addLog(LOG_LEVEL_INFO, log);
statusLED(true);
return(true);
}
else
{
// log = F("WIFI : Disconnecting!");
// addLog(LOG_LEVEL_INFO, log);
#if defined(ESP8266)
ETS_UART_INTR_DISABLE();
wifi_station_disconnect();
ETS_UART_INTR_ENABLE();
#endif
for (byte x = 0; x < 20; x++)
{
statusLED(true);
if (tryConnectWiFi()) {
do {
if (checkWifiJustConnected())
return true;
delay(50);
}
} while (!wifiConnectTimeoutReached());
}
// log = F("WIFI : Disconnecting!");
// addLog(LOG_LEVEL_INFO, log);
#if defined(ESP8266)
ETS_UART_INTR_DISABLE();
wifi_station_disconnect();
ETS_UART_INTR_ENABLE();
#endif
for (byte x = 0; x < 20; x++)
{
statusLED(true);
delay(50);
}
}
return false;
}
bool checkWifiJustConnected() {
if (wifiConnected) return true;
if (WiFi.status() != WL_CONNECTED) {
statusLED(false);
delay(1);
return false;
}
wifiConnected = true;
String log = F("WIFI : WiFi connect attempt took: ");
log += timePassedSince(wifi_connect_timer);
log += F(" ms");
addLog(LOG_LEVEL_INFO, log);
// fix octet?
if (Settings.IP_Octet != 0 && Settings.IP_Octet != 255)
{
IPAddress ip = WiFi.localIP();
IPAddress gw = WiFi.gatewayIP();
IPAddress subnet = WiFi.subnetMask();
ip[3] = Settings.IP_Octet;
log = F("IP : Fixed IP octet:");
log += ip;
addLog(LOG_LEVEL_INFO, log);
WiFi.config(ip, gw, subnet);
}
#ifdef FEATURE_MDNS
String log = F("WIFI : ");
if (MDNS.begin(WifiGetHostname().c_str(), WiFi.localIP())) {
log += F("mDNS started, with name: ");
log += WifiGetHostname();
log += F(".local");
}
else{
log += F("mDNS failed");
}
addLog(LOG_LEVEL_INFO, log);
#endif
// First try to get the time, since that may be used in logs
if (Settings.UseNTP) {
initTime();
}
uint8_t* curBSSID = WiFi.BSSID();
bool changed = false;
for (byte i=0; i < 6; ++i) {
if (lastBSSID[i] != *(curBSSID + i)) {
changed = true;
lastBSSID[i] = *(curBSSID + i);
}
}
if (Settings.UseRules)
{
if (changed) {
String event = F("WiFi#ChangedAccesspoint");
rulesProcessing(event);
}
String event = F("WiFi#Connected");
rulesProcessing(event);
}
log = F("WIFI : Connected! IP: ");
log += formatIP(WiFi.localIP());
log += F(" (");
log += WifiGetHostname();
log += F(") AP: ");
log += WiFi.SSID();
log += F(" AP BSSID: ");
log += WiFi.BSSIDstr();
addLog(LOG_LEVEL_INFO, log);
statusLED(true);
return true;
}
//********************************************************************************
// Disconnect from Wifi AP
@@ -234,6 +372,7 @@ boolean WifiConnectSSID(char WifiSSID[], char WifiKey[], byte connectAttempts)
void WifiDisconnect()
{
WiFi.disconnect();
wifiConnected = false;
}
@@ -275,7 +414,6 @@ void WifiScan()
//********************************************************************************
void WifiCheck()
{
if(wifiSetup)
return;
@@ -285,8 +423,11 @@ void WifiCheck()
//give it time to automatically reconnect
if (NC_Count > 2)
{
WifiConnect(2);
if (wifiConnected) {
wifi_connect_attempt = 0;
wifiConnected = false;
WiFiConnectRelaxed();
}
C_Count=0;
NC_Count = 0;
}
@@ -301,6 +442,10 @@ void WifiCheck()
WifiAPMode(false);
}
}
if (!wifiConnected) {
if (tryConnectWiFi())
checkWifiJustConnected();
}
}
//********************************************************************************
+25 -88
View File
@@ -76,64 +76,6 @@ boolean CPlugin_001(byte function, struct EventStruct *event, String& string)
switch (event->sensorType)
{
case SENSOR_TYPE_SINGLE: // single value sensor, used for Dallas, BH1750, etc
url += F("&svalue=");
url += formatUserVar(event, 0);
break;
case SENSOR_TYPE_LONG: // single LONG value, stored in two floats (rfid tags)
url += F("&svalue=");
url += (unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16);
break;
case SENSOR_TYPE_DUAL: // any sensor that uses two simple values
url += F("&svalue=");
url += formatUserVar(event, 0);
url += (";");
url += formatUserVar(event, 1);
break;
case SENSOR_TYPE_TEMP_HUM: // temp + hum + hum_stat, used for DHT11
url += F("&svalue=");
url += formatUserVar(event, 0);
url += F(";");
url += formatUserVar(event, 1);
url += F(";");
url += humStat(UserVar[event->BaseVarIndex + 1]);
break;
case SENSOR_TYPE_TEMP_BARO: // temp + bar used for BMP085 and BMP280
url += F("&svalue=");
url += formatUserVar(event, 0);
url += F(";0;0;");
url += formatUserVar(event, 1);
url += F(";0");
break;
case SENSOR_TYPE_TRIPLE:
url += F("&svalue=");
url += formatUserVar(event, 0);
url += F(";");
url += formatUserVar(event, 1);
url += F(";");
url += formatUserVar(event, 2);
break;
case SENSOR_TYPE_TEMP_HUM_BARO: // temp + hum + hum_stat + bar + bar_fore, used for BME280
url += F("&svalue=");
url += formatUserVar(event, 0);
url += F(";");
url += formatUserVar(event, 1);
url += F(";");
url += humStat(UserVar[event->BaseVarIndex + 1]);
url += F(";");
url += formatUserVar(event, 2);
url += F(";0");
break;
case SENSOR_TYPE_QUAD:
url += F("&svalue=");
url += formatUserVar(event, 0);
url += F(";");
url += formatUserVar(event, 1);
url += F(";");
url += formatUserVar(event, 2);
url += F(";");
url += formatUserVar(event, 3);
break;
case SENSOR_TYPE_SWITCH:
url = F("/json.htm?type=command&param=switchlight&idx=");
url += event->idx;
@@ -147,28 +89,39 @@ boolean CPlugin_001(byte function, struct EventStruct *event, String& string)
url = F("/json.htm?type=command&param=switchlight&idx=");
url += event->idx;
url += F("&switchcmd=");
if (UserVar[event->BaseVarIndex] == 0)
if (UserVar[event->BaseVarIndex] == 0) {
url += ("Off");
else
{
} else {
url += F("Set%20Level&level=");
url += UserVar[event->BaseVarIndex];
}
break;
case (SENSOR_TYPE_WIND):
url += F("&svalue="); // WindDir in degrees; WindDir as text; Wind speed average ; Wind speed gust; 0
url += formatUserVar(event, 0);
url += ";";
url += getBearing(UserVar[event->BaseVarIndex]);
url += ";";
// Domoticz expects the wind speed in (m/s * 10)
url += toString((UserVar[event->BaseVarIndex + 1] * 10),ExtraTaskSettings.TaskDeviceValueDecimals[1]);
url += ";";
url += toString((UserVar[event->BaseVarIndex + 2] * 10),ExtraTaskSettings.TaskDeviceValueDecimals[2]);
url += ";0;0";
case SENSOR_TYPE_SINGLE:
case SENSOR_TYPE_LONG:
case SENSOR_TYPE_DUAL:
case SENSOR_TYPE_TRIPLE:
case SENSOR_TYPE_QUAD:
case SENSOR_TYPE_TEMP_HUM:
case SENSOR_TYPE_TEMP_BARO:
case SENSOR_TYPE_TEMP_HUM_BARO:
case SENSOR_TYPE_WIND:
default:
url = F("/json.htm?type=command&param=udevice&idx=");
url += event->idx;
url += F("&nvalue=0");
url += F("&svalue=");
url += formatDomoticzSensorType(event);
break;
}
// Add WiFi reception quality
url += F("&rssi=");
url += mapRSSItoDomoticz();
#if FEATURE_ADC_VCC
url += F("&battery=");
url += mapVccToDomoticz();
#endif
// This will send the request to the server
String request = F("GET ");
@@ -212,19 +165,3 @@ boolean CPlugin_001(byte function, struct EventStruct *event, String& string)
}
return success;
}
int humStat(int hum){
int lHumStat;
if(hum<30){
lHumStat = 2;
}else if(hum<40){
lHumStat = 0;
}else if(hum<59){
lHumStat = 1;
}else{
lHumStat = 3;
}
return lHumStat;
}
+21 -105
View File
@@ -135,104 +135,23 @@ boolean CPlugin_002(byte function, struct EventStruct *event, String& string)
{
if (event->idx != 0)
{
if (!WiFiConnected(100)) {
ControllerSettingsStruct ControllerSettings;
LoadControllerSettings(event->ControllerIndex, (byte*)&ControllerSettings, sizeof(ControllerSettings));
if (!ControllerSettings.checkHostReachable(true)) {
success = false;
break;
}
ControllerSettingsStruct ControllerSettings;
LoadControllerSettings(event->ControllerIndex, (byte*)&ControllerSettings, sizeof(ControllerSettings));
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root[F("idx")] = event->idx;
String values;
// char str[80];
root[F("RSSI")] = mapRSSItoDomoticz();
#if FEATURE_ADC_VCC
root[F("Battery")] = mapVccToDomoticz();
#endif
switch (event->sensorType)
{
case SENSOR_TYPE_SINGLE: // single value sensor, used for Dallas, BH1750, etc
root[F("nvalue")] = 0;
values = formatUserVar(event, 0);
// values.toCharArray(str, 80);
root[F("svalue")] = values.c_str();
break;
case SENSOR_TYPE_LONG: // single LONG value, stored in two floats (rfid tags)
root[F("nvalue")] = 0;
values = (unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16);
// values.toCharArray(str, 80);
root[F("svalue")] = values.c_str();
break;
case SENSOR_TYPE_DUAL: // any sensor that uses two simple values
root[F("nvalue")] = 0;
values = formatUserVar(event, 0);
values += ";";
values += formatUserVar(event, 1);
// values.toCharArray(str, 80);
root[F("svalue")] = values.c_str();
// root[F("svalue")] = str;
break;
case SENSOR_TYPE_TRIPLE: // any sensor that uses three simple values
root[F("nvalue")] = 0;
values = formatUserVar(event, 0);
values += ";";
values += formatUserVar(event, 1);
values += ";";
values += formatUserVar(event, 2);
// values.toCharArray(str, 80);
root[F("svalue")] = values.c_str();
// root[F("svalue")] = str;
break;
case SENSOR_TYPE_TEMP_HUM: // temp + hum + hum_stat, used for DHT11
root[F("nvalue")] = 0;
values = formatUserVar(event, 0);
values += ";";
values += formatUserVar(event, 1);
//FIXME: this should be the same as in C001?, instead of 0:
// url += humStat(UserVar[event->BaseVarIndex + 1]);
values += ";0";
// values.toCharArray(str, 80);
root[F("svalue")] = values.c_str();
// root[F("svalue")] = str;
break;
case SENSOR_TYPE_TEMP_BARO: // temp + hum + hum_stat + bar + bar_fore, used for BMP085
root[F("nvalue")] = 0;
values = formatUserVar(event, 0);
values += ";0;0;";
values += formatUserVar(event, 1);
values += ";0";
// values.toCharArray(str, 80);
root[F("svalue")] = values.c_str();
// root[F("svalue")] = str;
break;
case SENSOR_TYPE_TEMP_HUM_BARO: // temp + hum + hum_stat + bar + bar_fore, used for BME280
root[F("nvalue")] = 0;
values = formatUserVar(event, 0);
values += ";";
values += formatUserVar(event, 1);
values += ";0;";
values += formatUserVar(event, 2);
values += ";0";
root[F("svalue")] = values.c_str();
// values.toCharArray(str, 80);
// root[F("svalue")] = str;
break;
case SENSOR_TYPE_QUAD:
root[F("nvalue")] = 0;
values = formatUserVar(event, 0);
values += ";";
values += formatUserVar(event, 1);
values += ";";
values += formatUserVar(event, 2);
values += ";";
values += formatUserVar(event, 3);
root[F("svalue")] = values.c_str();
// values.toCharArray(str, 80);
// root[F("svalue")] = str;
break;
case SENSOR_TYPE_SWITCH:
root[F("command")] = String(F("switchlight"));
if (UserVar[event->BaseVarIndex] == 0)
@@ -247,22 +166,20 @@ boolean CPlugin_002(byte function, struct EventStruct *event, String& string)
else
root[F("Set%20Level")] = UserVar[event->BaseVarIndex];
break;
case SENSOR_TYPE_WIND: // WindDir in degrees; WindDir as text; Wind speed average ; Wind speed gust
values = formatUserVar(event, 0);
values += ";";
values += getBearing(UserVar[event->BaseVarIndex]);
values += ";";
// Domoticz expects the wind speed in (m/s * 10)
values += toString((UserVar[event->BaseVarIndex + 1] * 10),ExtraTaskSettings.TaskDeviceValueDecimals[1]);
values += ";";
values += toString((UserVar[event->BaseVarIndex + 2] * 10),ExtraTaskSettings.TaskDeviceValueDecimals[2]);
values += ";0;0";
root[F("svalue")] = values.c_str();
// values.toCharArray(str, 80);
// root["svalue"] = str;
case SENSOR_TYPE_SINGLE:
case SENSOR_TYPE_LONG:
case SENSOR_TYPE_DUAL:
case SENSOR_TYPE_TRIPLE:
case SENSOR_TYPE_QUAD:
case SENSOR_TYPE_TEMP_HUM:
case SENSOR_TYPE_TEMP_BARO:
case SENSOR_TYPE_TEMP_HUM_BARO:
case SENSOR_TYPE_WIND:
default:
root[F("nvalue")] = 0;
root[F("svalue")] = formatDomoticzSensorType(event);
break;
}
String json;
@@ -272,8 +189,7 @@ boolean CPlugin_002(byte function, struct EventStruct *event, String& string)
addLog(LOG_LEVEL_DEBUG, log);
String pubname = ControllerSettings.Publish;
parseSystemVariables(pubname, false);
parseEventVariables(pubname, event, false);
parseControllerVariables(pubname, event, false);
if (!MQTTpublish(event->ControllerIndex, pubname.c_str(), json.c_str(), Settings.MQTTRetainFlag))
{
connectionFailures++;
+27 -34
View File
@@ -44,44 +44,38 @@ boolean CPlugin_005(byte function, struct EventStruct *event, String& string)
// Controller is not enabled.
break;
} else {
// Split topic into array
String tmpTopic = event->String1.substring(1);
String topicSplit[10];
int SlashIndex = tmpTopic.indexOf('/');
byte count = 0;
while (SlashIndex > 0 && (count < (10 - 1)))
{
topicSplit[count] = tmpTopic.substring(0, SlashIndex);
tmpTopic = tmpTopic.substring(SlashIndex + 1);
SlashIndex = tmpTopic.indexOf('/');
count++;
}
topicSplit[count] = tmpTopic;
String cmd = "";
String cmd;
struct EventStruct TempEvent;
if (topicSplit[count] == F("cmd"))
{
bool validTopic = false;
const int lastindex = event->String1.lastIndexOf('/');
const String lastPartTopic = event->String1.substring(lastindex + 1);
if (lastPartTopic == F("cmd")) {
cmd = event->String2;
parseCommandString(&TempEvent, cmd);
TempEvent.Source = VALUE_SOURCE_MQTT;
validTopic = true;
} else {
if (lastindex > 0) {
// Topic has at least one separator
if (isFloat(event->String2) && isInt(lastPartTopic)) {
int prevLastindex = event->String1.lastIndexOf('/', lastindex - 1);
cmd = event->String1.substring(prevLastindex + 1, lastindex);
TempEvent.Par1 = lastPartTopic.toInt();
TempEvent.Par2 = event->String2.toFloat();
TempEvent.Par3 = 0;
validTopic = true;
}
}
}
else
{
cmd = topicSplit[count - 1];
TempEvent.Par1 = topicSplit[count].toInt();
TempEvent.Par2 = event->String2.toFloat();
TempEvent.Par3 = 0;
}
// in case of event, store to buffer and return...
String command = parseString(cmd, 1);
if (command == F("event"))
if (validTopic) {
// in case of event, store to buffer and return...
String command = parseString(cmd, 1);
if (command == F("event")) {
eventBuffer = cmd.substring(6);
else if
(PluginCall(PLUGIN_WRITE, &TempEvent, cmd));
else
remoteConfig(&TempEvent, cmd);
} else if (!PluginCall(PLUGIN_WRITE, &TempEvent, cmd)) {
remoteConfig(&TempEvent, cmd);
}
}
}
break;
}
@@ -101,8 +95,7 @@ boolean CPlugin_005(byte function, struct EventStruct *event, String& string)
PluginCall(PLUGIN_GET_DEVICEVALUENAMES, event, dummyString);
String pubname = ControllerSettings.Publish;
parseSystemVariables(pubname, false);
parseEventVariables(pubname, event, false);
parseControllerVariables(pubname, event, false);
String value = "";
// byte DeviceIndex = getDeviceIndex(Settings.TaskDeviceNumber[event->TaskIndex]);
+1 -2
View File
@@ -89,8 +89,7 @@ boolean CPlugin_006(byte function, struct EventStruct *event, String& string)
PluginCall(PLUGIN_GET_DEVICEVALUENAMES, event, dummyString);
String pubname = ControllerSettings.Publish;
parseSystemVariables(pubname, false);
parseEventVariables(pubname, event, false);
parseControllerVariables(pubname, event, false);
String value = "";
// byte DeviceIndex = getDeviceIndex(Settings.TaskDeviceNumber[event->TaskIndex]);
+13 -39
View File
@@ -35,6 +35,12 @@ boolean CPlugin_007(byte function, struct EventStruct *event, String& string)
success = false;
break;
}
const byte valueCount = getValueCountFromSensorType(event->sensorType);
if (valueCount == 0 || valueCount > 3) {
addLog(LOG_LEVEL_ERROR, F("emoncms : Unknown sensortype or too many sensor values"));
break;
}
ControllerSettingsStruct ControllerSettings;
LoadControllerSettings(event->ControllerIndex, (byte*)&ControllerSettings, sizeof(ControllerSettings));
@@ -59,46 +65,14 @@ boolean CPlugin_007(byte function, struct EventStruct *event, String& string)
postDataStr += Settings.Unit;
postDataStr += F("&json=");
switch (event->sensorType)
{
case SENSOR_TYPE_SINGLE: // single value sensor, used for Dallas, BH1750, etc
case SENSOR_TYPE_SWITCH: // report switch state
postDataStr += F("{field");
postDataStr += event->idx;
postDataStr += ":";
postDataStr += formatUserVar(event, 0);
postDataStr += "}";
break;
case SENSOR_TYPE_TEMP_HUM: // dual value
case SENSOR_TYPE_TEMP_BARO:
case SENSOR_TYPE_DUAL:
postDataStr += F("{field");
postDataStr += event->idx;
postDataStr += ":";
postDataStr += formatUserVar(event, 0);
postDataStr += F(",field");
postDataStr += event->idx + 1;
postDataStr += ":";
postDataStr += formatUserVar(event, 1);
postDataStr += "}";
break;
case SENSOR_TYPE_TEMP_HUM_BARO:
case SENSOR_TYPE_TRIPLE:
postDataStr += F("{field");
postDataStr += event->idx;
postDataStr += ":";
postDataStr += formatUserVar(event, 0);
postDataStr += F(",field");
postDataStr += event->idx + 1;
postDataStr += ":";
postDataStr += formatUserVar(event, 1);
postDataStr += F(",field");
postDataStr += event->idx + 2;
postDataStr += ":";
postDataStr += formatUserVar(event, 2);
postDataStr += "}";
break;
for (byte i = 0; i < valueCount; ++i) {
postDataStr += (i == 0) ? F("{") : F(",");
postDataStr += F("field");
postDataStr += event->idx + i;
postDataStr += ":";
postDataStr += formatUserVar(event, i);
}
postDataStr += "}";
postDataStr += F("&apikey=");
postDataStr += SecuritySettings.ControllerPassword[event->ControllerIndex]; // "0UDNN17RW6XAS2E5" // api key
+1 -2
View File
@@ -105,8 +105,7 @@ boolean HTTPSend(struct EventStruct *event, byte varIndex, float value, unsigned
String url = "/";
url += ControllerSettings.Publish;
parseSystemVariables(url, true);
parseEventVariables(url, event, true);
parseControllerVariables(url, event, true);
url.replace(F("%valname%"), URLEncode(ExtraTaskSettings.TaskDeviceValueNames[varIndex]));
if (longValue)
+2 -6
View File
@@ -80,11 +80,7 @@ void C010_Send(struct EventStruct *event, byte varIndex, float value, unsigned l
String msg = "";
msg += ControllerSettings.Publish;
parseSystemVariables(msg, false);
parseEventVariables(msg, event, false);
msg.replace(F("%sysname%"), Settings.Name);
msg.replace(F("%tskname%"), ExtraTaskSettings.TaskDeviceName);
msg.replace(F("%id%"), String(event->idx));
parseControllerVariables(msg, event, false);
msg.replace(F("%valname%"), ExtraTaskSettings.TaskDeviceValueNames[varIndex]);
if (longValue)
msg.replace(F("%value%"), String(longValue));
@@ -93,7 +89,7 @@ void C010_Send(struct EventStruct *event, byte varIndex, float value, unsigned l
if (WiFi.status() == WL_CONNECTED) {
ControllerSettings.beginPacket(portUDP);
portUDP.write(msg.c_str());
portUDP.write((uint8_t*)msg.c_str(),msg.length());
portUDP.endPacket();
}
+3 -34
View File
@@ -270,44 +270,13 @@ void ReplaceTokenByValue(String& s, struct EventStruct *event)
// %1%%vname1%,Standort=%tskname% Wert=%val1%%/1%%2%%LF%%vname2%,Standort=%tskname% Wert=%val2%%/2%%3%%LF%%vname3%,Standort=%tskname% Wert=%val3%%/3%%4%%LF%%vname4%,Standort=%tskname% Wert=%val4%%/4%
addLog(LOG_LEVEL_DEBUG_MORE, F("HTTP before parsing: "));
addLog(LOG_LEVEL_DEBUG_MORE, s);
switch (event->sensorType)
{
case SENSOR_TYPE_SINGLE:
case SENSOR_TYPE_SWITCH:
case SENSOR_TYPE_DIMMER:
case SENSOR_TYPE_WIND:
case SENSOR_TYPE_LONG:
{
DeleteNotNeededValues(s,1);
break;
}
case SENSOR_TYPE_DUAL:
case SENSOR_TYPE_TEMP_HUM:
case SENSOR_TYPE_TEMP_BARO:
{
DeleteNotNeededValues(s,2);
break;
}
case SENSOR_TYPE_TRIPLE:
case SENSOR_TYPE_TEMP_HUM_BARO:
{
DeleteNotNeededValues(s,3);
break;
}
case SENSOR_TYPE_QUAD:
{
DeleteNotNeededValues(s,4);
break;
}
}
const byte valueCount = getValueCountFromSensorType(event->sensorType);
DeleteNotNeededValues(s,valueCount);
addLog(LOG_LEVEL_DEBUG_MORE, F("HTTP after parsing: "));
addLog(LOG_LEVEL_DEBUG_MORE, s);
//NOTE: cant we just call parseTemplate() for all the standard stuff??
parseSystemVariables(s, true);
parseEventVariables(s, event, true);
parseControllerVariables(s, event, true);
addLog(LOG_LEVEL_DEBUG_MORE, F("HTTP after replacements: "));
addLog(LOG_LEVEL_DEBUG_MORE, s);
+2 -23
View File
@@ -39,29 +39,8 @@ boolean CPlugin_012(byte function, struct EventStruct *event, String& string)
}
String postDataStr = F("");
switch (event->sensorType)
{
case SENSOR_TYPE_SINGLE: // single value sensor, used for Dallas, BH1750, etc
success = CPlugin_012_send(event, 1);
break;
case SENSOR_TYPE_TEMP_HUM: // dual value
case SENSOR_TYPE_TEMP_BARO:
case SENSOR_TYPE_DUAL:
success = CPlugin_012_send(event, 2);
break;
case SENSOR_TYPE_TEMP_HUM_BARO:
case SENSOR_TYPE_TRIPLE:
success = CPlugin_012_send(event, 3);
break;
case SENSOR_TYPE_QUAD:
success = CPlugin_012_send(event, 4);
break;
case SENSOR_TYPE_SWITCH:
success = CPlugin_012_send(event, 1);
break;
}
const byte valueCount = getValueCountFromSensorType(event->sensorType);
success = CPlugin_012_send(event, valueCount);
break;
}
}
+265
View File
@@ -0,0 +1,265 @@
//#######################################################################################################
//########################### Controller Plugin 013: ESPEasy P2P network ################################
//#######################################################################################################
#define CPLUGIN_013
#define CPLUGIN_ID_013 13
#define CPLUGIN_NAME_013 "ESPEasy P2P Networking"
WiFiUDP C013_portUDP;
struct infoStruct
{
byte header = 255;
byte ID = 3;
byte sourcelUnit;
byte destUnit;
byte sourceTaskIndex;
byte destTaskIndex;
byte deviceNumber;
char taskName[26];
char ValueNames[VARS_PER_TASK][26];
};
struct dataStruct
{
byte header = 255;
byte ID = 5;
byte sourcelUnit;
byte destUnit;
byte sourceTaskIndex;
byte destTaskIndex;
float Values[VARS_PER_TASK];
};
boolean CPlugin_013(byte function, struct EventStruct *event, String& string)
{
boolean success = false;
switch (function)
{
case CPLUGIN_PROTOCOL_ADD:
{
Protocol[++protocolCount].Number = CPLUGIN_ID_013;
Protocol[protocolCount].usesMQTT = false;
Protocol[protocolCount].usesTemplate = false;
Protocol[protocolCount].usesAccount = false;
Protocol[protocolCount].usesPassword = false;
Protocol[protocolCount].defaultPort = 65501;
Protocol[protocolCount].usesID = false;
Protocol[protocolCount].Custom = true;
break;
}
case CPLUGIN_GET_DEVICENAME:
{
string = F(CPLUGIN_NAME_013);
break;
}
case CPLUGIN_PROTOCOL_TEMPLATE:
{
event->String1 = "";
event->String2 = "";
break;
}
case CPLUGIN_INIT:
{
//C013_portUDP.begin(Settings.UDPPort);
break;
}
case CPLUGIN_TASK_CHANGE_NOTIFICATION:
{
C013_SendUDPTaskInfo(0, event->TaskIndex, event->TaskIndex);
break;
}
case CPLUGIN_PROTOCOL_SEND:
{
C013_Send(event, 0, UserVar[event->BaseVarIndex], 0);
break;
}
case CPLUGIN_UDP_IN:
{
C013_Receive(event);
break;
}
}
return success;
}
//********************************************************************************
// Generic UDP message
//********************************************************************************
void C013_Send(struct EventStruct *event, byte varIndex, float value, unsigned long longValue)
{
ControllerSettingsStruct ControllerSettings;
LoadControllerSettings(event->ControllerIndex, (byte*)&ControllerSettings, sizeof(ControllerSettings));
statusLED(true);
C013_SendUDPTaskData(0, event->TaskIndex, event->TaskIndex);
}
void C013_SendUDPTaskInfo(byte destUnit, byte sourceTaskIndex, byte destTaskIndex)
{
if (!WiFiConnected(100)) {
return;
}
struct infoStruct infoReply;
infoReply.sourcelUnit = Settings.Unit;
infoReply.sourceTaskIndex = sourceTaskIndex;
infoReply.destTaskIndex = destTaskIndex;
LoadTaskSettings(infoReply.sourceTaskIndex);
infoReply.deviceNumber = Settings.TaskDeviceNumber[infoReply.sourceTaskIndex];
strcpy(infoReply.taskName, ExtraTaskSettings.TaskDeviceName);
for (byte x = 0; x < VARS_PER_TASK; x++)
strcpy(infoReply.ValueNames[x], ExtraTaskSettings.TaskDeviceValueNames[x]);
byte firstUnit = 1;
byte lastUnit = UNIT_MAX - 1;
if (destUnit != 0)
{
firstUnit = destUnit;
lastUnit = destUnit;
}
for (byte x = firstUnit; x <= lastUnit; x++)
{
if (x != Settings.Unit){
infoReply.destUnit = x;
C013_sendUDP(x, (byte*)&infoReply, sizeof(infoStruct));
delay(10);
}
}
delay(50);
}
void C013_SendUDPTaskData(byte destUnit, byte sourceTaskIndex, byte destTaskIndex)
{
if (!WiFiConnected(100)) {
return;
}
struct dataStruct dataReply;
dataReply.sourcelUnit = Settings.Unit;
dataReply.sourceTaskIndex = sourceTaskIndex;
dataReply.destTaskIndex = destTaskIndex;
for (byte x = 0; x < VARS_PER_TASK; x++)
dataReply.Values[x] = UserVar[dataReply.sourceTaskIndex * VARS_PER_TASK + x];
byte firstUnit = 1;
byte lastUnit = UNIT_MAX - 1;
if (destUnit != 0)
{
firstUnit = destUnit;
lastUnit = destUnit;
}
for (byte x = firstUnit; x <= lastUnit; x++)
{
if (x != Settings.Unit){
dataReply.destUnit = x;
C013_sendUDP(x, (byte*) &dataReply, sizeof(dataStruct));
delay(10);
}
}
delay(50);
}
/*********************************************************************************************\
Send UDP message (unit 255=broadcast)
\*********************************************************************************************/
void C013_sendUDP(byte unit, byte* data, byte size)
{
if (!WiFiConnected(100)) {
return;
}
if (unit != 255)
if (Nodes[unit].ip[0] == 0)
return;
String log = "C013 : Send UDP message to ";
log += unit;
addLog(LOG_LEVEL_DEBUG_MORE, log);
statusLED(true);
IPAddress remoteNodeIP;
if (unit == 255)
remoteNodeIP = {255, 255, 255, 255};
else
remoteNodeIP = Nodes[unit].ip;
C013_portUDP.beginPacket(remoteNodeIP, Settings.UDPPort);
C013_portUDP.write(data, size);
C013_portUDP.endPacket();
}
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++)
{
log += " ";
log += (int)event->Data[x];
}
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
switch (event->Data[1]) {
case 2: // sensor info pull request
{
//SendUDPTaskInfo(packetBuffer[2], packetBuffer[5], packetBuffer[4]);
break;
}
case 3: // sensor info
{
struct infoStruct infoReply;
memcpy((byte*)&infoReply, (byte*)event->Data, sizeof(infoStruct));
// to prevent flash wear out (bugs in communication?) we can only write to an empty task
// so it will write only once and has to be cleared manually through webgui
if (Settings.TaskDeviceNumber[infoReply.destTaskIndex] == 0)
{
Settings.TaskDeviceNumber[infoReply.destTaskIndex] = infoReply.deviceNumber;
Settings.TaskDeviceDataFeed[infoReply.destTaskIndex] = 1; // remote feed
for (byte x = 0; x < CONTROLLER_MAX; x++)
Settings.TaskDeviceSendData[x][infoReply.destTaskIndex] = false;
strcpy(ExtraTaskSettings.TaskDeviceName, infoReply.taskName);
for (byte x = 0; x < VARS_PER_TASK; x++)
strcpy( ExtraTaskSettings.TaskDeviceValueNames[x], infoReply.ValueNames[x]);
SaveTaskSettings(infoReply.destTaskIndex);
SaveSettings();
}
break;
}
case 4: // sensor data pull request
{
//SendUDPTaskData(packetBuffer[2], packetBuffer[5], packetBuffer[4]);
break;
}
case 5: // sensor data
{
struct dataStruct dataReply;
memcpy((byte*)&dataReply, (byte*)event->Data, sizeof(dataStruct));
// only if this task has a remote feed, update values
if (Settings.TaskDeviceDataFeed[dataReply.destTaskIndex] != 0)
{
for (byte x = 0; x < VARS_PER_TASK; x++)
{
UserVar[dataReply.destTaskIndex * VARS_PER_TASK + x] = dataReply.Values[x];
}
if (Settings.UseRules)
createRuleEvents(dataReply.destTaskIndex);
}
break;
}
}
}
+140
View File
@@ -0,0 +1,140 @@
// HUM_STAT can be one of:
// 0=Normal
// 1=Comfortable
// 2=Dry
// 3=Wet
String humStatDomoticz(struct EventStruct *event, byte rel_index){
const int hum = UserVar[event->BaseVarIndex + rel_index];
if (hum < 30) { return formatUserVarDomoticz(2); }
if (hum < 40) { return formatUserVarDomoticz(0); }
if (hum < 59) { return formatUserVarDomoticz(1); }
return formatUserVarDomoticz(3);
}
int mapRSSItoDomoticz() {
long rssi = WiFi.RSSI();
if (-50 < rssi) { return 10; }
if (rssi <= -98) { return 0; }
rssi = rssi + 97; // Range 0..47 => 1..9
return (rssi / 5) + 1;
}
int mapVccToDomoticz() {
#if FEATURE_ADC_VCC
// Voltage range from 2.6V .. 3.6V => 0..100%
if (vcc < 2.6) return 0;
return (vcc - 2.6) * 100;
#else
return 255;
#endif
}
// Format including trailing semi colon
String formatUserVarDomoticz(struct EventStruct *event, byte rel_index) {
String text = formatUserVar(event, rel_index);
text += F(";");
return text;
}
String formatUserVarDomoticz(int value) {
String text;
text += value;
text.trim();
text += F(";");
return text;
}
String formatDomoticzSensorType(struct EventStruct *event) {
String values;
switch (event->sensorType)
{
case SENSOR_TYPE_SINGLE: // single value sensor, used for Dallas, BH1750, etc
values = formatUserVarDomoticz(event, 0);
break;
case SENSOR_TYPE_LONG: // single LONG value, stored in two floats (rfid tags)
values = (unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16);
break;
case SENSOR_TYPE_DUAL: // any sensor that uses two simple values
values = formatUserVarDomoticz(event, 0);
values += formatUserVarDomoticz(event, 1);
break;
case SENSOR_TYPE_TEMP_HUM:
// temp + hum + hum_stat, used for DHT11
// http://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Temperature.2Fhumidity
values = formatUserVarDomoticz(event, 0); // TEMP = Temperature
values += formatUserVarDomoticz(event, 1); // HUM = Humidity
values += humStatDomoticz(event, 1); // HUM_STAT = Humidity status
break;
case SENSOR_TYPE_TEMP_HUM_BARO:
// temp + hum + hum_stat + bar + bar_fore, used for BME280
// http://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Temperature.2Fhumidity.2Fbarometer
values = formatUserVarDomoticz(event, 0); // TEMP = Temperature
values += formatUserVarDomoticz(event, 1); // HUM = Humidity
values += humStatDomoticz(event, 1); // HUM_STAT = Humidity status
values += formatUserVarDomoticz(event, 2); // BAR = Barometric pressure
values += formatUserVarDomoticz(0); // BAR_FOR = Barometer forecast
break;
case SENSOR_TYPE_TEMP_BARO:
// temp + hum + hum_stat + bar + bar_fore, used for BMP085
// http://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Temperature.2Fbarometer
values = formatUserVarDomoticz(event, 0); // TEMP = Temperature
values += formatUserVarDomoticz(event, 1); // BAR = Barometric pressure
values += formatUserVarDomoticz(0); // BAR_FOR = Barometer forecast
values += formatUserVarDomoticz(0); // ALTITUDE= Not used at the moment, can be 0
break;
case SENSOR_TYPE_TRIPLE:
values = formatUserVarDomoticz(event, 0);
values += formatUserVarDomoticz(event, 1);
values += formatUserVarDomoticz(event, 2);
break;
case SENSOR_TYPE_QUAD:
values = formatUserVarDomoticz(event, 0);
values += formatUserVarDomoticz(event, 1);
values += formatUserVarDomoticz(event, 2);
values += formatUserVarDomoticz(event, 3);
break;
case SENSOR_TYPE_WIND:
// WindDir in degrees; WindDir as text; Wind speed average ; Wind speed gust; 0
// http://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Wind
values = formatUserVarDomoticz(event, 0); // WB = Wind bearing (0-359)
values += getBearing(UserVar[event->BaseVarIndex]); // WD = Wind direction (S, SW, NNW, etc.)
values += ";"; // Needed after getBearing
// Domoticz expects the wind speed in (m/s * 10)
values += toString((UserVar[event->BaseVarIndex + 1] * 10),ExtraTaskSettings.TaskDeviceValueDecimals[1]);
values += ";"; // WS = 10 * Wind speed [m/s]
values += toString((UserVar[event->BaseVarIndex + 2] * 10),ExtraTaskSettings.TaskDeviceValueDecimals[2]);
values += ";"; // WG = 10 * Gust [m/s]
values += formatUserVarDomoticz(0); // Temperature
values += formatUserVarDomoticz(0); // Temperature Windchill
break;
case SENSOR_TYPE_SWITCH:
case SENSOR_TYPE_DIMMER:
// Too specific for HTTP/MQTT
break;
default:
{
String log = F("Domoticz Controller: Not yet implemented sensor type: ");
log += event->sensorType;
log += F(" idx: ");
log += event->idx;
addLog(LOG_LEVEL_ERROR, log);
break;
}
}
// Now strip trailing semi colon.
int index_last_char = values.length() -1;
if (index_last_char > 0 && values.charAt(index_last_char) == ';') {
values.setCharAt(index_last_char, ' ');
}
values.trim();
{
String log = F(" Domoticz: Sensortype: ");
log += event->sensorType;
log += F(" idx: ");
log += event->idx;
log += F(" values: ");
log += values;
addLog(LOG_LEVEL_INFO, log);
}
return values;
}
+28
View File
@@ -0,0 +1,28 @@
/*********************************************************************************************\
Get value count from sensor type
\*********************************************************************************************/
byte getValueCountFromSensorType(byte sensorType)
{
switch (sensorType)
{
case SENSOR_TYPE_SINGLE: // single value sensor, used for Dallas, BH1750, etc
case SENSOR_TYPE_SWITCH:
case SENSOR_TYPE_DIMMER:
return 1;
case SENSOR_TYPE_LONG: // single LONG value, stored in two floats (rfid tags)
return 1;
case SENSOR_TYPE_TEMP_HUM:
case SENSOR_TYPE_TEMP_BARO:
case SENSOR_TYPE_DUAL:
return 2;
case SENSOR_TYPE_TEMP_HUM_BARO:
case SENSOR_TYPE_TRIPLE:
case SENSOR_TYPE_WIND:
return 3;
case SENSOR_TYPE_QUAD:
return 4;
}
addLog(LOG_LEVEL_ERROR, F("getValueCountFromSensorType: Unknown sensortype"));
return 0;
}
+49 -1
View File
@@ -10,7 +10,7 @@
Servo servo1;
Servo servo2;
#endif
#define GPIO_MAX 17
// Make sure the initial default is a switch (value 0)
#define PLUGIN_001_TYPE_SWITCH 0
#define PLUGIN_001_TYPE_DIMMER 3 // Due to some changes in previous versions, do not use 2.
@@ -27,6 +27,8 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
boolean success = false;
static boolean switchstate[TASKS_MAX];
static boolean outputstate[TASKS_MAX];
static int8_t PinMonitor[GPIO_MAX];
static int8_t PinMonitorState[GPIO_MAX];
switch (function)
{
@@ -108,6 +110,11 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
case PLUGIN_INIT:
{
for (byte x=0; x < GPIO_MAX; x++){
PinMonitor[x] = 0;
PinMonitorState[x] = 0;
}
if (Settings.TaskDevicePin1PullUp[event->TaskIndex])
pinMode(Settings.TaskDevicePin1[event->TaskIndex], INPUT_PULLUP);
else
@@ -128,6 +135,38 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_REQUEST:
{
String device = parseString(string, 1);
String command = parseString(string, 2);
String strPar1 = parseString(string, 3);
int par1 = strPar1.toInt();
if (device == F("gpio") && command == F("pinstate"))
{
string = digitalRead(par1);
success = true;
}
break;
}
case PLUGIN_UNCONDITIONAL_POLL:
{
// port monitoring, on request by rule command
for (byte x=0; x < GPIO_MAX; x++)
if (PinMonitor[x] != 0){
byte state = digitalRead(x);
if (PinMonitorState[x] != state){
String eventString = F("GPIO#");
eventString += x;
eventString += F("=");
eventString += state;
rulesProcessing(eventString);
PinMonitorState[x] = state;
}
}
break;
}
case PLUGIN_TEN_PER_SECOND:
{
const boolean state = Plugin_001_read_switch_state(event);
@@ -332,6 +371,15 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
}
}
if (command == F("monitor"))
{
if (parseString(string, 2) == F("gpio"))
{
PinMonitor[event->Par2] = 1;
success = true;
}
}
if (command == F("inputswitchstate"))
{
success = true;
+78 -54
View File
@@ -4,12 +4,17 @@
// Maxim Integrated (ex Dallas) DS18B20 datasheet : https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf
#if defined(ESP32)
#define ESP32noInterrupts() {portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;portENTER_CRITICAL(&mux)
#define ESP32interrupts() portEXIT_CRITICAL(&mux);}
#endif
#define PLUGIN_004
#define PLUGIN_ID_004 4
#define PLUGIN_NAME_004 "Environment - DS18b20"
#define PLUGIN_VALUENAME1_004 "Temperature"
uint8_t Plugin_004_DallasPin;
int8_t Plugin_004_DallasPin;
boolean Plugin_004(byte function, struct EventStruct * event, String& string)
{
@@ -49,46 +54,46 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
{
uint8_t savedAddress[8];
byte resolutionChoice = 0;
// Scan the onewire bus and fill dropdown list with devicecount on this GPIO.
Plugin_004_DallasPin = Settings.TaskDevicePin1[event->TaskIndex];
// get currently saved address
for (byte i = 0; i < 8; i++)
savedAddress[i] = ExtraTaskSettings.TaskDevicePluginConfigLong[i];
if (Plugin_004_DallasPin != -1){
// get currently saved address
for (byte i = 0; i < 8; i++)
savedAddress[i] = ExtraTaskSettings.TaskDevicePluginConfigLong[i];
// find all suitable devices
addRowLabel(string, F("Device Address"));
addSelector_Head(string, F("plugin_004_dev"), false);
addSelector_Item(string, "", -1, false, false, F(""));
uint8_t tmpAddress[8];
byte count = 0;
Plugin_004_DS_reset();
Plugin_004_DS_reset_search();
while (Plugin_004_DS_search(tmpAddress))
{
String option = "";
for (byte j = 0; j < 8; j++)
{
option += String(tmpAddress[j], HEX);
if (j < 7) option += F("-");
}
bool selected = (memcmp(tmpAddress, savedAddress, 8) == 0) ? true : false;
addSelector_Item(string, option, count, selected, false, F(""));
count ++;
// find all suitable devices
addRowLabel(string, F("Device Address"));
addSelector_Head(string, F("plugin_004_dev"), false);
addSelector_Item(string, "", -1, false, false, F(""));
uint8_t tmpAddress[8];
byte count = 0;
Plugin_004_DS_reset();
Plugin_004_DS_reset_search();
while (Plugin_004_DS_search(tmpAddress))
{
String option = "";
for (byte j = 0; j < 8; j++)
{
option += String(tmpAddress[j], HEX);
if (j < 7) option += F("-");
}
bool selected = (memcmp(tmpAddress, savedAddress, 8) == 0) ? true : false;
addSelector_Item(string, option, count, selected, false, F(""));
count ++;
}
addSelector_Foot(string);
// Device Resolution select
if (ExtraTaskSettings.TaskDevicePluginConfigLong[0] != 0)
resolutionChoice = Plugin_004_DS_getResolution(savedAddress);
else
resolutionChoice = 9;
String resultsOptions[4] = { "9", "10", "11", "12" };
int resultsOptionValues[4] = { 9, 10, 11, 12 };
addFormSelector(string, F("Device Resolution"), F("plugin_004_res"), 4, resultsOptions, resultsOptionValues, resolutionChoice);
string += F(" Bit");
}
addSelector_Foot(string);
// Device Resolution select
if (ExtraTaskSettings.TaskDevicePluginConfigLong[0] != 0)
resolutionChoice = Plugin_004_DS_getResolution(savedAddress);
else
resolutionChoice = 9;
String resultsOptions[4] = { "9", "10", "11", "12" };
int resultsOptionValues[4] = { 9, 10, 11, 12 };
addFormSelector(string, F("Device Resolution"), F("plugin_004_res"), 4, resultsOptions, resultsOptionValues, resolutionChoice);
string += F(" Bit");
success = true;
break;
}
@@ -100,13 +105,14 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
// save the address for selected device and store into extra tasksettings
Plugin_004_DallasPin = Settings.TaskDevicePin1[event->TaskIndex];
// byte devCount =
Plugin_004_DS_scan(getFormItemInt(F("plugin_004_dev")), addr);
for (byte x = 0; x < 8; x++)
ExtraTaskSettings.TaskDevicePluginConfigLong[x] = addr[x];
Plugin_004_DS_setResolution(addr, getFormItemInt(F("plugin_004_res")));
Plugin_004_DS_startConvertion(addr);
if (Plugin_004_DallasPin != -1){
Plugin_004_DS_scan(getFormItemInt(F("plugin_004_dev")), addr);
for (byte x = 0; x < 8; x++)
ExtraTaskSettings.TaskDevicePluginConfigLong[x] = addr[x];
Plugin_004_DS_setResolution(addr, getFormItemInt(F("plugin_004_res")));
Plugin_004_DS_startConvertion(addr);
}
success = true;
break;
}
@@ -125,10 +131,12 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
case PLUGIN_INIT:
{
Plugin_004_DallasPin = Settings.TaskDevicePin1[event->TaskIndex];
uint8_t addr[8];
Plugin_004_get_addr(addr, event->TaskIndex);
Plugin_004_DS_startConvertion(addr);
delay(800); //give it time to do intial conversion
if (Plugin_004_DallasPin != -1){
uint8_t addr[8];
Plugin_004_get_addr(addr, event->TaskIndex);
Plugin_004_DS_startConvertion(addr);
delay(800); //give it time to do intial conversion
}
success = true;
break;
}
@@ -371,7 +379,9 @@ uint8_t Plugin_004_DS_reset()
{
uint8_t r;
uint8_t retries = 125;
// noInterrupts();
#if defined(ESP32)
ESP32noInterrupts();
#endif
pinMode(Plugin_004_DallasPin, INPUT);
do // wait until the wire is high... just in case
{
@@ -387,7 +397,9 @@ uint8_t Plugin_004_DS_reset()
delayMicroseconds(40);
r = !digitalRead(Plugin_004_DallasPin);
delayMicroseconds(420);
// interrupts();
#if defined(ESP32)
ESP32interrupts();
#endif
return r;
}
@@ -569,14 +581,18 @@ uint8_t Plugin_004_DS_read_bit(void)
{
uint8_t r;
// noInterrupts();
#if defined(ESP32)
ESP32noInterrupts();
#endif
pinMode(Plugin_004_DallasPin, OUTPUT);
digitalWrite(Plugin_004_DallasPin, LOW);
delayMicroseconds(3);
pinMode(Plugin_004_DallasPin, INPUT); // let pin float, pull up will raise
delayMicroseconds(10);
r = digitalRead(Plugin_004_DallasPin);
// interrupts();
#if defined(ESP32)
ESP32interrupts();
#endif
delayMicroseconds(53);
return r;
}
@@ -588,22 +604,30 @@ void Plugin_004_DS_write_bit(uint8_t v)
{
if (v & 1)
{
// noInterrupts();
#if defined(ESP32)
ESP32noInterrupts();
#endif
digitalWrite(Plugin_004_DallasPin, LOW);
pinMode(Plugin_004_DallasPin, OUTPUT);
delayMicroseconds(10);
digitalWrite(Plugin_004_DallasPin, HIGH);
// interrupts();
#if defined(ESP32)
ESP32interrupts();
#endif
delayMicroseconds(55);
}
else
{
// noInterrupts();
#if defined(ESP32)
ESP32noInterrupts();
#endif
digitalWrite(Plugin_004_DallasPin, LOW);
pinMode(Plugin_004_DallasPin, OUTPUT);
delayMicroseconds(65);
digitalWrite(Plugin_004_DallasPin, HIGH);
// interrupts();
#if defined(ESP32)
ESP32interrupts();
#endif
delayMicroseconds(5);
}
}
+12 -1
View File
@@ -7,6 +7,7 @@
// DS Temp:[Dallas1#Temperature#R]
// Lux:[Lux#Lux#R]
// Baro:[Baro#Pressure#R]
// Pump:[Pump#on#O] -> ON/OFF
#include <LiquidCrystal_I2C.h>
@@ -202,7 +203,7 @@ boolean Plugin_012(byte function, struct EventStruct *event, String& string)
String tmpString = deviceTemplate[x];
if (lcd && tmpString.length())
{
String newString = parseTemplate(tmpString, col);
String newString = P012_parseTemplate(tmpString, col);
lcd->setCursor(0, x);
lcd->print(newString);
}
@@ -302,3 +303,13 @@ boolean Plugin_012(byte function, struct EventStruct *event, String& string)
}
return success;
}
// Perform some specific changes for LCD display
// https://www.letscontrolit.com/forum/viewtopic.php?t=2368
String P012_parseTemplate(String &tmpString, byte lineSize) {
String result = parseTemplate(tmpString, lineSize);
const char degree[3] = {0xc2, 0xb0, 0}; // Unicode degree symbol
const char degree_lcd[2] = {0xdf, 0}; // P012_LCD degree symbol
result.replace(degree, degree_lcd);
return result;
}
+34 -21
View File
@@ -112,9 +112,17 @@ boolean Plugin_019(byte function, struct EventStruct *event, String& string)
if (command == F("pcfgpio"))
{
success = true;
Plugin_019_Write(event->Par1, event->Par2);
setPinState(PLUGIN_ID_019, event->Par1, PIN_MODE_OUTPUT, event->Par2);
log = String(F("PCF : GPIO ")) + String(event->Par1) + String(F(" Set to ")) + String(event->Par2);
if (event->Par2 == 2) { //INPUT
// PCF8574 specific: only can read 0/low state, so we must send 1
setPinState(PLUGIN_ID_019, event->Par1, PIN_MODE_INPUT, 1);
Plugin_019_Write(event->Par1,1);
log = String(F("PCF : GPIO ")) + String(event->Par1) + String(F(" Set to 1"));
}
else { // OUTPUT
setPinState(PLUGIN_ID_019, event->Par1, PIN_MODE_OUTPUT, event->Par2);
Plugin_019_Write(event->Par1, event->Par2);
log = String(F("PCF : GPIO ")) + String(event->Par1) + String(F(" Set to ")) + String(event->Par2);
}
addLog(LOG_LEVEL_INFO, log);
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_019, event->Par1, log, 0));
}
@@ -200,28 +208,33 @@ int Plugin_019_Read(byte Par1)
//********************************************************************************
boolean Plugin_019_Write(byte Par1, byte Par2)
{
boolean success = false;
byte portvalue = 0;
byte unit = (Par1 - 1) / 8;
byte port = Par1 - (unit * 8);
uint8_t address = 0x20 + unit;
if (unit > 7) address += 0x10;
// get the current pin status
Wire.requestFrom(address, (uint8_t)0x1);
if (Wire.available())
{
portvalue = Wire.read();
if (Par2 == 1)
portvalue |= (1 << (port - 1));
else
portvalue &= ~(1 << (port - 1));
// write back new data
Wire.beginTransmission(address);
Wire.write(portvalue);
Wire.endTransmission();
success = true;
//generate bitmask
int i = 0;
byte portmask = 0;
byte mode = 0;
uint16_t value = 0;
unit *= 8; // calculate first pin
unit += 1;
for(i =0;i<8;i++){
mode =0;
if(!getPinState(PLUGIN_ID_019, unit, &mode, &value) || mode == PIN_MODE_INPUT || (mode == PIN_MODE_OUTPUT && value == 1))
portmask |= (1 << i);
unit++;
}
return(success);
if (Par2 == 1)
portmask |= (1 << (port - 1));
else
portmask &= ~(1 << (port - 1));
Wire.beginTransmission(address);
Wire.write(portmask);
Wire.endTransmission();
return true;
}
+12 -2
View File
@@ -96,12 +96,22 @@ boolean Plugin_020(byte function, struct EventStruct *event, String& string)
LoadTaskSettings(event->TaskIndex);
if ((ExtraTaskSettings.TaskDevicePluginConfigLong[0] != 0) && (ExtraTaskSettings.TaskDevicePluginConfigLong[1] != 0))
{
byte serialconfig = 0x10;
#if defined(ESP8266)
byte serialconfig = 0x10;
#endif
#if defined(ESP32)
uint32_t serialconfig = 0x8000010;
#endif
serialconfig += ExtraTaskSettings.TaskDevicePluginConfigLong[3];
serialconfig += (ExtraTaskSettings.TaskDevicePluginConfigLong[2] - 5) << 2;
if (ExtraTaskSettings.TaskDevicePluginConfigLong[4] == 2)
serialconfig += 0x20;
Serial.begin(ExtraTaskSettings.TaskDevicePluginConfigLong[1], (SerialConfig)serialconfig);
#if defined(ESP8266)
Serial.begin(ExtraTaskSettings.TaskDevicePluginConfigLong[1], (SerialConfig)serialconfig);
#endif
#if defined(ESP32)
Serial.begin(ExtraTaskSettings.TaskDevicePluginConfigLong[1], serialconfig);
#endif
ser2netServer = new WiFiServer(ExtraTaskSettings.TaskDevicePluginConfigLong[0]);
ser2netServer->begin();
+2 -1
View File
@@ -213,7 +213,8 @@ boolean Plugin_023(byte function, struct EventStruct *event, String& string)
success = true;
argIndex = string.lastIndexOf(',');
tmpString = string.substring(argIndex + 1);
Plugin_023_sendStrXY(tmpString.c_str(), event->Par1 - 1, event->Par2 - 1);
String newString = P023_parseTemplate(tmpString, 16);
Plugin_023_sendStrXY(newString.c_str(), event->Par1 - 1, event->Par2 - 1);
}
if (tmpString.equalsIgnoreCase(F("OLEDCMD")))
{
+9 -3
View File
@@ -225,7 +225,7 @@ boolean Plugin_036(byte function, struct EventStruct *event, String& string)
// Display the device name, logo, time and wifi
display_header();
// display_logo();
display_logo();
display->display();
// Set up the display timer
@@ -503,8 +503,14 @@ void display_title(String& title) {
}
void display_logo() {
// draw an xbm image.
display->drawXbm(34, 14, WiFi_Logo_width, WiFi_Logo_height, WiFi_Logo_bits);
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(ArialMT_Plain_16);
display->setColor(BLACK);
display->fillRect(0, 14, 128, 64);
display->setColor(WHITE);
display->drawString(65, 15, F("ESP"));
display->drawString(65, 34, F("Easy"));
display->drawXbm(24, 14, espeasy_logo_width, espeasy_logo_height, espeasy_logo_bits);
}
// Draw the frame position
+3 -43
View File
@@ -166,13 +166,11 @@ boolean Plugin_037(byte function, struct EventStruct *event, String& string)
// This is a private option only used by the MQTT 037 callback function
// Get the payload and check it out
String Payload = event->String2;
float floatPayload = string2float(Payload);
LoadTaskSettings(event->TaskIndex);
if (floatPayload == -999) {
String Payload = event->String2;
float floatPayload;
if (!string2float(Payload, floatPayload)) {
String log = F("IMPT : Bad Import MQTT Command ");
log += event->String1;
addLog(LOG_LEVEL_ERROR, log);
@@ -450,41 +448,3 @@ boolean MQTTCheckSubscription_037(String Topic, String Subscription) {
}
return false;
}
// ***************************************************************************
// Convert String to float - returns -999 in case of error
float string2float(String myString) {
int i, len;
float value;
len = myString.length();
char tmp[(len + 1)]; // one extra for the zero termination
byte start = 0;
// Look for decimal point - they can be anywhere but no more than one of them!
int dotIndex = myString.indexOf('.');
//Serial.println(dotIndex);
if (dotIndex != -1)
{
int dotIndex2 = (myString.substring(dotIndex + 1)).indexOf('.');
//Serial.println(dotIndex2);
if (dotIndex2 != -1)return -999.00; // Give error if there is more than one dot
}
if (myString.charAt(0) == '-') {
tmp[0] = '-';
start = 1; //allow a minus in front of string
}
for (i = start; i < len; i++)
{
tmp[i] = myString.charAt(i);
if (!isdigit(tmp[i]))
{
if (tmp[i] != '.')return -999;
}
}
tmp[i] = 0;
value = atof(tmp);
return value;
}
+12 -2
View File
@@ -108,12 +108,22 @@ boolean Plugin_044(byte function, struct EventStruct *event, String& string)
LoadTaskSettings(event->TaskIndex);
if ((ExtraTaskSettings.TaskDevicePluginConfigLong[0] != 0) && (ExtraTaskSettings.TaskDevicePluginConfigLong[1] != 0))
{
byte serialconfig = 0x10;
#if defined(ESP8266)
byte serialconfig = 0x10;
#endif
#if defined(ESP32)
uint32_t serialconfig = 0x8000010;
#endif
serialconfig += ExtraTaskSettings.TaskDevicePluginConfigLong[3];
serialconfig += (ExtraTaskSettings.TaskDevicePluginConfigLong[2] - 5) << 2;
if (ExtraTaskSettings.TaskDevicePluginConfigLong[4] == 2)
serialconfig += 0x20;
Serial.begin(ExtraTaskSettings.TaskDevicePluginConfigLong[1], (SerialConfig)serialconfig);
#if defined(ESP8266)
Serial.begin(ExtraTaskSettings.TaskDevicePluginConfigLong[1], (SerialConfig)serialconfig);
#endif
#if defined(ESP32)
Serial.begin(ExtraTaskSettings.TaskDevicePluginConfigLong[1], serialconfig);
#endif
if (P1GatewayServer) P1GatewayServer->close();
P1GatewayServer = new WiFiServer(ExtraTaskSettings.TaskDevicePluginConfigLong[0]);
P1GatewayServer->begin();
+77 -39
View File
@@ -31,17 +31,38 @@ boolean Plugin_049_ABC_MustApply = false;
#include <ESPeasySoftwareSerial.h>
ESPeasySoftwareSerial *Plugin_049_SoftSerial;
// 9-bytes CMD PPM read command
byte mhzCmdReadPPM[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
byte mhzResp[9]; // 9 bytes bytes response
byte mhzCmdCalibrateZero[9] = {0xFF,0x01,0x87,0x00,0x00,0x00,0x00,0x00,0x78};
byte mhzCmdABCEnable[9] = {0xFF,0x01,0x79,0xA0,0x00,0x00,0x00,0x00,0xE6};
byte mhzCmdABCDisable[9] = {0xFF,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x86};
byte mhzCmdReset[9] = {0xFF,0x01,0x8d,0x00,0x00,0x00,0x00,0x00,0x72};
byte mhzCmdMeasurementRange1000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x03,0xE8,0x7B};
byte mhzCmdMeasurementRange2000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x07,0xD0,0x8F};
byte mhzCmdMeasurementRange3000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x0B,0xB8,0xA3};
byte mhzCmdMeasurementRange5000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x13,0x88,0xCB};
enum mhzCommands : byte { mhzCmdReadPPM,
mhzCmdCalibrateZero,
mhzCmdABCEnable,
mhzCmdABCDisable,
mhzCmdReset,
mhzCmdMeasurementRange1000,
mhzCmdMeasurementRange2000,
mhzCmdMeasurementRange3000,
mhzCmdMeasurementRange5000 };
// 9 byte commands:
// mhzCmdReadPPM[] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
// mhzCmdCalibrateZero[] = {0xFF,0x01,0x87,0x00,0x00,0x00,0x00,0x00,0x78};
// mhzCmdABCEnable[] = {0xFF,0x01,0x79,0xA0,0x00,0x00,0x00,0x00,0xE6};
// mhzCmdABCDisable[] = {0xFF,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x86};
// mhzCmdReset[] = {0xFF,0x01,0x8d,0x00,0x00,0x00,0x00,0x00,0x72};
// mhzCmdMeasurementRange1000[] = {0xFF,0x01,0x99,0x03,0xE8,0x00,0x00,0x00,0x7B};
// mhzCmdMeasurementRange2000[] = {0xFF,0x01,0x99,0x07,0xD0,0x00,0x00,0x00,0x8F};
// mhzCmdMeasurementRange3000[] = {0xFF,0x01,0x99,0x0B,0xB8,0x00,0x00,0x00,0xA3};
// mhzCmdMeasurementRange5000[] = {0xFF,0x01,0x99,0x13,0x88,0x00,0x00,0x00,0xCB};
// Removing redundant data, just keeping offsets [2]..[4]:
const PROGMEM byte mhzCmdData[][3] = {
{0x86,0x00,0x00},
{0x87,0x00,0x00},
{0x79,0xA0,0x00},
{0x79,0x00,0x00},
{0x8d,0x00,0x00},
{0x99,0x03,0xE8},
{0x99,0x07,0xD0},
{0x99,0x0B,0xB8},
{0x99,0x13,0x88}};
byte mhzResp[9]; // 9 byte response buffer
enum
{
@@ -179,7 +200,7 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
// No guarantee the correct state is active on the sensor after reboot.
Plugin_049_ABC_MustApply = true;
}
Plugin_049_SoftSerial = new ESPeasySoftwareSerial(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], false, 18);
Plugin_049_SoftSerial = new ESPeasySoftwareSerial(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex]);
Plugin_049_SoftSerial->begin(9600);
addLog(LOG_LEVEL_INFO, F("MHZ19: Init OK "));
@@ -198,56 +219,56 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
if (command == F("mhzcalibratezero"))
{
Plugin_049_SoftSerial->write(mhzCmdCalibrateZero, 9);
_P049_send_mhzCmd(mhzCmdCalibrateZero);
addLog(LOG_LEVEL_INFO, F("MHZ19: Calibrated zero point!"));
success = true;
}
if (command == F("mhzreset"))
{
Plugin_049_SoftSerial->write(mhzCmdReset, 9);
_P049_send_mhzCmd(mhzCmdReset);
addLog(LOG_LEVEL_INFO, F("MHZ19: Sent sensor reset!"));
success = true;
}
if (command == F("mhzabcenable"))
{
Plugin_049_SoftSerial->write(mhzCmdABCEnable, 9);
_P049_send_mhzCmd(mhzCmdABCEnable);
addLog(LOG_LEVEL_INFO, F("MHZ19: Sent sensor ABC Enable!"));
success = true;
}
if (command == F("mhzabcdisable"))
{
Plugin_049_SoftSerial->write(mhzCmdABCDisable, 9);
_P049_send_mhzCmd(mhzCmdABCDisable);
addLog(LOG_LEVEL_INFO, F("MHZ19: Sent sensor ABC Disable!"));
success = true;
}
if (command == F("mhzmeasurementrange1000"))
{
Plugin_049_SoftSerial->write(mhzCmdMeasurementRange1000, 9);
_P049_send_mhzCmd(mhzCmdMeasurementRange1000);
addLog(LOG_LEVEL_INFO, F("MHZ19: Sent measurement range 0-1000PPM!"));
success = true;
}
if (command == F("mhzmeasurementrange2000"))
{
Plugin_049_SoftSerial->write(mhzCmdMeasurementRange2000, 9);
_P049_send_mhzCmd(mhzCmdMeasurementRange2000);
addLog(LOG_LEVEL_INFO, F("MHZ19: Sent measurement range 0-2000PPM!"));
success = true;
}
if (command == F("mhzmeasurementrange3000"))
{
Plugin_049_SoftSerial->write(mhzCmdMeasurementRange3000, 9);
_P049_send_mhzCmd(mhzCmdMeasurementRange3000);
addLog(LOG_LEVEL_INFO, F("MHZ19: Sent measurement range 0-3000PPM!"));
success = true;
}
if (command == F("mhzmeasurementrange5000"))
{
Plugin_049_SoftSerial->write(mhzCmdMeasurementRange5000, 9);
_P049_send_mhzCmd(mhzCmdMeasurementRange5000);
addLog(LOG_LEVEL_INFO, F("MHZ19: Sent measurement range 0-5000PPM!"));
success = true;
}
@@ -261,7 +282,7 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
if (Plugin_049_init)
{
//send read PPM command
int nbBytesSent = Plugin_049_SoftSerial->write(mhzCmdReadPPM, 9);
byte nbBytesSent = _P049_send_mhzCmd(mhzCmdReadPPM);
if (nbBytesSent != 9) {
String log = F("MHZ19: Error, nb bytes sent != 9 : ");
log += nbBytesSent;
@@ -285,19 +306,15 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
}
unsigned int ppm = 0;
int i;
signed int temp = 0;
unsigned int s = 0;
float u = 0;
byte crc = 0;
for (i = 1; i < 8; i++) crc+=mhzResp[i];
crc = 255 - crc;
crc++;
byte checksum = _P049_calculateChecksum(mhzResp);
if ( !(mhzResp[8] == crc) ) {
String log = F("MHZ19: Read error : CRC = ");
log += String(crc); log += " / "; log += String(mhzResp[8]);
log += " bytes read => ";for (i = 0; i < 9; i++) {log += mhzResp[i];log += "/" ;}
if ( !(mhzResp[8] == checksum) ) {
String log = F("MHZ19: Read error: checksum = ");
log += String(checksum); log += " / "; log += String(mhzResp[8]);
log += " bytes read => ";for (byte i = 0; i < 9; i++) {log += mhzResp[i];log += "/" ;}
addLog(LOG_LEVEL_ERROR, log);
// Sometimes there is a misalignment in the serial read
@@ -305,24 +322,24 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
// This goes on forever.
// There must be a better way to handle this, but here
// we're trying to shift it so that 0xFF is the next byte
byte crcshift;
for (i = 1; i < 8; i++) {
crcshift = Plugin_049_SoftSerial->peek();
if (crcshift == 0xFF) {
byte checksum_shift;
for (byte i = 1; i < 8; i++) {
checksum_shift = Plugin_049_SoftSerial->peek();
if (checksum_shift == 0xFF) {
String log = F("MHZ19: Shifted ");
log += i;
log += F(" bytes to attempt to fix buffer alignment");
addLog(LOG_LEVEL_ERROR, log);
break;
} else {
crcshift = Plugin_049_SoftSerial->read();
checksum_shift = Plugin_049_SoftSerial->read();
}
}
success = false;
break;
// Process responses to 0x86
} else if (mhzResp[0] == 0xFF && mhzResp[1] == 0x86 && mhzResp[8] == crc) {
} else if (mhzResp[0] == 0xFF && mhzResp[1] == 0x86 && mhzResp[8] == checksum) {
//calculate CO2 PPM
unsigned int mhzRespHigh = (unsigned int) mhzResp[2];
@@ -368,10 +385,10 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
if (Plugin_049_ABC_MustApply) {
// Send ABC enable/disable command based on the desired state.
if (Plugin_049_ABC_Disable) {
Plugin_049_SoftSerial->write(mhzCmdABCDisable, 9);
_P049_send_mhzCmd(mhzCmdABCDisable);
addLog(LOG_LEVEL_INFO, F("MHZ19: Sent sensor ABC Disable!"));
} else {
Plugin_049_SoftSerial->write(mhzCmdABCEnable, 9);
_P049_send_mhzCmd(mhzCmdABCEnable);
addLog(LOG_LEVEL_INFO, F("MHZ19: Sent sensor ABC Enable!"));
}
Plugin_049_ABC_MustApply = false;
@@ -396,7 +413,7 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
break;
// Sensor responds with 0x99 whenever we send it a measurement range adjustment
} else if (mhzResp[0] == 0xFF && mhzResp[1] == 0x99 && mhzResp[8] == crc) {
} else if (mhzResp[0] == 0xFF && mhzResp[1] == 0x99 && mhzResp[8] == checksum) {
addLog(LOG_LEVEL_INFO, F("MHZ19: Received measurement range acknowledgment! "));
addLog(LOG_LEVEL_INFO, F("Expecting sensor reset..."));
@@ -423,3 +440,24 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
}
return success;
}
byte _P049_calculateChecksum(byte *array)
{
byte checksum = 0;
for (byte i = 1; i < 8; i++)
checksum+=array[i];
checksum = 0xFF - checksum;
return (checksum+1);
}
size_t _P049_send_mhzCmd(byte CommandId)
{
// The receive buffer "mhzResp" is re-used to send a command here:
mhzResp[0] = 0xFF; // Start byte, fixed
mhzResp[1] = 0x01; // Sensor number, 0x01 by default
memcpy_P(&mhzResp[2], mhzCmdData[CommandId], sizeof(mhzCmdData[0]));
mhzResp[5] = mhzResp[6] = mhzResp[7] = 0x00;
mhzResp[8] = _P049_calculateChecksum(mhzResp);
return Plugin_049_SoftSerial->write(mhzResp, sizeof(mhzResp));
}
+106 -81
View File
@@ -66,42 +66,108 @@ void SerialRead16(uint16_t* value, uint16_t* checksum)
#endif
}
void SerialFlush() {
if (swSerial != NULL) {
swSerial->flush();
} else {
Serial.flush();
}
}
boolean PacketAvailable(void)
{
boolean success = false;
if (swSerial != NULL) // Software serial
{
// When there is enough data in the buffer, search through the buffer to
// find header (buffer may be out of sync)
while (swSerial->available() >= PMSx003_SIZE)
{
if (swSerial->read() == PMSx003_SIG1 && swSerial->read() == PMSx003_SIG2)
{
success = true;
break;
}
if (!swSerial->available()) return false;
while ((swSerial->peek() != PMSx003_SIG1) && swSerial->available()) {
swSerial->read(); // Read until the buffer starts with the first byte of a message, or buffer empty.
}
if (swSerial->available() < PMSx003_SIZE) return false; // Not enough yet for a complete packet
}
else // Hardware serial
{
// When there is enough data in the buffer, search through the buffer to
// find header (buffer may be out of sync)
while (Serial.available() >= PMSx003_SIZE)
{
if (Serial.read() == PMSx003_SIG1 && Serial.read() == PMSx003_SIG2)
{
success = true;
break;
}
if (!Serial.available()) return false;
while ((Serial.peek() != PMSx003_SIG1) && Serial.available()) {
Serial.read(); // Read until the buffer starts with the first byte of a message, or buffer empty.
}
if (Serial.available() < PMSx003_SIZE) return false; // Not enough yet for a complete packet
}
return success;
return true;
}
boolean Plugin_053_process_data(struct EventStruct *event) {
String log;
uint16_t checksum = 0, checksum2 = 0;
uint16_t framelength = 0;
uint16 packet_header = 0;
SerialRead16(&packet_header, &checksum); // read PMSx003_SIG1 + PMSx003_SIG2
if (packet_header != ((PMSx003_SIG1 << 8) | PMSx003_SIG2)) {
// Not the start of the packet, stop reading.
return false;
}
SerialRead16(&framelength, &checksum);
if (framelength != (PMSx003_SIZE - 4))
{
log = F("PMSx003 : invalid framelength - ");
log += framelength;
addLog(LOG_LEVEL_ERROR, log);
return false;
}
uint16_t data[13]; // byte data_low, data_high;
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);
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);
SerialFlush(); // Make sure no data is lost due to full buffer.
if (checksum == checksum2)
{
// Data is checked and good, fill in output
UserVar[event->BaseVarIndex] = data[3];
UserVar[event->BaseVarIndex + 1] = data[4];
UserVar[event->BaseVarIndex + 2] = data[5];
values_received = true;
return true;
}
return false;
}
boolean Plugin_053(byte function, struct EventStruct *event, String& string)
{
String log;
boolean success = false;
switch (function)
@@ -153,12 +219,18 @@ boolean Plugin_053(byte function, struct EventStruct *event, String& string)
int txPin = Settings.TaskDevicePin2[event->TaskIndex];
int resetPin = Settings.TaskDevicePin3[event->TaskIndex];
log = F("PMSx003 : config ");
String log = F("PMSx003 : config ");
log += rxPin;
log += txPin;
log += resetPin;
addLog(LOG_LEVEL_DEBUG, log);
if (swSerial != NULL) {
// Regardless the set pins, the software serial must be deleted.
delete swSerial;
swSerial = NULL;
}
// Hardware serial is RX on 3 and TX on 1
if (rxPin == 3 && txPin == 1)
{
@@ -171,7 +243,7 @@ boolean Plugin_053(byte function, struct EventStruct *event, String& string)
{
log = F("PMSx003: using software serial");
addLog(LOG_LEVEL_INFO, log);
swSerial = new ESPeasySoftwareSerial(rxPin, txPin);
swSerial = new ESPeasySoftwareSerial(rxPin, txPin, false, 96); // 96 Bytes buffer, enough for up to 3 packets.
swSerial->begin(9600);
swSerial->flush();
}
@@ -192,6 +264,17 @@ boolean Plugin_053(byte function, struct EventStruct *event, String& string)
success = true;
break;
}
case PLUGIN_EXIT:
{
if (swSerial)
{
delete swSerial;
swSerial=NULL;
}
break;
}
// The update rate from the module is 200ms .. multiple seconds. Practise
// shows that we need to read the buffer many times per seconds to stay in
// sync.
@@ -199,69 +282,11 @@ boolean Plugin_053(byte function, struct EventStruct *event, String& string)
{
if (Plugin_053_init)
{
uint16_t checksum = 0, checksum2 = 0;
uint16_t framelength = 0;
uint16_t data[13];
// byte data_low, data_high;
int i = 0;
// Check if a packet is available in the UART FIFO.
// Check if a complete packet is available in the UART FIFO.
if (PacketAvailable())
{
log = F("PMSx003 : Packet available");
addLog(LOG_LEVEL_DEBUG_MORE, log);
checksum += PMSx003_SIG1 + PMSx003_SIG2;
SerialRead16(&framelength, &checksum);
if (framelength != (PMSx003_SIZE - 4))
{
log = F("PMSx003 : invalid framelength - ");
log += framelength;
addLog(LOG_LEVEL_ERROR, log);
break;
}
for (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);
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);
if (checksum == checksum2)
{
// Data is checked and good, fill in output
UserVar[event->BaseVarIndex] = data[3];
UserVar[event->BaseVarIndex + 1] = data[4];
UserVar[event->BaseVarIndex + 2] = data[5];
values_received = true;
success = true;
}
addLog(LOG_LEVEL_DEBUG_MORE, F("PMSx003 : Packet available"));
success = Plugin_053_process_data(event);
}
}
break;
+1 -1
View File
@@ -34,7 +34,7 @@
// Transceiver:
// SN75176 or MAX485 or LT1785 or ...
// Pin 5: GND
// Pin 2, 3, 5: +5V
// Pin 2, 3, 8: +5V
// Pin 4: to ESP D4
// Pin 6: DMX+ (hot)
// Pin 7: DMX- (cold)
+20
View File
@@ -166,6 +166,26 @@ boolean Plugin_059(byte function, struct EventStruct *event, String& string)
break;
}
case PLUGIN_WRITE:
{
if (Plugin_059_QE)
{
String log = "";
String command = parseString(string, 1);
if (command == F("encwrite"))
{
if (event->Par1 >= 0)
{
log = String(F("QEI : ")) + string;
addLog(LOG_LEVEL_INFO, log);
Plugin_059_QE->write(event->Par1);
success = true;
}
}
}
break;
}
}
return success;
}
+2 -2
View File
@@ -81,11 +81,11 @@ boolean Plugin_060(byte function, struct EventStruct *event, String& string)
addFormCheckBox(string, F("Calibration Enabled"), F("plugin_060_cal"), CONFIG(3));
addFormNumericBox(string, F("Point 1"), F("plugin_060_adc1"), Settings.TaskDevicePluginConfigLong[event->TaskIndex][0], 0, 1023);
addFormNumericBox(string, F("Point 1"), F("plugin_060_adc1"), Settings.TaskDevicePluginConfigLong[event->TaskIndex][0], 0, 4095);
string += F(" &#8793; ");
addTextBox(string, F("plugin_060_out1"), String(Settings.TaskDevicePluginConfigFloat[event->TaskIndex][0], 3), 10);
addFormNumericBox(string, F("Point 2"), F("plugin_060_adc2"), Settings.TaskDevicePluginConfigLong[event->TaskIndex][1], 0, 1023);
addFormNumericBox(string, F("Point 2"), F("plugin_060_adc2"), Settings.TaskDevicePluginConfigLong[event->TaskIndex][1], 0, 4095);
string += F(" &#8793; ");
addTextBox(string, F("plugin_060_out2"), String(Settings.TaskDevicePluginConfigFloat[event->TaskIndex][1], 3), 10);
+8 -8
View File
@@ -87,7 +87,7 @@ void SHT3X::get()
#define CONFIG(n) (Settings.TaskDevicePluginConfig[event->TaskIndex][n])
#endif
SHT3X* Plugin_068_SHT3x = NULL;
SHT3X* Plugin_068_SHT3x[TASKS_MAX] = { NULL, };
//==============================================
@@ -148,9 +148,9 @@ boolean Plugin_068(byte function, struct EventStruct *event, String& string)
case PLUGIN_INIT:
{
if (Plugin_068_SHT3x)
delete Plugin_068_SHT3x;
Plugin_068_SHT3x = new SHT3X(CONFIG(0));
if (Plugin_068_SHT3x[event->TaskIndex])
delete Plugin_068_SHT3x[event->TaskIndex];
Plugin_068_SHT3x[event->TaskIndex] = new SHT3X(CONFIG(0));
success = true;
break;
@@ -158,12 +158,12 @@ boolean Plugin_068(byte function, struct EventStruct *event, String& string)
case PLUGIN_READ:
{
if (!Plugin_068_SHT3x)
if (!Plugin_068_SHT3x[event->TaskIndex])
return success;
Plugin_068_SHT3x->get();
UserVar[event->BaseVarIndex + 0] = Plugin_068_SHT3x->tmp;
UserVar[event->BaseVarIndex + 1] = Plugin_068_SHT3x->hum;
Plugin_068_SHT3x[event->TaskIndex]->get();
UserVar[event->BaseVarIndex + 0] = Plugin_068_SHT3x[event->TaskIndex]->tmp;
UserVar[event->BaseVarIndex + 1] = Plugin_068_SHT3x[event->TaskIndex]->hum;
String log = F("SHT3x: Temperature: ");
log += UserVar[event->BaseVarIndex + 0];
addLog(LOG_LEVEL_INFO, log);
+4 -1
View File
@@ -90,9 +90,12 @@ boolean Plugin_072(byte function, struct EventStruct *event, String& string)
log = F("HDC1080: Humidity: ");
log += UserVar[event->BaseVarIndex + 1];
addLog(LOG_LEVEL_INFO, log);
success = true;
break;
}
}
return success;
}
#endif
#endif
+225 -65
View File
@@ -2,21 +2,24 @@
//################### Plugin 073 - 7-segment display plugin TM1637/MAX7219 ######################
//#######################################################################################################
//
// Chip supported:
// - TM1637 -- 2 pins - 4 digits and colon in the middle (XX:XX)
// - MAX7219/21 -- 3 pins - 8 digits and dot on each digit
// Chips/displays supported:
// 0 - TM1637 -- 2 pins - 4 digits and colon in the middle (XX:XX)
// 1 - TM1637 -- 2 pins - 4 digits and dot on each digit (X.X.X.X.)
// 2 - TM1637 -- 2 pins - 6 digits and dot on each digit (X.X.X.X.X.X.)
// 3 - MAX7219/21 -- 3 pins - 8 digits and dot on each digit (X.X.X.X.)
//
// Plugin can be setup as:
// - Manual -- display is manually updated sending commands
// "7dn,<number>" (number can be negative or positive)
// "7dn,<number>" (number can be negative or positive, even with decimal)
// "7dt,<temperature>" (temperature can be negative or positive and containing decimals)
// - Clock-Blink -- display is automatically updated with current time and blinking dot/lines
// - Clock-NoBlink -- display is automatically updated with current time and steady dot/lines
// - Date -- display is automatically updated with current date
//
// Generic commands:
// - "7don" -- turn ON the display
// - "7doff" -- turn OFF the display
// - "7db,<0-15> -- set brightness to specifi value between 0 and 15
// - "7db,<0-15> -- set brightness to specific value between 0 and 15
//
#ifdef PLUGIN_BUILD_TESTING
@@ -24,7 +27,7 @@
#define PLUGIN_073
#define PLUGIN_ID_073 73
#define PLUGIN_NAME_073 "Display - 7-segment display [TESTING]"
#define PLUGIN_073_DEBUG true //activate extra log info in the debug
#define PLUGIN_073_DEBUG false //activate extra log info in the debug
//---------------------------------------------------
// Class used by plugin
@@ -38,15 +41,19 @@ class p073_7dgt
byte brightness;
boolean timesep;
};
p073_7dgt *Plugin_073_7dgt;
p073_7dgt *Plugin_073_7dgt = NULL;
//---------------------------------------------------
uint8_t p073_showbuffer[8];
byte p073_spidata[2];
byte p073_dotpos;
bool p073_shift;
#define TM1637_POWER_ON 0b10001000
#define TM1637_POWER_OFF 0b10000000
#define TM1637_POWER_ON B10001000
#define TM1637_POWER_OFF B10000000
#define TM1637_CLOCKDELAY 40
#define TM1637_4DIGIT 4
#define TM1637_6DIGIT 2
// each char table is specific for each display and maps all numbers/symbols needed:
// - pos 0-9 - Numbers from 0 to 9
@@ -89,8 +96,8 @@ boolean Plugin_073(byte function, struct EventStruct *event, String& string)
{
addFormNote(string, F("TM1637: 1st=CLK-Pin, 2nd=DIO-Pin"));
addFormNote(string, F("MAX7219: 1st=DIN-Pin, 2nd=CLK-Pin, 3rd=CS-Pin"));
String displtype[3] = { F("TM1637 - 4 digit"), F("MAX7219 - 8 digit")};
addFormSelector(string, F("Display Type"), F("plugin_073_displtype"), 2, displtype, NULL, Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
String displtype[5] = { F("TM1637 - 4 digit (colon)"), F("TM1637 - 4 digit (dots)"), F("TM1637 - 6 digit"), F("MAX7219 - 8 digit")};
addFormSelector(string, F("Display Type"), F("plugin_073_displtype"), 4, displtype, NULL, Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
String displout[4] = { F("Manual"), F("Clock - Blink"), F("Clock - No Blink"), F("Date") };
addFormSelector(string, F("Display Output"), F("plugin_073_displout"), 4, displout, NULL, Settings.TaskDevicePluginConfig[event->TaskIndex][1]);
addFormNumericBox(string, F("Brightness"), F("plugin_073_brightness"), Settings.TaskDevicePluginConfig[event->TaskIndex][2], 0, 15);
@@ -114,6 +121,8 @@ boolean Plugin_073(byte function, struct EventStruct *event, String& string)
switch (Settings.TaskDevicePluginConfig[event->TaskIndex][0])
{
case 0: // set brightness of TM1637
case 1:
case 2:
{
int tm1637_bright = Settings.TaskDevicePluginConfig[event->TaskIndex][2] / 2;
tm1637_SetPowerBrightness(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], tm1637_bright, true);
@@ -121,7 +130,7 @@ boolean Plugin_073(byte function, struct EventStruct *event, String& string)
tm1637_ClearDisplay(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex]);
break;
}
case 1: // set brightness of MAX7219
case 3: // set brightness of MAX7219
{
max7219_SetPowerBrightness(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], Settings.TaskDevicePin3[event->TaskIndex], Settings.TaskDevicePluginConfig[event->TaskIndex][2], true);
if (Settings.TaskDevicePluginConfig[event->TaskIndex][1] == 0)
@@ -147,13 +156,15 @@ boolean Plugin_073(byte function, struct EventStruct *event, String& string)
switch (Settings.TaskDevicePluginConfig[event->TaskIndex][0])
{
case 0:
case 1:
case 2:
{
tm1637_InitDisplay(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex]);
int tm1637_bright = Settings.TaskDevicePluginConfig[event->TaskIndex][2] / 2;
tm1637_SetPowerBrightness(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], tm1637_bright, true);
break;
}
case 1:
case 3:
{
max7219_InitDisplay(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], Settings.TaskDevicePin3[event->TaskIndex]);
max7219_SetPowerBrightness(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], Settings.TaskDevicePin3[event->TaskIndex], Settings.TaskDevicePluginConfig[event->TaskIndex][2], true);
@@ -181,18 +192,38 @@ boolean Plugin_073(byte function, struct EventStruct *event, String& string)
if (tmpString.equalsIgnoreCase(F("7dn"))) {
if (Plugin_073_7dgt->output != 0)
break;
String log = F("7DGT : Show Number=");
log += event->Par1;
addLog(LOG_LEVEL_INFO, log);
switch (Plugin_073_7dgt->type)
{
case 0:
{
if (event->Par1 > -1000 && event->Par1 < 10000)
p073_FillBufferWithNumber(String(int(event->Par1)));
else
p073_FillBufferWithDash();
tm1637_ShowBuffer(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2);
tm1637_ShowBuffer(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, TM1637_4DIGIT);
break;
case 1:
{
if (event->Par1 > -1000 && event->Par1 < 10000)
p073_FillBufferWithNumber(tmpStr.substring(comma1+1).c_str());
else
p073_FillBufferWithDash();
tm1637_ShowBuffer(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, TM1637_4DIGIT);
break;
}
case 1:
case 2:
{
if (event->Par1 > -100000 && event->Par1 < 1000000)
p073_FillBufferWithNumber(tmpStr.substring(comma1+1).c_str());
else
p073_FillBufferWithDash();
tm1637_SwapDigitInBuffer(); // only needed for 6-digits displays
tm1637_ShowBuffer(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, TM1637_6DIGIT);
break;
}
case 3:
{
if (comma1 > 0) {
if (event->Par1 > -10000000 && event->Par1 < 100000000) {
@@ -205,6 +236,7 @@ boolean Plugin_073(byte function, struct EventStruct *event, String& string)
break;
}
}
success = true;
} else if (tmpString.equalsIgnoreCase(F("7dt"))) {
if (Plugin_073_7dgt->output != 0)
break;
@@ -212,9 +244,13 @@ boolean Plugin_073(byte function, struct EventStruct *event, String& string)
bool p073_tempflagdot = false;
if (comma1 > 0)
p073_temptemp = atof(tmpStr.substring(comma1+1).c_str());
String log = F("7DGT : Show Temperature=");
log += p073_temptemp;
addLog(LOG_LEVEL_INFO, log);
switch (Plugin_073_7dgt->type)
{
case 0:
case 1:
{
if (p073_temptemp > 999 || p073_temptemp < -99.9)
p073_FillBufferWithDash();
@@ -227,10 +263,26 @@ boolean Plugin_073(byte function, struct EventStruct *event, String& string)
if (p073_temptemp == 0 && p073_tempflagdot)
p073_showbuffer[5] = 0;
}
tm1637_ShowTimeTemp(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, p073_tempflagdot, 4);
tm1637_ShowTimeTemp4(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, p073_tempflagdot, 4);
break;
}
case 1:
case 2:
{
if (p073_temptemp > 999 || p073_temptemp < -99.9)
p073_FillBufferWithDash();
else {
if (p073_temptemp < 100 && p073_temptemp > -10) {
p073_temptemp = int(p073_temptemp*10);
p073_tempflagdot = true;
}
p073_FillBufferWithTemp(p073_temptemp);
if (p073_temptemp == 0 && p073_tempflagdot)
p073_showbuffer[5] = 0;
}
tm1637_ShowTemp6(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, p073_tempflagdot);
break;
}
case 3:
{
p073_temptemp = int(p073_temptemp*10);
p073_FillBufferWithTemp(p073_temptemp);
@@ -240,38 +292,48 @@ boolean Plugin_073(byte function, struct EventStruct *event, String& string)
break;
}
}
success = true;
} else {
bool p073_validcmd = false;
bool p073_displayon;
if (tmpString.equalsIgnoreCase(F("7don"))) {
String log = F("7DGT : Display ON");
addLog(LOG_LEVEL_INFO, log);
p073_displayon = true;
p073_validcmd = true;
}
else if (tmpString.equalsIgnoreCase(F("7doff"))) {
String log = F("7DGT : Display OFF");
addLog(LOG_LEVEL_INFO, log);
p073_displayon = false;
p073_validcmd = true;
}
else if (tmpString.equalsIgnoreCase(F("7db"))) {
if (event->Par1 >= 0 && event->Par1 < 16) {
String log = F("7DGT : Brightness=");
log += event->Par1;
addLog(LOG_LEVEL_INFO, log);
Plugin_073_7dgt->brightness = event->Par1;
p073_displayon = true;
p073_validcmd = true;
}
}
if (p073_validcmd) {
success = true;
switch (Plugin_073_7dgt->type)
{
case 0:
case 1:
case 2:
{ int tm1637_bright = Plugin_073_7dgt->brightness / 2;
tm1637_SetPowerBrightness(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, tm1637_bright, p073_displayon);
break; }
case 1:
case 3:
{ max7219_SetPowerBrightness(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, Plugin_073_7dgt->pin3, Plugin_073_7dgt->brightness, p073_displayon);
break; }
}
}
}
success = true;
break;
}
@@ -293,11 +355,20 @@ boolean Plugin_073(byte function, struct EventStruct *event, String& string)
switch (Plugin_073_7dgt->type)
{
case 0:
case 1:
{
tm1637_ShowTimeTemp(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, Plugin_073_7dgt->timesep, 0);
tm1637_ShowTimeTemp4(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, Plugin_073_7dgt->timesep, 0);
break;
}
case 1:
case 2:
{
if (Settings.TaskDevicePluginConfig[event->TaskIndex][1] == 3)
tm1637_ShowDate6(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, Plugin_073_7dgt->timesep);
else
tm1637_ShowTime6(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, Plugin_073_7dgt->timesep);
break;
}
case 3:
{
if (Settings.TaskDevicePluginConfig[event->TaskIndex][1] == 3)
max7219_ShowDate(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, Plugin_073_7dgt->pin3);
@@ -411,62 +482,88 @@ void p073_FillBufferWithDash() // in case of error show all dashes
void tm1637_i2cStart (uint8_t clk_pin, uint8_t dio_pin)
{
CLK_HIGH();
if (PLUGIN_073_DEBUG) {
String log = F("7DGT : Comm Start");
addLog(LOG_LEVEL_INFO, log);
}
DIO_HIGH();
delayMicroseconds(2);
CLK_HIGH();
delayMicroseconds(TM1637_CLOCKDELAY);
DIO_LOW();
}
void tm1637_i2cStop (uint8_t clk_pin, uint8_t dio_pin)
{
if (PLUGIN_073_DEBUG) {
String log = F("7DGT : Comm Stop");
addLog(LOG_LEVEL_INFO, log);
}
CLK_LOW();
delayMicroseconds(2);
delayMicroseconds(TM1637_CLOCKDELAY);
DIO_LOW();
delayMicroseconds(2);
delayMicroseconds(TM1637_CLOCKDELAY);
CLK_HIGH();
delayMicroseconds(2);
delayMicroseconds(TM1637_CLOCKDELAY);
DIO_HIGH();
}
void tm1637_i2cAck (uint8_t clk_pin, uint8_t dio_pin)
{
bool dummyAck = false;
CLK_LOW();
DIO_HIGH();
delayMicroseconds(5);
while(digitalRead(dio_pin));
pinMode(dio_pin, INPUT_PULLUP);
//DIO_HIGH();
delayMicroseconds(TM1637_CLOCKDELAY);
//while(digitalRead(dio_pin));
dummyAck = digitalRead(dio_pin);
if (PLUGIN_073_DEBUG) {
String log = F("7DGT : Comm ACK=");
if (dummyAck == 0) { log += F("TRUE"); } else { log += F("FALSE"); }
addLog(LOG_LEVEL_INFO, log);
}
CLK_HIGH();
delayMicroseconds(2);
delayMicroseconds(TM1637_CLOCKDELAY);
CLK_LOW();
pinMode(dio_pin, OUTPUT);
}
void tm1637_i2cWrite (uint8_t clk_pin, uint8_t dio_pin, uint8_t bytetoprint)
{
if (PLUGIN_073_DEBUG) {
String log = F("7DGT : WriteByte");
addLog(LOG_LEVEL_INFO, log);
}
uint8_t i;
for(i=0; i<8; i++)
{
CLK_LOW();
(bytetoprint & B00000001)? DIO_HIGH() : DIO_LOW();
delayMicroseconds(3);
delayMicroseconds(TM1637_CLOCKDELAY);
bytetoprint = bytetoprint >> 1;
CLK_HIGH();
delayMicroseconds(3);
delayMicroseconds(TM1637_CLOCKDELAY);
}
}
void tm1637_ClearDisplay (uint8_t clk_pin, uint8_t dio_pin)
{
tm1637_i2cStart(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0xC0);
tm1637_i2cAck(clk_pin, dio_pin); tm1637_i2cWrite(clk_pin, dio_pin, 0);
tm1637_i2cAck(clk_pin, dio_pin); tm1637_i2cWrite(clk_pin, dio_pin, 0);
tm1637_i2cAck(clk_pin, dio_pin); tm1637_i2cWrite(clk_pin, dio_pin, 0);
tm1637_i2cAck(clk_pin, dio_pin); tm1637_i2cWrite(clk_pin, dio_pin, 0);
tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0xC0); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cStop(clk_pin, dio_pin);
}
void tm1637_SetPowerBrightness (uint8_t clk_pin, uint8_t dio_pin, uint8_t brightlvl, bool poweron)
{
if (PLUGIN_073_DEBUG) {
String log = F("7DGT : Set BRIGHT");
addLog(LOG_LEVEL_INFO, log);
}
uint8_t brightvalue = (brightlvl & 0b111);
if (poweron)
brightvalue = TM1637_POWER_ON | brightvalue;
@@ -480,10 +577,12 @@ void tm1637_SetPowerBrightness (uint8_t clk_pin, uint8_t dio_pin, uint8_t bright
void tm1637_InitDisplay(uint8_t clk_pin, uint8_t dio_pin)
{
pinMode(dio_pin, OUTPUT);
digitalWrite(dio_pin, LOW);
pinMode(dio_pin, INPUT_PULLUP);
pinMode(clk_pin, OUTPUT);
pinMode(dio_pin, OUTPUT);
CLK_HIGH();
DIO_HIGH();
// pinMode(dio_pin, INPUT_PULLUP);
// pinMode(clk_pin, OUTPUT);
tm1637_i2cStart(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0x40);
tm1637_i2cAck(clk_pin, dio_pin);
@@ -491,38 +590,99 @@ void tm1637_InitDisplay(uint8_t clk_pin, uint8_t dio_pin)
tm1637_ClearDisplay(clk_pin, dio_pin);
}
void tm1637_ShowTimeTemp(uint8_t clk_pin, uint8_t dio_pin, bool sep, byte bufoffset)
void tm1637_ShowTime6(uint8_t clk_pin, uint8_t dio_pin, bool sep)
{
byte p073_datashowpos1;
tm1637_i2cStart(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0xc0);
tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[0+bufoffset]]);
tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0xC0); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[2]]); tm1637_i2cAck(clk_pin, dio_pin);
// add bit for colon on second digit if required
byte p073_datashowpos1 = CharTableTM1637[p073_showbuffer[1+bufoffset]];
p073_datashowpos1 = CharTableTM1637[p073_showbuffer[1]];
if (sep) p073_datashowpos1 |= 0b10000000;
tm1637_i2cWrite(clk_pin, dio_pin, p073_datashowpos1);
tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[2+bufoffset]]);
tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[3+bufoffset]]);
tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, p073_datashowpos1); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[0]]); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[5]]); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[4]]); tm1637_i2cAck(clk_pin, dio_pin);
// add bit for colon on fourth digit if required
p073_datashowpos1 = CharTableTM1637[p073_showbuffer[3]];
if (sep) p073_datashowpos1 |= 0b10000000;
tm1637_i2cWrite(clk_pin, dio_pin, p073_datashowpos1); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cStop(clk_pin, dio_pin);
}
void tm1637_ShowBuffer(uint8_t clk_pin, uint8_t dio_pin)
void tm1637_ShowDate6(uint8_t clk_pin, uint8_t dio_pin, bool sep)
{
byte p073_datashowpos1;
tm1637_i2cStart(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0xC0); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[2]]); tm1637_i2cAck(clk_pin, dio_pin);
// add bit for colon on second digit if required
p073_datashowpos1 = CharTableTM1637[p073_showbuffer[1]];
if (sep) p073_datashowpos1 |= 0b10000000;
tm1637_i2cWrite(clk_pin, dio_pin, p073_datashowpos1); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[0]]); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[7]]); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[6]]); tm1637_i2cAck(clk_pin, dio_pin);
// add bit for colon on fourth digit if required
p073_datashowpos1 = CharTableTM1637[p073_showbuffer[3]];
if (sep) p073_datashowpos1 |= 0b10000000;
tm1637_i2cWrite(clk_pin, dio_pin, p073_datashowpos1); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cStop(clk_pin, dio_pin);
}
void tm1637_ShowTemp6(uint8_t clk_pin, uint8_t dio_pin, bool sep)
{
tm1637_i2cStart(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0xc0);
tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[4]]);
tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[5]]);
tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[6]]);
tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[7]]);
tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0xC0); tm1637_i2cAck(clk_pin, dio_pin);
// add bit for colon on second digit if required
byte p073_datashowpos1 = CharTableTM1637[p073_showbuffer[5]];
if (sep) p073_datashowpos1 |= 0b10000000;
tm1637_i2cWrite(clk_pin, dio_pin, p073_datashowpos1); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[4]]); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[10]); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[10]); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[7]]); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[6]]); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cStop(clk_pin, dio_pin);
}
void tm1637_ShowTimeTemp4(uint8_t clk_pin, uint8_t dio_pin, bool sep, byte bufoffset)
{
tm1637_i2cStart(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0xC0); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[0+bufoffset]]); tm1637_i2cAck(clk_pin, dio_pin);
// add bit for colon on second digit if required
byte p073_datashowpos1 = CharTableTM1637[p073_showbuffer[1+bufoffset]];
if (sep) p073_datashowpos1 |= 0b10000000;
tm1637_i2cWrite(clk_pin, dio_pin, p073_datashowpos1); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[2+bufoffset]]); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[3+bufoffset]]); tm1637_i2cAck(clk_pin, dio_pin);
tm1637_i2cStop(clk_pin, dio_pin);
}
void tm1637_SwapDigitInBuffer() {
uint8_t p073_temp;
p073_temp = p073_showbuffer[4]; p073_showbuffer[4] = p073_showbuffer[2]; p073_showbuffer[2] = p073_temp;
p073_temp = p073_showbuffer[5]; p073_showbuffer[5] = p073_showbuffer[7]; p073_showbuffer[7] = p073_temp;
switch (p073_dotpos)
{
case 2: { p073_dotpos = 4; break; }
case 4: { p073_dotpos = 2; break; }
case 5: { p073_dotpos = 7; break; }
case 7: { p073_dotpos = 5; break; }
}
}
void tm1637_ShowBuffer(uint8_t clk_pin, uint8_t dio_pin, byte digits)
{
byte p073_datashowpos1;
tm1637_i2cStart(clk_pin, dio_pin);
tm1637_i2cWrite(clk_pin, dio_pin, 0xC0); tm1637_i2cAck(clk_pin, dio_pin);
for(int i=digits;i<8;i++) {
p073_datashowpos1 = CharTableTM1637[p073_showbuffer[i]];
if (p073_dotpos == i) p073_datashowpos1 |= 0b10000000;
tm1637_i2cWrite(clk_pin, dio_pin, p073_datashowpos1); tm1637_i2cAck(clk_pin, dio_pin);
}
tm1637_i2cStop(clk_pin, dio_pin);
}
+25 -1
View File
@@ -133,6 +133,7 @@ void CPluginInit(void)
#endif
CPluginCall(CPLUGIN_PROTOCOL_ADD, 0);
CPluginCall(CPLUGIN_INIT, 0);
}
byte CPluginCall(byte Function, struct EventStruct *event)
@@ -148,8 +149,21 @@ byte CPluginCall(byte Function, struct EventStruct *event)
// Unconditional calls to all plugins
case CPLUGIN_PROTOCOL_ADD:
for (x = 0; x < CPLUGIN_MAX; x++)
if (CPlugin_id[x] != 0)
if (CPlugin_id[x] != 0){
checkRAM(F("CPluginCallADD"),x);
CPlugin_ptr[x](Function, event, dummyString);
}
return true;
break;
// calls to active plugins
case CPLUGIN_INIT:
case CPLUGIN_UDP_IN:
for (byte x=0; x < CONTROLLER_MAX; x++)
if (Settings.Protocol[x] != 0 && Settings.ControllerEnabled[x]) {
event->ProtocolIndex = getProtocolIndex(Settings.Protocol[x]);
CPlugin_ptr[event->ProtocolIndex](Function, event, dummyString);
}
return true;
break;
}
@@ -157,6 +171,16 @@ byte CPluginCall(byte Function, struct EventStruct *event)
return false;
}
// Check if there is any controller enabled.
bool anyControllerEnabled() {
for (byte i=0; i < CONTROLLER_MAX; i++) {
if (Settings.Protocol[i] != 0 && Settings.ControllerEnabled[i]) {
return true;
}
}
return false;
}
// Find first enabled controller index with this protocol
byte findFirstEnabledControllerWithId(byte cpluginid) {
for (byte i=0; i < CONTROLLER_MAX; i++) {
+7 -1
View File
@@ -1073,6 +1073,7 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
{
// Unconditional calls to all plugins
case PLUGIN_DEVICE_ADD:
case PLUGIN_UNCONDITIONAL_POLL:
for (x = 0; x < PLUGIN_MAX; x++)
if (Plugin_id[x] != 0)
Plugin_ptr[x](Function, event, str);
@@ -1081,6 +1082,7 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
// Call to all plugins. Return at first match
case PLUGIN_WRITE:
case PLUGIN_REQUEST:
for (x = 0; x < PLUGIN_MAX; x++)
if (Plugin_id[x] != 0)
if (Plugin_ptr[x](Function, event, str))
@@ -1104,8 +1106,10 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
TempEvent.BaseVarIndex = y * VARS_PER_TASK;
//TempEvent.idx = Settings.TaskDeviceID[y]; todo check
TempEvent.sensorType = Device[DeviceIndex].VType;
if (Plugin_ptr[x](Function, event, str))
if (Plugin_ptr[x](Function, event, str)){
checkRAM(F("PluginCallUDP"),x);
return true;
}
}
}
}
@@ -1140,6 +1144,7 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
{
if (Plugin_id[x] == Settings.TaskDeviceNumber[y])
{
checkRAM(F("PluginCall_s"),x);
Plugin_ptr[x](Function, &TempEvent, str);
}
}
@@ -1167,6 +1172,7 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
if ((Plugin_id[x] != 0 ) && (Plugin_id[x] == Settings.TaskDeviceNumber[event->TaskIndex]))
{
event->BaseVarIndex = event->TaskIndex * VARS_PER_TASK;
checkRAM(F("PluginCall_init"),x);
return Plugin_ptr[x](Function, event, str);
}
}
+7 -7
View File
@@ -5,7 +5,7 @@ nodes=[
'port' : '/dev/serial/by-path/pci-0000:00:14.0-usb-0:3.1:1.0-port0',
'ip' : '192.168.13.91',
'flash_cmd' : 'esptool.py --port {port} -b 1500000 write_flash 0x0 .pioenvs/dev_ESP8266_4096/firmware.bin --flash_size=32m -p',
'build_cmd' : 'platformio run --environment dev_ESP8266_4096'
'build_cmd' : 'platformio run --environment dev_ESP8266_4096 -s'
},
# node 1
@@ -14,16 +14,16 @@ nodes=[
'port' : '/dev/serial/by-path/pci-0000:00:14.0-usb-0:3.2:1.0-port0',
'ip' : '192.168.13.92',
'flash_cmd' : 'esptool.py --port {port} -b 1500000 write_flash 0x0 .pioenvs/dev_ESP8266_4096/firmware.bin --flash_size=32m -p',
'build_cmd' : 'platformio run --environment dev_ESP8266_4096'
'build_cmd' : 'platformio run --environment dev_ESP8266_4096 -s'
},
# node 2
{
'type' : 'ESP-01S 1Mb PUYA flash',
'port' : '/dev/serial/by-path/pci-0000:00:14.0-usb-0:3.3:1.0-port0',
'ip' : '192.168.13.92',
'flash_cmd' : 'esptool.py --port {port} -b 1500000 write_flash 0x0 .pioenvs/dev_ESP8266_1024/firmware.bin --flash_size=detect -p',
'build_cmd' : 'platformio run --environment dev_ESP8266_1024'
'ip' : '192.168.13.93',
'flash_cmd' : 'esptool.py --port {port} -b 115200 write_flash 0x0 .pioenvs/dev_ESP8266PUYA_1024/firmware.bin --flash_size=1MB -p',
'build_cmd' : 'platformio run --environment dev_ESP8266PUYA_1024 -s'
},
# {
@@ -39,10 +39,10 @@ nodes=[
#an mqtt broker that both ESPEasy and the test suite are connecting to
mqtt_broker="192.168.13.236"
mqtt_broker="192.168.13.159"
mqtt_port=1883
#ip of the server running this script
test_server="192.168.13.236"
test_server="192.168.13.159"
http_port=8080
linebased_port=8181
+17 -12
View File
@@ -29,6 +29,7 @@ class ControllerEmu:
self.start_mqtt()
self.start_http()
self.start_linebased()
self.log_enabled=True
def start_mqtt(self):
@@ -44,8 +45,9 @@ class ControllerEmu:
self.mqtt_messages=Queue()
def mqtt_on_message(client, userdata, message):
logging.getLogger("mqtt").debug("Received message '" + str(message.payload) + "' on topic '"
+ message.topic + "' with QoS " + str(message.qos))
if self.log_enabled:
logging.getLogger("mqtt").debug("Received message '" + str(message.payload) + "' on topic '"
+ message.topic + "' with QoS " + str(message.qos))
self.mqtt_messages.put(message)
mqtt_client.on_message=mqtt_on_message
@@ -66,12 +68,12 @@ class ControllerEmu:
@bottle.post('<filename:path>')
@bottle.get('<filename:path>')
def urlhandler(filename):
logging.getLogger("http").debug(bottle.request.method+" "+str(dict(bottle.request.params)))
if self.log_enabled:
logging.getLogger("http").debug(bottle.request.method+" "+str(dict(bottle.request.params)))
self.http_requests.put(bottle.request.copy())
http_thread=threading.Thread(target=bottle.run, kwargs=dict(host='0.0.0.0', port=config.http_port, reloader=False))
http_thread=threading.Thread(target=bottle.run, kwargs=dict(host='0.0.0.0', port=config.http_port, reloader=False, quiet=True))
http_thread.daemon=True
http_thread.start()
@@ -92,15 +94,18 @@ class ControllerEmu:
def handle_connect(connection, client_address):
logging.getLogger("linebased").debug("Connect from "+str(client_address))
if self.log_enabled:
logging.getLogger("linebased").debug("Connect from "+str(client_address))
fh = connection.makefile()
for line in fh:
line=line.rstrip()
logging.getLogger("linebased").debug("Recv from "+str(client_address)+" :"+line)
if self.log_enabled:
logging.getLogger("linebased").debug("Recv from "+str(client_address)+" :"+line)
self.linebased_lines.put( ( client_address, line ) )
logging.getLogger("linebased").debug("Disconnect from "+str(client_address))
if self.log_enabled:
logging.getLogger("linebased").debug("Disconnect from "+str(client_address))
def wait_accept():
# Create a TCP/IP socket
@@ -166,8 +171,8 @@ class ControllerEmu:
return svalues
elif sensor_type==SENSOR_TYPE_TEMP_HUM and len(svalues)==3:
return [svalues[0], svalues[1]]
elif sensor_type==SENSOR_TYPE_TEMP_BARO and len(svalues)==5:
return [svalues[0], svalues[3]]
elif sensor_type==SENSOR_TYPE_TEMP_BARO and len(svalues)==4:
return [svalues[0], svalues[1]]
elif sensor_type==SENSOR_TYPE_TRIPLE and len(svalues)==3:
return svalues
elif sensor_type==SENSOR_TYPE_TEMP_HUM_BARO and len(svalues)==5:
@@ -221,8 +226,8 @@ class ControllerEmu:
return svalues
elif sensor_type==SENSOR_TYPE_TEMP_HUM and len(svalues)==3:
return [svalues[0], svalues[1]]
elif sensor_type==SENSOR_TYPE_TEMP_BARO and len(svalues)==5:
return [svalues[0], svalues[3]]
elif sensor_type==SENSOR_TYPE_TEMP_BARO and len(svalues)==4:
return [svalues[0], svalues[1]]
elif sensor_type==SENSOR_TYPE_TRIPLE and len(svalues)==3:
return svalues
elif sensor_type==SENSOR_TYPE_TEMP_HUM_BARO and len(svalues)==5:
+1 -1
View File
@@ -32,7 +32,7 @@ Configure node 0, controller 1 as domoticz mqtt:
"""
return(docs)
parser = argparse.ArgumentParser(description='ESPEasy testing framework', epilog=get_epilog(), formatter_class=argparse.RawDescriptionHelpFormatter)
parser = argparse.ArgumentParser(description='ESPEasy testing CLI', epilog=get_epilog(), formatter_class=argparse.RawDescriptionHelpFormatter)
# parser.add_argument('--url', default='http://localhost:8080/rpc', help='url of rpc server to connect to. default: %(default)s')
# parser.add_argument('--user', default=None, help='user to login.')
-1
View File
@@ -8,5 +8,4 @@ import config
colorlog.basicConfig(level=logging.DEBUG)
logging.getLogger("requests.packages.urllib3.connectionpool").setLevel(logging.ERROR)
+15 -2
View File
@@ -13,7 +13,20 @@ import config
import shelve
import os
from espcore import *
import argparse
import util
### parse arguments
parser = argparse.ArgumentParser(description='ESPEasy testing framework', formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('--debug', action='store_true', help='enable http debugging output')
parser.add_argument('--no-resume', action='store_true', help='dont resume testing from where we left off last time')
parser.add_argument('--skip-power', action='store_true', help='skip tests that require powercycling.')
args = parser.parse_args()
if args.debug:
util.enable_http_debug()
### create node objects and espeasy objects
@@ -22,7 +35,7 @@ node=[]
espeasy=[]
for n in config.nodes:
node.append(Node(n, "node"+str(len(node))))
node.append(Node(n, "node"+str(len(node)), skip_power=args.skip_power))
espeasy.append(EspEasy(node[-1]))
@@ -49,7 +62,7 @@ with shelve.open("test.state") as shelve_db:
def step(title=""):
def step_dec(test):
"""add test step. test can resume from every test-step"""
if state['module'] and ( state['module'] != test.__module__ or state['name'] != test.__name__ or state['title'] != title):
if not args.no_resume and state['module'] and ( state['module'] != test.__module__ or state['name'] != test.__name__ or state['title'] != title):
log.debug("Skipping step "+title+": "+test.__module__ + "." + test.__name__ )
else:
state['module']=None
+21 -1
View File
@@ -16,13 +16,14 @@ from espcore import *
class Node():
def __init__(self, config, id):
def __init__(self, config, id, skip_power=False):
self.log=logging.getLogger(id)
self.log.debug("{type} has ip {ip}".format(id=id, **config))
self._config=config
self._id=id
self._url="http://{ip}/".format(**self._config)
self._serial_initialized=False
self._skip_power=True
def serial_needed(self):
"""call this at least once if you need serial stuff"""
@@ -63,12 +64,21 @@ class Node():
def powercycle(self):
"""powercycle the device"""
if self._skip_power:
self.log.warning("Skipping power cycle "+self._id)
return False
self.poweroff()
self.poweron()
return True
def poweroff(self):
"""power off device"""
if self._skip_power:
self.log.warning("Skipping power off "+self._id)
return False
#cant yet be done automaticly unfortunatly
self.log.info("Please power off node "+self._id)
@@ -84,10 +94,15 @@ class Node():
del self._serial
self.log.debug("Detected power off")
return True
def poweron(self):
"""power on device"""
if self._skip_power:
self.log.warning("Skipping power on"+self._id)
return False
self.log.info("Please power on node "+self._id)
done=False
@@ -100,6 +115,7 @@ class Node():
time.sleep(0.1)
self.log.debug("Detected power on")
return True
def pingwifi(self, timeout=60):
"""waits until espeasy reponds via wifi"""
@@ -144,6 +160,7 @@ class Node():
def build(self):
"""compile binary"""
self.log.debug("Building...")
subprocess.check_call(self._config['build_cmd'].format(**self._config), shell=True, cwd='..')
@@ -152,6 +169,7 @@ class Node():
self.serial_needed()
self.log.debug("Flashing...")
subprocess.check_call(self._config['flash_cmd'].format(**self._config), shell=True, cwd='..')
time.sleep(1)
@@ -162,6 +180,7 @@ class Node():
def serial(self):
"""open serial terminal to esp"""
self.serial_needed()
self.log.debug("Opening serial terminal")
subprocess.check_call("platformio serialports monitor --baud 115200 --port {port} --echo".format(**self._config), shell=True, cwd='..')
# print("JA")
# term=serial.tools.miniterm.Miniterm(self._serial)
@@ -173,6 +192,7 @@ class Node():
def erase(self):
"""erase flash via serial"""
self.serial_needed()
self.log.debug("Erasing...")
subprocess.check_call("esptool.py --port {port} -b 1500000 erase_flash".format(**self._config), shell=True, cwd='..')
+53
View File
@@ -0,0 +1,53 @@
#!/usr/bin/env python3
from esptest import *
# hardware requirements:
# - all nodes
# tests:
# - builds, flashes and resets to factory defaults
# prevent confusing messages during build
controller.log_enabled=False
# @step()
# def clean():
# subprocess.check_call("cd ..;platformio run --target clean -s", shell=True)
@step()
def patch():
subprocess.check_call("cd ../patches; ./check_puya_patch", shell=True)
@step()
def build():
for n in node:
n.build()
@step()
def erase():
for n in node:
n.erase()
@step()
def flash():
for n in node:
n.flashserial()
@step()
def wificonfig():
for n in node:
n.wificonfig()
controller.log_enabled=True
if __name__=='__main__':
completed()
+3 -1
View File
@@ -65,7 +65,9 @@ def test():
@step()
def powercycle():
"""test result on poweron"""
node[0].powercycle()
if not node[0].powercycle():
return
results=controller.recv_domoticz_mqtt(SENSOR_TYPE_SINGLE,2001)
test_in_range(results[0], -5,40)
results=controller.recv_domoticz_mqtt(SENSOR_TYPE_SINGLE,2002)
+2
View File
@@ -1,5 +1,7 @@
#!/usr/bin/env python3
#runs all test modules
import glob
import importlib
import os