mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 04:07:47 +00:00
Compare commits
172
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c5f8af083 | ||
|
|
e7a9ee7eee | ||
|
|
3edfdbf5f7 | ||
|
|
27bac2ca00 | ||
|
|
373f74e9f8 | ||
|
|
1220c565c8 | ||
|
|
1931fe9e53 | ||
|
|
0eab6293dc | ||
|
|
f0987dab41 | ||
|
|
51bd52603f | ||
|
|
47f1fa145a | ||
|
|
605055d95a | ||
|
|
af3e353181 | ||
|
|
c711d6ea51 | ||
|
|
20c23a2935 | ||
|
|
bbfe254232 | ||
|
|
882c888f6d | ||
|
|
0a754f072c | ||
|
|
1f084c51cc | ||
|
|
89df0932c5 | ||
|
|
429fd3e4d0 | ||
|
|
85e8d98da8 | ||
|
|
6d52a7e03a | ||
|
|
fa513b52f9 | ||
|
|
f98401524f | ||
|
|
4090b4f23c | ||
|
|
b89c00008d | ||
|
|
d57a617138 | ||
|
|
cefe6b4b7c | ||
|
|
2432740b41 | ||
|
|
44a934651c | ||
|
|
95fb0d6e6c | ||
|
|
8ccbdcadf0 | ||
|
|
433aa6910a | ||
|
|
2ebc733b63 | ||
|
|
21bc1a7814 | ||
|
|
53b8009df6 | ||
|
|
68a8e5982e | ||
|
|
08acfeac97 | ||
|
|
999a561515 | ||
|
|
3ee1a4ed2e | ||
|
|
05801db47c | ||
|
|
7bec632f15 | ||
|
|
3f8fe11b47 | ||
|
|
4b8f1e4c1b | ||
|
|
573fd0f320 | ||
|
|
4fa5203c5b | ||
|
|
9c9617f6ed | ||
|
|
bbbf6c483f | ||
|
|
668909e7b3 | ||
|
|
c642848ef2 | ||
|
|
6eea35aa81 | ||
|
|
738a48213c | ||
|
|
d1c093d109 | ||
|
|
00166a1aad | ||
|
|
589238324b | ||
|
|
6787bc8c0e | ||
|
|
6845a03741 | ||
|
|
6a4284f189 | ||
|
|
cf644b45b1 | ||
|
|
e6fe1c63a9 | ||
|
|
df978036f0 | ||
|
|
7cb375833d | ||
|
|
41c57f1ef9 | ||
|
|
808b40bdba | ||
|
|
58b20615da | ||
|
|
13026b1cc4 | ||
|
|
7f3460e492 | ||
|
|
a222391f81 | ||
|
|
a8165531d5 | ||
|
|
3218ea9839 | ||
|
|
eca8901fca | ||
|
|
6635eafe91 | ||
|
|
fe4d1f952f | ||
|
|
1abd31b421 | ||
|
|
72fe49d905 | ||
|
|
9dd9f3befa | ||
|
|
471d76dbe6 | ||
|
|
4475a225cc | ||
|
|
8b047490c4 | ||
|
|
455f77d0ed | ||
|
|
836fc4a875 | ||
|
|
2aece1c143 | ||
|
|
70df225e7e | ||
|
|
19af52a3ef | ||
|
|
3d396575ff | ||
|
|
873f8474b5 | ||
|
|
826deaac89 | ||
|
|
cce621cff8 | ||
|
|
57eb38dbd0 | ||
|
|
fd2451bb07 | ||
|
|
c94e5cb903 | ||
|
|
27699f7192 | ||
|
|
2eff001b14 | ||
|
|
bd499c7a94 | ||
|
|
4da1e4fbdd | ||
|
|
1d14770ea7 | ||
|
|
8b7574d298 | ||
|
|
14d87d95f6 | ||
|
|
5a15288d80 | ||
|
|
869dff12ce | ||
|
|
cc0b3dac26 | ||
|
|
4208048fc1 | ||
|
|
06a2f47812 | ||
|
|
d3434eb4d2 | ||
|
|
bd2665041f | ||
|
|
1fd429a029 | ||
|
|
7b3a71bcc9 | ||
|
|
18e612dea2 | ||
|
|
f99593ed62 | ||
|
|
2f7e96fa5b | ||
|
|
25b4392dd5 | ||
|
|
ad4130a547 | ||
|
|
e4d4463eab | ||
|
|
991384822f | ||
|
|
b29f56c6f4 | ||
|
|
779514481d | ||
|
|
82ed319e59 | ||
|
|
0a752dd26f | ||
|
|
2e4af86a99 | ||
|
|
8112e0e67a | ||
|
|
89a9f842fd | ||
|
|
b4791d3421 | ||
|
|
885c5394a3 | ||
|
|
e35304e4e7 | ||
|
|
6561d577d4 | ||
|
|
92932fddb2 | ||
|
|
02d8834763 | ||
|
|
e82080dc52 | ||
|
|
89581fd0fb | ||
|
|
cfbf972c1b | ||
|
|
e25ea52edc | ||
|
|
3f84a961ad | ||
|
|
7d8e5e5175 | ||
|
|
3d39dec686 | ||
|
|
ff656593ec | ||
|
|
96bfaa27f5 | ||
|
|
bcca0514dd | ||
|
|
90b4e3438d | ||
|
|
139f8905d0 | ||
|
|
6c1806fae6 | ||
|
|
e6b581e7ff | ||
|
|
bb9f8fc809 | ||
|
|
4d9504bce0 | ||
|
|
ff3a769033 | ||
|
|
e3de56a7a8 | ||
|
|
873d639461 | ||
|
|
edb2a6d3f6 | ||
|
|
2682b0bd2f | ||
|
|
5097157a09 | ||
|
|
02ea957894 | ||
|
|
c2b0d76595 | ||
|
|
91b7cbe075 | ||
|
|
bff60a2e27 | ||
|
|
61831e5962 | ||
|
|
d105b47d44 | ||
|
|
449568bcc4 | ||
|
|
3144077103 | ||
|
|
8f056be0a8 | ||
|
|
e9cdc5693d | ||
|
|
64b38df187 | ||
|
|
377c50ec36 | ||
|
|
76f6dfdc59 | ||
|
|
3a6f7acd15 | ||
|
|
d65b126f84 | ||
|
|
90a2a799da | ||
|
|
feb419b6ae | ||
|
|
e83d8468b0 | ||
|
|
6eabaaa62d | ||
|
|
8299e38b24 | ||
|
|
eee55a92d9 | ||
|
|
21398fbf8a |
Vendored
+237
@@ -1,3 +1,240 @@
|
||||
-------------------------------------------------
|
||||
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)
|
||||
-------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,3 +1,6 @@
|
||||
#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= {
|
||||
@@ -38,3 +41,5 @@ const char inactiveSymbole[] PROGMEM = {
|
||||
B00000000,
|
||||
B00000000
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+2
-5
@@ -8,9 +8,6 @@ void sendData(struct EventStruct *event)
|
||||
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);
|
||||
|
||||
@@ -138,7 +135,7 @@ bool MQTTConnect(int controller_idx)
|
||||
|
||||
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.
|
||||
|
||||
boolean MQTTresult = false;
|
||||
@@ -247,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);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-10
@@ -58,19 +58,22 @@ String centimeterToImperialLength(float cm) {
|
||||
}
|
||||
|
||||
String millimeterToImperialLength(float mm) {
|
||||
int inches = mm / 25.4;
|
||||
float inches = mm / 25.4;
|
||||
int feet = inches /12;
|
||||
inches = inches % 12;
|
||||
char imperial[20];
|
||||
if (feet == 0)
|
||||
sprintf_P(imperial, PSTR("%d%c"), inches, '"');
|
||||
else
|
||||
sprintf_P(imperial, PSTR("%d%c%d%c"), feet, '\'', inches, '"');
|
||||
return imperial;
|
||||
inches = inches - (feet * 12);
|
||||
String result;
|
||||
result.reserve(10);
|
||||
if (feet != 0) {
|
||||
result += feet;
|
||||
result += '\'';
|
||||
}
|
||||
result += toString(inches,1);
|
||||
result += '"';
|
||||
return result;
|
||||
}
|
||||
|
||||
int minutesToDay(int minutes) {
|
||||
return minutes / 1440;
|
||||
float minutesToDay(int minutes) {
|
||||
return minutes / 1440.0;
|
||||
}
|
||||
|
||||
String minutesToDayHour(int minutes) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+47
-1089
File diff suppressed because it is too large
Load Diff
@@ -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_ */
|
||||
|
||||
+174
-135
@@ -27,8 +27,6 @@ bool isDeepSleepEnabled()
|
||||
{
|
||||
if (!Settings.deepSleep)
|
||||
return false;
|
||||
if (!timeOutReached(timerAwakeFromDeepSleep + 1000 * Settings.deepSleep))
|
||||
return false;
|
||||
|
||||
//cancel deep sleep loop by pulling the pin GPIO16(D0) to GND
|
||||
//recommended wiring: 3-pin-header with 1=RST, 2=D0, 3=GND
|
||||
@@ -42,6 +40,13 @@ bool isDeepSleepEnabled()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readyForSleep()
|
||||
{
|
||||
if (!isDeepSleepEnabled())
|
||||
return false;
|
||||
return timeOutReached(timerAwakeFromDeepSleep + 1000 * Settings.deepSleep);
|
||||
}
|
||||
|
||||
void deepSleep(int delay)
|
||||
{
|
||||
|
||||
@@ -973,22 +978,11 @@ String ClearInFile(char* fname, int index, int datasize)
|
||||
String LoadFromFile(char* fname, int index, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("LoadFromFile"));
|
||||
// addLog(LOG_LEVEL_INFO, String(F("FILE : Load size "))+datasize);
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "r+");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
|
||||
// addLog(LOG_LEVEL_INFO, String(F("FILE : File size "))+f.size());
|
||||
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
byte *pointerToByteToRead = memAddress;
|
||||
for (int x = 0; x < datasize; x++)
|
||||
{
|
||||
int readres=f.read();
|
||||
SPIFFS_CHECK(readres >=0, fname);
|
||||
*pointerToByteToRead = readres;
|
||||
pointerToByteToRead++;// next byte
|
||||
}
|
||||
SPIFFS_CHECK(f.read(memAddress,datasize), fname);
|
||||
f.close();
|
||||
|
||||
return(String());
|
||||
@@ -1896,6 +1890,29 @@ int Calculate(const char *input, float* result)
|
||||
}
|
||||
|
||||
|
||||
void checkRuleSets(){
|
||||
for (byte x=0; x < RULESETS_MAX; x++){
|
||||
#if defined(ESP8266)
|
||||
String fileName = F("rules");
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
String fileName = F("/rules");
|
||||
#endif
|
||||
fileName += x+1;
|
||||
fileName += F(".txt");
|
||||
if (SPIFFS.exists(fileName))
|
||||
activeRuleSets[x] = true;
|
||||
else
|
||||
activeRuleSets[x] = false;
|
||||
|
||||
if (Settings.SerialLogLevel == LOG_LEVEL_DEBUG_DEV){
|
||||
Serial.print(fileName);
|
||||
Serial.print(" ");
|
||||
Serial.println(activeRuleSets[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Rules processing
|
||||
@@ -1910,7 +1927,7 @@ void rulesProcessing(String& event)
|
||||
log += event;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
for (byte x = 1; x < RULESETS_MAX + 1; x++)
|
||||
for (byte x = 0; x < RULESETS_MAX; x++)
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
String fileName = F("rules");
|
||||
@@ -1918,9 +1935,9 @@ void rulesProcessing(String& event)
|
||||
#if defined(ESP32)
|
||||
String fileName = F("/rules");
|
||||
#endif
|
||||
fileName += x;
|
||||
fileName += x+1;
|
||||
fileName += F(".txt");
|
||||
if (SPIFFS.exists(fileName))
|
||||
if(activeRuleSets[x])
|
||||
rulesProcessingFile(fileName, event);
|
||||
}
|
||||
|
||||
@@ -1937,6 +1954,11 @@ void rulesProcessing(String& event)
|
||||
String rulesProcessingFile(String fileName, String& event)
|
||||
{
|
||||
checkRAM(F("rulesProcessingFile"));
|
||||
if (Settings.SerialLogLevel == LOG_LEVEL_DEBUG_DEV){
|
||||
Serial.print(F("RuleDebug Processing:"));
|
||||
Serial.println(fileName);
|
||||
Serial.println(F(" flags CMI parse output:"));
|
||||
}
|
||||
fs::File f = SPIFFS.open(fileName, "r+");
|
||||
SPIFFS_CHECK(f, fileName.c_str());
|
||||
|
||||
@@ -1950,11 +1972,9 @@ String rulesProcessingFile(String fileName, String& event)
|
||||
log = F("EVENT: Error: Nesting level exceeded!");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
nestingLevel--;
|
||||
return(log);
|
||||
return (log);
|
||||
}
|
||||
|
||||
|
||||
// int pos = 0;
|
||||
String line = "";
|
||||
boolean match = false;
|
||||
boolean codeBlock = false;
|
||||
@@ -1963,148 +1983,167 @@ String rulesProcessingFile(String fileName, String& event)
|
||||
boolean condition = false;
|
||||
boolean ifBranche = false;
|
||||
|
||||
byte buf[RULES_BUFFER_SIZE];
|
||||
int len = 0;
|
||||
while (f.available())
|
||||
{
|
||||
data = f.read();
|
||||
len = f.read((byte*)buf, RULES_BUFFER_SIZE);
|
||||
for (int x = 0; x < len; x++) {
|
||||
data = buf[x];
|
||||
|
||||
SPIFFS_CHECK(data >= 0, fileName.c_str());
|
||||
SPIFFS_CHECK(data >= 0, fileName.c_str());
|
||||
|
||||
if (data != 10)
|
||||
line += char(data);
|
||||
if (data != 10)
|
||||
line += char(data);
|
||||
|
||||
if (data == 10) // if line complete, parse this rule
|
||||
{
|
||||
line.replace("\r", "");
|
||||
if (line.substring(0, 2) != "//" && line.length() > 0)
|
||||
if (data == 10) // if line complete, parse this rule
|
||||
{
|
||||
isCommand = true;
|
||||
|
||||
int comment = line.indexOf("//");
|
||||
if (comment > 0)
|
||||
line = line.substring(0, comment);
|
||||
|
||||
line = parseTemplate(line, line.length());
|
||||
line.trim();
|
||||
|
||||
String lineOrg = line; // store original line for future use
|
||||
line.toLowerCase(); // convert all to lower case to make checks easier
|
||||
|
||||
String eventTrigger = "";
|
||||
String action = "";
|
||||
|
||||
if (!codeBlock) // do not check "on" rules if a block of actions is to be processed
|
||||
line.replace("\r", "");
|
||||
if (line.substring(0, 2) != "//" && line.length() > 0)
|
||||
{
|
||||
if (line.startsWith("on "))
|
||||
isCommand = true;
|
||||
|
||||
int comment = line.indexOf("//");
|
||||
if (comment > 0)
|
||||
line = line.substring(0, comment);
|
||||
|
||||
if (match || !codeBlock) {
|
||||
// only parse [xxx#yyy] if we have a matching ruleblock or need to eval the "on" (no codeBlock)
|
||||
// This to avoid waisting CPU time...
|
||||
line = parseTemplate(line, line.length());
|
||||
}
|
||||
line.trim();
|
||||
|
||||
String lineOrg = line; // store original line for future use
|
||||
line.toLowerCase(); // convert all to lower case to make checks easier
|
||||
|
||||
|
||||
String eventTrigger = "";
|
||||
String action = "";
|
||||
|
||||
if (!codeBlock) // do not check "on" rules if a block of actions is to be processed
|
||||
{
|
||||
line = line.substring(3);
|
||||
int split = line.indexOf(" do");
|
||||
if (line.startsWith("on "))
|
||||
{
|
||||
line = line.substring(3);
|
||||
int split = line.indexOf(" do");
|
||||
if (split != -1)
|
||||
{
|
||||
eventTrigger = line.substring(0, split);
|
||||
action = lineOrg.substring(split + 7);
|
||||
action.trim();
|
||||
}
|
||||
if (eventTrigger == "*") // wildcard, always process
|
||||
match = true;
|
||||
else
|
||||
match = ruleMatch(event, eventTrigger);
|
||||
if (action.length() > 0) // single on/do/action line, no block
|
||||
{
|
||||
isCommand = true;
|
||||
codeBlock = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
isCommand = false;
|
||||
codeBlock = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
action = lineOrg;
|
||||
}
|
||||
|
||||
String lcAction = action;
|
||||
lcAction.toLowerCase();
|
||||
if (lcAction == "endon") // Check if action block has ended, then we will wait for a new "on" rule
|
||||
{
|
||||
isCommand = false;
|
||||
codeBlock = false;
|
||||
match = false;
|
||||
}
|
||||
|
||||
if (Settings.SerialLogLevel == LOG_LEVEL_DEBUG_DEV){
|
||||
Serial.print(F("RuleDebug: "));
|
||||
Serial.print(codeBlock);
|
||||
Serial.print(match);
|
||||
Serial.print(isCommand);
|
||||
Serial.print(": ");
|
||||
Serial.println(line);
|
||||
}
|
||||
|
||||
if (match) // rule matched for one action or a block of actions
|
||||
{
|
||||
int split = lcAction.indexOf("if "); // check for optional "if" condition
|
||||
if (split != -1)
|
||||
{
|
||||
eventTrigger = line.substring(0, split);
|
||||
action = lineOrg.substring(split + 7);
|
||||
action.trim();
|
||||
}
|
||||
if (eventTrigger == "*") // wildcard, always process
|
||||
match = true;
|
||||
else
|
||||
match = ruleMatch(event, eventTrigger);
|
||||
if (action.length() > 0) // single on/do/action line, no block
|
||||
{
|
||||
isCommand = true;
|
||||
codeBlock = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
conditional = true;
|
||||
String check = lcAction.substring(split + 3);
|
||||
condition = conditionMatchExtended(check);
|
||||
ifBranche = true;
|
||||
isCommand = false;
|
||||
codeBlock = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
action = lineOrg;
|
||||
}
|
||||
|
||||
String lcAction = action;
|
||||
lcAction.toLowerCase();
|
||||
if (lcAction == "endon") // Check if action block has ended, then we will wait for a new "on" rule
|
||||
{
|
||||
isCommand = false;
|
||||
codeBlock = false;
|
||||
}
|
||||
|
||||
if (match) // rule matched for one action or a block of actions
|
||||
{
|
||||
int split = lcAction.indexOf("if "); // check for optional "if" condition
|
||||
if (split != -1)
|
||||
{
|
||||
conditional = true;
|
||||
String check = lcAction.substring(split + 3);
|
||||
condition = conditionMatchExtended(check);
|
||||
ifBranche = true;
|
||||
isCommand = false;
|
||||
}
|
||||
|
||||
if (lcAction == "else") // in case of an "else" block of actions, set ifBranche to false
|
||||
{
|
||||
ifBranche = false;
|
||||
isCommand = false;
|
||||
}
|
||||
|
||||
if (lcAction == "endif") // conditional block ends here
|
||||
{
|
||||
conditional = false;
|
||||
isCommand = false;
|
||||
}
|
||||
|
||||
// process the action if it's a command and unconditional, or conditional and the condition matches the if or else block.
|
||||
if (isCommand && ((!conditional) || (conditional && (condition == ifBranche))))
|
||||
{
|
||||
if (event.charAt(0) == '!')
|
||||
if (lcAction == "else") // in case of an "else" block of actions, set ifBranche to false
|
||||
{
|
||||
action.replace(F("%eventvalue%"), event); // substitute %eventvalue% with literal event string if starting with '!'
|
||||
ifBranche = false;
|
||||
isCommand = false;
|
||||
}
|
||||
else
|
||||
|
||||
if (lcAction == "endif") // conditional block ends here
|
||||
{
|
||||
int equalsPos = event.indexOf("=");
|
||||
if (equalsPos > 0)
|
||||
conditional = false;
|
||||
isCommand = false;
|
||||
}
|
||||
|
||||
// process the action if it's a command and unconditional, or conditional and the condition matches the if or else block.
|
||||
if (isCommand && ((!conditional) || (conditional && (condition == ifBranche))))
|
||||
{
|
||||
if (event.charAt(0) == '!')
|
||||
{
|
||||
String tmpString = event.substring(equalsPos + 1);
|
||||
action.replace(F("%eventvalue%"), tmpString); // substitute %eventvalue% in actions with the actual value from the event
|
||||
action.replace(F("%eventvalue%"), event); // substitute %eventvalue% with literal event string if starting with '!'
|
||||
}
|
||||
}
|
||||
log = F("ACT : ");
|
||||
log += action;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
else
|
||||
{
|
||||
int equalsPos = event.indexOf("=");
|
||||
if (equalsPos > 0)
|
||||
{
|
||||
String tmpString = event.substring(equalsPos + 1);
|
||||
action.replace(F("%eventvalue%"), tmpString); // substitute %eventvalue% in actions with the actual value from the event
|
||||
}
|
||||
}
|
||||
log = F("ACT : ");
|
||||
log += action;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
struct EventStruct TempEvent;
|
||||
parseCommandString(&TempEvent, action);
|
||||
yield();
|
||||
// Use a tmp string to call PLUGIN_WRITE, since PluginCall may inadvertenly alter the string.
|
||||
String tmpAction(action);
|
||||
if (!PluginCall(PLUGIN_WRITE, &TempEvent, tmpAction)) {
|
||||
if (!tmpAction.equals(action)) {
|
||||
String log = F("PLUGIN_WRITE altered the string: ");
|
||||
log += action;
|
||||
log += F(" to: ");
|
||||
log += tmpAction;
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
struct EventStruct TempEvent;
|
||||
parseCommandString(&TempEvent, action);
|
||||
yield();
|
||||
// Use a tmp string to call PLUGIN_WRITE, since PluginCall may inadvertenly alter the string.
|
||||
String tmpAction(action);
|
||||
if (!PluginCall(PLUGIN_WRITE, &TempEvent, tmpAction)) {
|
||||
if (!tmpAction.equals(action)) {
|
||||
String log = F("PLUGIN_WRITE altered the string: ");
|
||||
log += action;
|
||||
log += F(" to: ");
|
||||
log += tmpAction;
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
ExecuteCommand(VALUE_SOURCE_SYSTEM, action.c_str());
|
||||
}
|
||||
ExecuteCommand(VALUE_SOURCE_SYSTEM, action.c_str());
|
||||
yield();
|
||||
}
|
||||
yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
line = "";
|
||||
line = "";
|
||||
}
|
||||
}
|
||||
//pos++;
|
||||
}
|
||||
|
||||
nestingLevel--;
|
||||
checkRAM(F("rulesProcessingFile2"));
|
||||
return(String());
|
||||
return (String());
|
||||
}
|
||||
|
||||
|
||||
@@ -2482,7 +2521,7 @@ class RamTracker{
|
||||
writePtr=0;
|
||||
for (int i = 0; i< TRACES; i++) {
|
||||
traces[i]="";
|
||||
tracesMemory[i]=0xffff; // init with best case memory values, so they get replaced if memory goes lower
|
||||
tracesMemory[i]=0xffffffff; // init with best case memory values, so they get replaced if memory goes lower
|
||||
}
|
||||
for (int i = 0; i< TRACEENTRIES; i++) {
|
||||
nextAction[i]="startup";
|
||||
@@ -2591,7 +2630,7 @@ void play_rtttl(uint8_t _pin, const char *p )
|
||||
#define OCTAVE_OFFSET 0
|
||||
// FIXME: Absolutely no error checking in here
|
||||
|
||||
int notes[] = { 0,
|
||||
const int notes[] = { 0,
|
||||
262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494,
|
||||
523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988,
|
||||
1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976,
|
||||
|
||||
+6
-167
@@ -36,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)
|
||||
\*********************************************************************************************/
|
||||
@@ -108,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];
|
||||
@@ -160,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;
|
||||
}
|
||||
}
|
||||
@@ -236,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
|
||||
\*********************************************************************************************/
|
||||
@@ -761,6 +596,11 @@ bool WiFiConnected(uint32_t timeout_ms) {
|
||||
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;
|
||||
@@ -798,4 +638,3 @@ bool hostReachable(const String& hostname) {
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -285,10 +285,13 @@ void parseSystemVariables(String& s, boolean useURLencode)
|
||||
#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.
|
||||
@@ -306,6 +309,7 @@ void parseSystemVariables(String& s, boolean useURLencode)
|
||||
#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);
|
||||
@@ -367,11 +371,11 @@ void parseStandardConversions(String& s, boolean useURLencode) {
|
||||
// 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%"), String(CelsiusToFahrenheit(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%"), String(minutesToDay(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))
|
||||
|
||||
+40
-7
@@ -390,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
|
||||
@@ -409,20 +433,29 @@ 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);
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
|
||||
@@ -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;
|
||||
|
||||
+163
-116
@@ -6,6 +6,7 @@
|
||||
#define ONLY_IP_RANGE_ALLOWED 2
|
||||
#define _HEAD false
|
||||
#define _TAIL true
|
||||
#define CHUNKED_BUFFER_SIZE 400
|
||||
|
||||
void sendContentBlocking(String& data);
|
||||
void sendHeaderBlocking(bool json);
|
||||
@@ -21,58 +22,72 @@ public:
|
||||
uint32_t finalRam;
|
||||
uint32_t maxCoreUsage;
|
||||
uint32_t maxServerUsage;
|
||||
unsigned int BufferSize;
|
||||
unsigned int sentBytes;
|
||||
String buf;
|
||||
|
||||
StreamingBuffer(void) : lowMemorySkip(false),
|
||||
initialRam(0), beforeTXRam(0), duringTXRam(0), finalRam(0), maxCoreUsage(0),
|
||||
maxServerUsage(0), BufferSize(400), sentBytes(0)
|
||||
maxServerUsage(0), sentBytes(0)
|
||||
{
|
||||
buf.reserve(BufferSize + 100);
|
||||
buf.reserve(CHUNKED_BUFFER_SIZE + 50);
|
||||
buf = "";
|
||||
}
|
||||
StreamingBuffer operator= (String& a) { this->buf=a; checkFull(); return *this; }
|
||||
StreamingBuffer operator= (const String& a) { this->buf=a; checkFull(); return *this; }
|
||||
StreamingBuffer operator+= (long unsigned int a) { this->buf+=String(a); checkFull(); return *this; }
|
||||
StreamingBuffer operator+= (float a) { this->buf+=String(a); checkFull(); return *this; }
|
||||
StreamingBuffer operator+= (int a) { this->buf+=String(a); checkFull(); return *this; }
|
||||
StreamingBuffer operator+= (uint32_t a) { this->buf+=String(a); checkFull(); return *this; }
|
||||
StreamingBuffer operator+=(const String& a) {
|
||||
StreamingBuffer operator= (String& a) { flush(); return addString(a); }
|
||||
StreamingBuffer operator= (const String& a) { flush(); return addString(a); }
|
||||
StreamingBuffer operator+= (long unsigned int a) { return addString(String(a)); }
|
||||
StreamingBuffer operator+= (float a) { return addString(String(a)); }
|
||||
StreamingBuffer operator+= (int a) { return addString(String(a)); }
|
||||
StreamingBuffer operator+= (uint32_t a) { return addString(String(a)); }
|
||||
StreamingBuffer operator+=(const String& a) { return addString(a); }
|
||||
|
||||
StreamingBuffer addString(const String& a) {
|
||||
if (lowMemorySkip) return *this;
|
||||
const int length = a.length();
|
||||
if (((this->buf.length() + length) > BufferSize) &&
|
||||
(this->buf.length() > 100))
|
||||
sendContentBlocking(this->buf);
|
||||
int flush_step = CHUNKED_BUFFER_SIZE - this->buf.length();
|
||||
if (flush_step < 1) flush_step = 0;
|
||||
int pos = 0;
|
||||
int flush_step = BufferSize - this->buf.length();
|
||||
if (flush_step < 1) flush_step = 1;
|
||||
const int length = a.length();
|
||||
while (pos < length) {
|
||||
const char c = a[pos];
|
||||
this->buf += c;
|
||||
++pos;
|
||||
--flush_step;
|
||||
if (flush_step == 0) {
|
||||
sendContentBlocking(this->buf);
|
||||
flush_step = BufferSize;
|
||||
flush_step = CHUNKED_BUFFER_SIZE;
|
||||
}
|
||||
this->buf += a[pos];
|
||||
++pos;
|
||||
--flush_step;
|
||||
}
|
||||
checkFull();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void flush() {
|
||||
if (lowMemorySkip) {
|
||||
this->buf = "";
|
||||
} else {
|
||||
sendContentBlocking(this->buf);
|
||||
}
|
||||
}
|
||||
|
||||
void checkFull(void) {
|
||||
if (lowMemorySkip) this->buf = "";
|
||||
if (this->buf.length() > BufferSize) {
|
||||
if (this->buf.length() > CHUNKED_BUFFER_SIZE) {
|
||||
trackTotalMem();
|
||||
sendContentBlocking(this->buf);
|
||||
}
|
||||
}
|
||||
|
||||
void startStream() {
|
||||
startStream(false);
|
||||
}
|
||||
|
||||
void startJsonStream() {
|
||||
startStream(true);
|
||||
}
|
||||
|
||||
private:
|
||||
void startStream(bool json) {
|
||||
maxCoreUsage = maxServerUsage = 0;
|
||||
beforeTXRam = ESP.getFreeHeap();
|
||||
initialRam = ESP.getFreeHeap();
|
||||
beforeTXRam = initialRam;
|
||||
sentBytes = 0;
|
||||
buf = "";
|
||||
if (beforeTXRam < 3000) {
|
||||
@@ -83,7 +98,7 @@ public:
|
||||
#endif
|
||||
return;
|
||||
} else
|
||||
sendHeaderBlocking();
|
||||
sendHeaderBlocking(json);
|
||||
}
|
||||
|
||||
void trackTotalMem() {
|
||||
@@ -92,6 +107,8 @@ public:
|
||||
maxServerUsage = initialRam - beforeTXRam;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void trackCoreMem() {
|
||||
duringTXRam = ESP.getFreeHeap();
|
||||
if ((initialRam - duringTXRam) > maxCoreUsage)
|
||||
@@ -118,17 +135,18 @@ public:
|
||||
void sendContentBlocking(String& data) {
|
||||
checkRAM(F("sendContentBlocking"));
|
||||
uint32_t freeBeforeSend = ESP.getFreeHeap();
|
||||
String log = String("sendcontent free: ") + freeBeforeSend + " chunk size:" + data.length();
|
||||
const uint32_t length = data.length();
|
||||
String log = String("sendcontent free: ") + freeBeforeSend + " chunk size:" + length;
|
||||
addLog(LOG_LEVEL_DEBUG_DEV, log);
|
||||
freeBeforeSend = ESP.getFreeHeap();
|
||||
if (TXBuffer.beforeTXRam > freeBeforeSend)
|
||||
TXBuffer.beforeTXRam = freeBeforeSend;
|
||||
TXBuffer.duringTXRam = freeBeforeSend;
|
||||
#if defined(ESP8266) && defined(ARDUINO_ESP8266_RELEASE_2_3_0)
|
||||
String size = String(data.length(), HEX) + "\r\n";
|
||||
String size = String(length, HEX) + "\r\n";
|
||||
// do chunked transfer encoding ourselves (WebServer doesn't support it)
|
||||
WebServer.sendContent(size);
|
||||
if (data.length()) WebServer.sendContent(data);
|
||||
if (length > 0) WebServer.sendContent(data);
|
||||
WebServer.sendContent("\r\n");
|
||||
#else // ESP8266 2.4.0rc2 and higher and the ESP32 webserver supports chunked http transfer
|
||||
unsigned int timeout = 0;
|
||||
@@ -147,18 +165,18 @@ void sendContentBlocking(String& data) {
|
||||
}
|
||||
#endif
|
||||
|
||||
TXBuffer.sentBytes += data.length();
|
||||
TXBuffer.sentBytes += length;
|
||||
data = "";
|
||||
}
|
||||
|
||||
void sendHeaderBlocking() {
|
||||
void sendHeaderBlocking(bool json) {
|
||||
checkRAM(F("sendHeaderBlocking"));
|
||||
#if defined(ESP8266) && defined(ARDUINO_ESP8266_RELEASE_2_3_0)
|
||||
WebServer.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||
WebServer.sendHeader("Content-Type", "text/html", true);
|
||||
WebServer.sendHeader("Accept-Ranges", "none");
|
||||
WebServer.sendHeader("Cache-Control", "no-cache");
|
||||
WebServer.sendHeader("Transfer-Encoding", "chunked");
|
||||
WebServer.sendHeader(F("Content-Type"), json ? F("application/json") : F("text/html"), true);
|
||||
WebServer.sendHeader(F("Accept-Ranges"), F("none"));
|
||||
WebServer.sendHeader(F("Cache-Control"), F("no-cache"));
|
||||
WebServer.sendHeader(F("Transfer-Encoding"), F("chunked"));
|
||||
WebServer.send(200);
|
||||
#else
|
||||
unsigned int timeout = 0;
|
||||
@@ -167,8 +185,8 @@ void sendHeaderBlocking() {
|
||||
if (freeBeforeSend < 4000) timeout = 1000;
|
||||
const uint32_t beginWait = millis();
|
||||
WebServer.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||
WebServer.sendHeader("Content-Type", "text/html", true);
|
||||
WebServer.sendHeader("Cache-Control", "no-cache");
|
||||
WebServer.sendHeader(F("Content-Type"), json ? F("application/json") : F("text/html"), true);
|
||||
WebServer.sendHeader(F("Cache-Control"), F("no-cache"));
|
||||
WebServer.send(200);
|
||||
// dont wait on 2.3.0. Memory returns just too slow.
|
||||
while ((ESP.getFreeHeap() < freeBeforeSend) &&
|
||||
@@ -349,7 +367,7 @@ void clearAccessBlock()
|
||||
//********************************************************************************
|
||||
// Web Interface init
|
||||
//********************************************************************************
|
||||
#include "core_version.h"
|
||||
//#include "core_version.h"
|
||||
#define HTML_SYMBOL_WARNING "⚠"
|
||||
|
||||
#if defined(ESP8266)
|
||||
@@ -380,6 +398,7 @@ static const char pgDefaultCSS[] PROGMEM = {
|
||||
".note {color: #444; font-style: italic; }"
|
||||
//header with title and menu
|
||||
".headermenu {position: fixed; top: 0; left: 0; right: 0; height: 90px; padding: 8px 12px; background-color: #F8F8F8; border-bottom: 1px solid #DDD; }"
|
||||
".apheader {padding: 8px 12px; background-color: #F8F8F8;}"
|
||||
".bodymenu {margin-top: 96px; }"
|
||||
// menu
|
||||
".menubar {position: inherit; top: 55px; }"
|
||||
@@ -494,11 +513,13 @@ void getWebPageTemplateDefault(const String& tmplName, String& tmpl)
|
||||
"{{css}}"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<header class='headermenu'>"
|
||||
"<header class='apheader'>"
|
||||
"<h1>Welcome to ESP Easy Mega AP</h1>"
|
||||
"</header>"
|
||||
"<section>"
|
||||
"<span class='message error'>"
|
||||
"{{error}}"
|
||||
"</span>"
|
||||
"{{content}}"
|
||||
"</section>"
|
||||
"<footer>"
|
||||
@@ -521,7 +542,9 @@ void getWebPageTemplateDefault(const String& tmplName, String& tmpl)
|
||||
"<h1>ESP Easy Mega: {{name}}</h1>"
|
||||
"</header>"
|
||||
"<section>"
|
||||
"<span class='message error'>"
|
||||
"{{error}}"
|
||||
"</span>"
|
||||
"{{content}}"
|
||||
"</section>"
|
||||
"<footer>"
|
||||
@@ -658,13 +681,15 @@ void getWebPageTemplateVar(const String& varName )
|
||||
// Send CSS per chunk to avoid sending either too short or too large strings.
|
||||
String tmpString;
|
||||
tmpString.reserve(64);
|
||||
uint16_t tmpStringPos = 0;
|
||||
for (unsigned int i = 0; i < strlen(pgDefaultCSS); i++)
|
||||
{
|
||||
const char c = (char)pgm_read_byte(&pgDefaultCSS[i]);
|
||||
tmpString += c;
|
||||
if (c == ';' || c == '{') {
|
||||
tmpString += (char)pgm_read_byte(&pgDefaultCSS[i]);
|
||||
++tmpStringPos;
|
||||
if (tmpStringPos == 64) {
|
||||
TXBuffer += tmpString;
|
||||
tmpString = "";
|
||||
tmpStringPos = 0;
|
||||
}
|
||||
} // saves 1k of ram
|
||||
if (tmpString.length() > 0) {
|
||||
@@ -1186,6 +1211,7 @@ void handle_controllers() {
|
||||
copyFormPassword(F("controllerpassword"), SecuritySettings.ControllerPassword[controllerindex], sizeof(SecuritySettings.ControllerPassword[0]));
|
||||
strncpy(ControllerSettings.Subscribe, controllersubscribe.c_str(), sizeof(ControllerSettings.Subscribe));
|
||||
strncpy(ControllerSettings.Publish, controllerpublish.c_str(), sizeof(ControllerSettings.Publish));
|
||||
CPlugin_ptr[ProtocolIndex](CPLUGIN_INIT, &TempEvent, dummyString);
|
||||
}
|
||||
}
|
||||
addHtmlError( TXBuffer.buf, SaveControllerSettings(controllerindex, (byte*)&ControllerSettings, sizeof(ControllerSettings)));
|
||||
@@ -1264,57 +1290,61 @@ void handle_controllers() {
|
||||
options[0] = F("Use IP address");
|
||||
options[1] = F("Use Hostname");
|
||||
|
||||
addFormSelector(TXBuffer.buf, F("Locate Controller"), F("usedns"), 2, options, NULL, NULL, choice, true);
|
||||
|
||||
if (ControllerSettings.UseDNS)
|
||||
{
|
||||
addFormTextBox(TXBuffer.buf, F("Controller Hostname"), F("controllerhostname"), ControllerSettings.HostName, sizeof(ControllerSettings.HostName)-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
addFormIPBox(TXBuffer.buf, F("Controller IP"), F("controllerip"), ControllerSettings.IP);
|
||||
}
|
||||
|
||||
addFormNumericBox(TXBuffer.buf, F("Controller Port"), F("controllerport"), ControllerSettings.Port, 1, 65535);
|
||||
|
||||
byte ProtocolIndex = getProtocolIndex(Settings.Protocol[controllerindex]);
|
||||
if (Protocol[ProtocolIndex].usesAccount)
|
||||
{
|
||||
String protoDisplayName;
|
||||
if (!getControllerProtocolDisplayName(ProtocolIndex, CONTROLLER_USER, protoDisplayName)) {
|
||||
protoDisplayName = F("Controller User");
|
||||
if (!Protocol[ProtocolIndex].Custom){
|
||||
|
||||
addFormSelector(TXBuffer.buf, F("Locate Controller"), F("usedns"), 2, options, NULL, NULL, choice, true);
|
||||
|
||||
if (ControllerSettings.UseDNS)
|
||||
{
|
||||
addFormTextBox(TXBuffer.buf, F("Controller Hostname"), F("controllerhostname"), ControllerSettings.HostName, sizeof(ControllerSettings.HostName)-1);
|
||||
}
|
||||
addFormTextBox(TXBuffer.buf, protoDisplayName, F("controlleruser"), SecuritySettings.ControllerUser[controllerindex], sizeof(SecuritySettings.ControllerUser[0])-1);
|
||||
}
|
||||
if (Protocol[ProtocolIndex].usesPassword)
|
||||
{
|
||||
String protoDisplayName;
|
||||
if (getControllerProtocolDisplayName(ProtocolIndex, CONTROLLER_PASS, protoDisplayName)) {
|
||||
// It is not a regular password, thus use normal text field.
|
||||
addFormTextBox(TXBuffer.buf, protoDisplayName, F("controllerpassword"), SecuritySettings.ControllerPassword[controllerindex], sizeof(SecuritySettings.ControllerPassword[0])-1);
|
||||
} else {
|
||||
addFormPasswordBox(TXBuffer.buf, F("Controller Password"), F("controllerpassword"), SecuritySettings.ControllerPassword[controllerindex], sizeof(SecuritySettings.ControllerPassword[0])-1);
|
||||
else
|
||||
{
|
||||
addFormIPBox(TXBuffer.buf, F("Controller IP"), F("controllerip"), ControllerSettings.IP);
|
||||
}
|
||||
|
||||
addFormNumericBox(TXBuffer.buf, F("Controller Port"), F("controllerport"), ControllerSettings.Port, 1, 65535);
|
||||
|
||||
if (Protocol[ProtocolIndex].usesAccount)
|
||||
{
|
||||
String protoDisplayName;
|
||||
if (!getControllerProtocolDisplayName(ProtocolIndex, CONTROLLER_USER, protoDisplayName)) {
|
||||
protoDisplayName = F("Controller User");
|
||||
}
|
||||
addFormTextBox(TXBuffer.buf, protoDisplayName, F("controlleruser"), SecuritySettings.ControllerUser[controllerindex], sizeof(SecuritySettings.ControllerUser[0])-1);
|
||||
}
|
||||
if (Protocol[ProtocolIndex].usesPassword)
|
||||
{
|
||||
String protoDisplayName;
|
||||
if (getControllerProtocolDisplayName(ProtocolIndex, CONTROLLER_PASS, protoDisplayName)) {
|
||||
// It is not a regular password, thus use normal text field.
|
||||
addFormTextBox(TXBuffer.buf, protoDisplayName, F("controllerpassword"), SecuritySettings.ControllerPassword[controllerindex], sizeof(SecuritySettings.ControllerPassword[0])-1);
|
||||
} else {
|
||||
addFormPasswordBox(TXBuffer.buf, F("Controller Password"), F("controllerpassword"), SecuritySettings.ControllerPassword[controllerindex], sizeof(SecuritySettings.ControllerPassword[0])-1);
|
||||
}
|
||||
}
|
||||
|
||||
if (Protocol[ProtocolIndex].usesTemplate || Protocol[ProtocolIndex].usesMQTT)
|
||||
{
|
||||
String protoDisplayName;
|
||||
if (!getControllerProtocolDisplayName(ProtocolIndex, CONTROLLER_SUBSCRIBE, protoDisplayName)) {
|
||||
protoDisplayName = F("Controller Subscribe");
|
||||
}
|
||||
addFormTextBox(TXBuffer.buf, protoDisplayName, F("controllersubscribe"), ControllerSettings.Subscribe, sizeof(ControllerSettings.Subscribe)-1);
|
||||
}
|
||||
|
||||
if (Protocol[ProtocolIndex].usesTemplate || Protocol[ProtocolIndex].usesMQTT)
|
||||
{
|
||||
String protoDisplayName;
|
||||
if (!getControllerProtocolDisplayName(ProtocolIndex, CONTROLLER_PUBLISH, protoDisplayName)) {
|
||||
protoDisplayName = F("Controller Publish");
|
||||
}
|
||||
addFormTextBox(TXBuffer.buf, protoDisplayName, F("controllerpublish"), ControllerSettings.Publish, sizeof(ControllerSettings.Publish)-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (Protocol[ProtocolIndex].usesTemplate || Protocol[ProtocolIndex].usesMQTT)
|
||||
{
|
||||
String protoDisplayName;
|
||||
if (!getControllerProtocolDisplayName(ProtocolIndex, CONTROLLER_SUBSCRIBE, protoDisplayName)) {
|
||||
protoDisplayName = F("Controller Subscribe");
|
||||
}
|
||||
addFormTextBox(TXBuffer.buf, protoDisplayName, F("controllersubscribe"), ControllerSettings.Subscribe, sizeof(ControllerSettings.Subscribe)-1);
|
||||
}
|
||||
|
||||
if (Protocol[ProtocolIndex].usesTemplate || Protocol[ProtocolIndex].usesMQTT)
|
||||
{
|
||||
String protoDisplayName;
|
||||
if (!getControllerProtocolDisplayName(ProtocolIndex, CONTROLLER_PUBLISH, protoDisplayName)) {
|
||||
protoDisplayName = F("Controller Publish");
|
||||
}
|
||||
addFormTextBox(TXBuffer.buf, protoDisplayName, F("controllerpublish"), ControllerSettings.Publish, sizeof(ControllerSettings.Publish)-1);
|
||||
}
|
||||
|
||||
addFormCheckBox(TXBuffer.buf, F("Enabled"), F("controllerenabled"), Settings.ControllerEnabled[controllerindex]);
|
||||
|
||||
TempEvent.ControllerIndex = controllerindex;
|
||||
@@ -1825,18 +1855,6 @@ void handle_devices() {
|
||||
if (Device[DeviceIndex].InverseLogicOption)
|
||||
Settings.TaskDevicePin1Inversed[taskIndex] = (WebServer.arg(F("TDPI")) == F("on"));
|
||||
|
||||
if (Settings.GlobalSync)
|
||||
{
|
||||
if (Device[DeviceIndex].GlobalSyncOption)
|
||||
Settings.TaskDeviceGlobalSync[taskIndex] = (WebServer.arg(F("TDGS")) == F("on"));
|
||||
|
||||
// Send task info if set global
|
||||
if (Settings.TaskDeviceGlobalSync[taskIndex])
|
||||
{
|
||||
SendUDPTaskInfo(0, taskIndex, taskIndex);
|
||||
}
|
||||
}
|
||||
|
||||
for (byte varNr = 0; varNr < Device[DeviceIndex].ValueCount; varNr++)
|
||||
{
|
||||
|
||||
@@ -1864,6 +1882,18 @@ void handle_devices() {
|
||||
|
||||
//allow the plugin to save plugin-specific form settings.
|
||||
PluginCall(PLUGIN_WEBFORM_SAVE, &TempEvent, dummyString);
|
||||
|
||||
// notify controllers: CPLUGIN_TASK_CHANGE_NOTIFICATION
|
||||
for (byte x=0; x < CONTROLLER_MAX; x++)
|
||||
{
|
||||
TempEvent.ControllerIndex = x;
|
||||
if (Settings.TaskDeviceSendData[TempEvent.ControllerIndex][TempEvent.TaskIndex] &&
|
||||
Settings.ControllerEnabled[TempEvent.ControllerIndex] && Settings.Protocol[TempEvent.ControllerIndex])
|
||||
{
|
||||
TempEvent.ProtocolIndex = getProtocolIndex(Settings.Protocol[TempEvent.ControllerIndex]);
|
||||
CPlugin_ptr[TempEvent.ProtocolIndex](CPLUGIN_TASK_CHANGE_NOTIFICATION, &TempEvent, dummyString);
|
||||
}
|
||||
}
|
||||
}
|
||||
addHtmlError( SaveTaskSettings(taskIndex));
|
||||
|
||||
@@ -2062,11 +2092,6 @@ void handle_devices() {
|
||||
|
||||
addFormCheckBox(TXBuffer.buf, F("Enabled"), F("TDE"), Settings.TaskDeviceEnabled[taskIndex]); //="taskdeviceenabled"
|
||||
|
||||
if (Settings.GlobalSync && Device[DeviceIndex].GlobalSyncOption && Settings.TaskDeviceDataFeed[taskIndex] == 0 && Settings.UDPPort != 0)
|
||||
{
|
||||
addFormCheckBox(TXBuffer.buf, F("Global Sync"), F("TDGS"), Settings.TaskDeviceGlobalSync[taskIndex]); //="taskdeviceglobalsync"
|
||||
}
|
||||
|
||||
// section: Sensor / Actuator
|
||||
if (!Device[DeviceIndex].Custom && Settings.TaskDeviceDataFeed[taskIndex] == 0 &&
|
||||
((Device[DeviceIndex].Ports != 0) || (Device[DeviceIndex].PullUpOption) || (Device[DeviceIndex].InverseLogicOption) || (Device[DeviceIndex].Type >= DEVICE_TYPE_SINGLE && Device[DeviceIndex].Type <= DEVICE_TYPE_TRIPLE)) )
|
||||
@@ -3417,8 +3442,7 @@ void handle_control() {
|
||||
checkRAM(F("handle_control"));
|
||||
if (!clientIPallowed()) return;
|
||||
//TXBuffer.startStream(true); // true= json
|
||||
// sendHeadandTail(F("TmplStd"),_HEAD);
|
||||
|
||||
// sendHeadandTail(F("TmplStd"),_HEAD);
|
||||
String webrequest = WebServer.arg(F("cmd"));
|
||||
|
||||
// in case of event, store to buffer and return...
|
||||
@@ -3437,18 +3461,18 @@ void handle_control() {
|
||||
printToWeb = true;
|
||||
printWebString = "";
|
||||
|
||||
if (printToWebJSON)
|
||||
TXBuffer.startJsonStream();
|
||||
else
|
||||
TXBuffer.startStream();
|
||||
|
||||
if (PluginCall(PLUGIN_WRITE, &TempEvent, webrequest));
|
||||
else if (remoteConfig(&TempEvent, webrequest));
|
||||
else
|
||||
TXBuffer += F("Unknown or restricted command!");
|
||||
|
||||
TXBuffer += printWebString;
|
||||
|
||||
if (printToWebJSON)
|
||||
WebServer.send(200, "application/json");
|
||||
else
|
||||
WebServer.send(200, "text/html");
|
||||
TXBuffer += printWebString;
|
||||
TXBuffer.endStream();
|
||||
|
||||
printWebString = "";
|
||||
printToWeb = false;
|
||||
@@ -3475,10 +3499,34 @@ void handle_json()
|
||||
reply += F(",\n");
|
||||
reply += to_json_object_value(F("Unit"), String(Settings.Unit));
|
||||
reply += F(",\n");
|
||||
reply += to_json_object_value(F("Name"), String(Settings.Name));
|
||||
reply += F(",\n");
|
||||
reply += to_json_object_value(F("Uptime"), String(wdcounter / 2));
|
||||
reply += F(",\n");
|
||||
reply += to_json_object_value(F("Free RAM"), String(ESP.getFreeHeap()));
|
||||
reply += F("\n},\n");
|
||||
|
||||
reply += F("\"WiFi\":{\n");
|
||||
reply += to_json_object_value(F("Hostname"), WiFi.hostname());
|
||||
reply += F(",\n");
|
||||
reply += to_json_object_value(F("IP"), WiFi.localIP().toString());
|
||||
reply += F(",\n");
|
||||
reply += to_json_object_value(F("Subnet Mask"), WiFi.subnetMask().toString());
|
||||
reply += F(",\n");
|
||||
reply += to_json_object_value(F("Gateway IP"), WiFi.gatewayIP().toString());
|
||||
reply += F(",\n");
|
||||
reply += to_json_object_value(F("MAC address"), WiFi.macAddress());
|
||||
reply += F(",\n");
|
||||
reply += to_json_object_value(F("DNS 1"), WiFi.dnsIP(0).toString());
|
||||
reply += F(",\n");
|
||||
reply += to_json_object_value(F("DNS 2"), WiFi.dnsIP(1).toString());
|
||||
reply += F(",\n");
|
||||
reply += to_json_object_value(F("SSID"), WiFi.SSID());
|
||||
reply += F(",\n");
|
||||
reply += to_json_object_value(F("BSSID"), WiFi.BSSIDstr());
|
||||
reply += F(",\n");
|
||||
reply += to_json_object_value(F("RSSI"), String(WiFi.RSSI()));
|
||||
reply += F("\n},\n");
|
||||
}
|
||||
|
||||
byte taskNr = tasknr.toInt();
|
||||
@@ -3572,7 +3620,6 @@ void handle_advanced() {
|
||||
String usessdp = WebServer.arg(F("usessdp"));
|
||||
String edit = WebServer.arg(F("edit"));
|
||||
String wireclockstretchlimit = WebServer.arg(F("wireclockstretchlimit"));
|
||||
String globalsync = WebServer.arg(F("globalsync"));
|
||||
String userules = WebServer.arg(F("userules"));
|
||||
String cft = WebServer.arg(F("cft"));
|
||||
String MQTTRetainFlag = WebServer.arg(F("mqttretainflag"));
|
||||
@@ -3606,7 +3653,6 @@ void handle_advanced() {
|
||||
Settings.UseSSDP = (usessdp == "on");
|
||||
Settings.WireClockStretchLimit = wireclockstretchlimit.toInt();
|
||||
Settings.UseRules = (userules == "on");
|
||||
Settings.GlobalSync = (globalsync == "on");
|
||||
Settings.ConnectionFailuresThreshold = cft.toInt();
|
||||
Settings.MQTTRetainFlag = (MQTTRetainFlag == "on");
|
||||
Settings.ArduinoOTAEnable = (ArduinoOTAEnable == "on");
|
||||
@@ -3662,9 +3708,8 @@ void handle_advanced() {
|
||||
addFormNumericBox(TXBuffer.buf, F("Baud Rate"), F("baudrate"), Settings.BaudRate, 0, 1000000);
|
||||
|
||||
|
||||
addFormSubHeader(TXBuffer.buf, F("Inter-ESPEasy Network (experimental)"));
|
||||
addFormSubHeader(TXBuffer.buf, F("Inter-ESPEasy Network"));
|
||||
|
||||
addFormCheckBox( TXBuffer.buf, F("Global Sync"), F("globalsync"), Settings.GlobalSync);
|
||||
addFormNumericBox(TXBuffer.buf, F("UDP port"), F("udpport"), Settings.UDPPort, 0, 65535);
|
||||
|
||||
|
||||
@@ -4143,7 +4188,7 @@ void handle_filelist() {
|
||||
if (fdelete.length() > 0)
|
||||
{
|
||||
SPIFFS.remove(fdelete);
|
||||
// flashCount();
|
||||
checkRuleSets();
|
||||
}
|
||||
|
||||
|
||||
@@ -4617,6 +4662,7 @@ void handle_rules() {
|
||||
|
||||
TXBuffer += F("<TR><TD>Edit: ");
|
||||
addSelector(TXBuffer.buf, F("set"), RULESETS_MAX, options, optionValues, NULL, choice, true);
|
||||
addButton(TXBuffer.buf, fileName, F("Download to file"));
|
||||
addHelpButton(TXBuffer.buf, F("Tutorial_Rules"));
|
||||
|
||||
// load form data from flash
|
||||
@@ -4656,6 +4702,7 @@ void handle_rules() {
|
||||
sendHeadandTail(F("TmplStd"),true);
|
||||
TXBuffer.endStream();
|
||||
|
||||
checkRuleSets();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+248
-107
@@ -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,131 +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);
|
||||
}
|
||||
|
||||
#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");
|
||||
//********************************************************************************
|
||||
// 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);
|
||||
}
|
||||
else{
|
||||
log += F("mDNS failed");
|
||||
}
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
if (Settings.UseRules)
|
||||
{
|
||||
String event = F("WiFi#Connected");
|
||||
rulesProcessing(event);
|
||||
}
|
||||
return(true);
|
||||
if (connected) {
|
||||
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
|
||||
@@ -238,6 +372,7 @@ boolean WifiConnectSSID(char WifiSSID[], char WifiKey[], byte connectAttempts)
|
||||
void WifiDisconnect()
|
||||
{
|
||||
WiFi.disconnect();
|
||||
wifiConnected = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -279,7 +414,6 @@ void WifiScan()
|
||||
//********************************************************************************
|
||||
void WifiCheck()
|
||||
{
|
||||
|
||||
if(wifiSetup)
|
||||
return;
|
||||
|
||||
@@ -289,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;
|
||||
}
|
||||
@@ -305,6 +442,10 @@ void WifiCheck()
|
||||
WifiAPMode(false);
|
||||
}
|
||||
}
|
||||
if (!wifiConnected) {
|
||||
if (tryConnectWiFi())
|
||||
checkWifiJustConnected();
|
||||
}
|
||||
}
|
||||
|
||||
//********************************************************************************
|
||||
|
||||
+1
-1
@@ -89,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();
|
||||
}
|
||||
|
||||
|
||||
+265
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(" ≙ ");
|
||||
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(" ≙ ");
|
||||
addTextBox(string, F("plugin_060_out2"), String(Settings.TaskDevicePluginConfigFloat[event->TaskIndex][1], 3), 10);
|
||||
|
||||
|
||||
+8
-8
@@ -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);
|
||||
|
||||
+225
-70
@@ -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,16 +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_BIT_DELAY 50
|
||||
#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
|
||||
@@ -90,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);
|
||||
@@ -115,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);
|
||||
@@ -122,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)
|
||||
@@ -148,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);
|
||||
@@ -182,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) {
|
||||
@@ -206,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;
|
||||
@@ -213,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();
|
||||
@@ -228,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);
|
||||
@@ -241,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;
|
||||
}
|
||||
|
||||
@@ -294,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);
|
||||
@@ -410,68 +480,90 @@ void p073_FillBufferWithDash() // in case of error show all dashes
|
||||
#define DIO_HIGH() pinMode(dio_pin, INPUT)
|
||||
#define DIO_LOW() pinMode(dio_pin, OUTPUT)
|
||||
|
||||
void tm1637_bitDelay(){
|
||||
delayMicroseconds(TM1637_BIT_DELAY);
|
||||
}
|
||||
|
||||
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();
|
||||
tm1637_bitDelay();
|
||||
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();
|
||||
tm1637_bitDelay();
|
||||
delayMicroseconds(TM1637_CLOCKDELAY);
|
||||
DIO_LOW();
|
||||
tm1637_bitDelay();
|
||||
delayMicroseconds(TM1637_CLOCKDELAY);
|
||||
CLK_HIGH();
|
||||
tm1637_bitDelay();
|
||||
delayMicroseconds(TM1637_CLOCKDELAY);
|
||||
DIO_HIGH();
|
||||
}
|
||||
|
||||
void tm1637_i2cAck (uint8_t clk_pin, uint8_t dio_pin)
|
||||
{
|
||||
bool dummyAck = false;
|
||||
CLK_LOW();
|
||||
DIO_HIGH();
|
||||
tm1637_bitDelay();
|
||||
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();
|
||||
tm1637_bitDelay();
|
||||
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();
|
||||
tm1637_bitDelay();
|
||||
delayMicroseconds(TM1637_CLOCKDELAY);
|
||||
bytetoprint = bytetoprint >> 1;
|
||||
CLK_HIGH();
|
||||
tm1637_bitDelay();
|
||||
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;
|
||||
@@ -485,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);
|
||||
@@ -496,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ void CPluginInit(void)
|
||||
#endif
|
||||
|
||||
CPluginCall(CPLUGIN_PROTOCOL_ADD, 0);
|
||||
CPluginCall(CPLUGIN_INIT, 0);
|
||||
}
|
||||
|
||||
byte CPluginCall(byte Function, struct EventStruct *event)
|
||||
@@ -154,6 +155,17 @@ byte CPluginCall(byte Function, struct EventStruct *event)
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user