From 2fbbaf7972d2ab3540bc70e66eb1de83799b38af Mon Sep 17 00:00:00 2001 From: Jaro Date: Thu, 19 Nov 2020 10:55:37 +0100 Subject: [PATCH] remove clock dependency --- platformio.ini | 23 +- src/Scroller.cpp | 45 ++-- src/Scroller.h | 27 ++- src/main.cpp | 549 +++++++++++++++-------------------------------- 4 files changed, 239 insertions(+), 405 deletions(-) diff --git a/platformio.ini b/platformio.ini index 1a56c6c..ba62067 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,4 +1,4 @@ -;PlatformIO Project Configuration File +; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags @@ -8,9 +8,22 @@ ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html -[env:esp32doit-devkit-v1] +[env:ttgo-t1] platform = espressif32 -board = esp32doit-devkit-v1 +board = ttgo-t1 framework = arduino -monitor_port = COM[13] -monitor_speed = 115200 \ No newline at end of file +monitor_port = COM[1367] +monitor_speed = 115200 +lib_deps = + knolleary/PubSubClient@^2.8 + adafruit/Adafruit GFX Library@^1.10.1 + adafruit/Adafruit BusIO@^1.5.0 + fastled/FastLED@^3.3.3 + marcmerlin/FastLED NeoMatrix@^1.2 + bertmelis/Ticker-esp32@^1.1.0 + bblanchon/ArduinoJson@^6.16.1 + prampec/IotWebConf@^2.3.1 + khoih-prog/ESP32TimerInterrupt@^1.0.3 + aharshac/StringSplitter@^1.0.0 + sstaub/NTP@^1.4 + aster94/Utilities@^0.4.6 diff --git a/src/Scroller.cpp b/src/Scroller.cpp index 3359bd6..33b51ba 100644 --- a/src/Scroller.cpp +++ b/src/Scroller.cpp @@ -5,19 +5,20 @@ Scroller::Scroller(int max_loops) _max_loops = max_loops; } -void Scroller::SetMatrix(Adafruit_NeoMatrix *matrix) +void Scroller::SetMatrix(FastLED_NeoMatrix *matrix) { - this->_matrix = matrix; + _matrix = matrix; } int Scroller::GetNumberOfLines() { - return this->_nlines; + return _nlines; } int Scroller::AddLine(String line) { - this->_Lines[this->_nlines] = line; + _Lines[_nlines] = line; + SetParameters(_nlines); return _nlines++; } @@ -25,6 +26,7 @@ int Scroller::AddLines(String* lines,int nlines) { for (int i=0; i < nlines; i++) { _Lines[i] = lines[i]; + SetParameters(i); } _nlines = nlines; @@ -42,7 +44,7 @@ void Scroller::DeleteLines() _nlines = 0; } -int Scroller::Scroll(int tick) +int Scroller::Scroll() { int mx = 32; String line; @@ -55,29 +57,30 @@ int Scroller::Scroll(int tick) { _matrix->fillScreen(0); _matrix->setCursor(-_x, _y); - _matrix->setTextColor(_colors[1]); + _matrix->setTextColor(_colors[_Settings[_lp].color]); + _matrix->setBrightness(_Settings[_lp].brightness); _matrix->print(line); _matrix->show(); if (_x++ == 0) { - return 3; + return _Settings[_lp].timeout_on/SCROLLER_TICK_TIME; } else { - return 1; + return _Settings[_lp].speed/SCROLLER_TICK_TIME; } } _lp++; _x = 0; - return 10; + return _Settings[_lp].timeout_off/SCROLLER_TICK_TIME; } else { _matrix->fillScreen(0); _matrix->setCursor(_x, _y); - _matrix->setTextColor(_colors[1]); + _matrix->setTextColor(_colors[_Settings[_lp].color]); + _matrix->setBrightness(_Settings[_lp].brightness); _matrix->print(line); _matrix->show(); - _lp++; - return 30; + return _Settings[_lp++].timeout_off/SCROLLER_TICK_TIME; } } @@ -91,6 +94,7 @@ void Scroller::PrintSerialLines() bool Scroller::TurnOn() { + Serial.println("Turn on Scroller"); _off = false; _lp = 0; _x = 0; @@ -103,6 +107,7 @@ bool Scroller::TurnOn() void Scroller::TurnOff() { + Serial.println("TURN OFF"); _matrix->fillScreen(0); _matrix->print(""); _matrix->show(); @@ -114,7 +119,7 @@ void Scroller::SetColors(uint16_t *colors) _colors = colors; } -void Scroller::loop(int tick) +void Scroller::loop(ulong tick) { if (_off) return; @@ -131,10 +136,13 @@ void Scroller::loop(int tick) return; } - if (_delayTicks - delta <= 0) _delayTicks = Scroll(tick); + if (_delayTicks - delta <= 0) _delayTicks = Scroll(); else _delayTicks -= delta; + if (_delayTicks < 0) _delayTicks = 0; + + _tick = tick; } int Scroller::TimesScrolled() @@ -142,6 +150,15 @@ int Scroller::TimesScrolled() return _nscrolled; } +void Scroller::SetParameters(int line,uint8_t color,uint8_t brightness,int timeout_off,int timeout_on,int speed) +{ + _Settings[line].color = color; + _Settings[line].brightness = brightness; + _Settings[line].timeout_on = timeout_on; + _Settings[line].timeout_off = timeout_off; + _Settings[line].speed = speed; +} + Scroller::~Scroller() { } diff --git a/src/Scroller.h b/src/Scroller.h index da31a38..584aa9a 100644 --- a/src/Scroller.h +++ b/src/Scroller.h @@ -1,45 +1,58 @@ #ifndef SCROLLER_H #define SCROLLER_H -#include -#include -#include +#include +#include #include #include +#include "ESP32TimerInterrupt.h" + #define SCROLLER_TICK_TIME 100 //ms +struct Setting +{ + uint8_t color; + uint8_t brightness; + int timeout_off; + int timeout_on; + int speed; +}; + class Scroller { private: /* data */ const static int MAX_LINES = 10; String _Lines[MAX_LINES]; + Setting _Settings[MAX_LINES]; int _nlines = 0; int _lp = 0; int _tick=0; int _delayTicks = 0; int _nscrolled = 0; int _x = 0, _y = 0; - Adafruit_NeoMatrix *_matrix; + FastLED_NeoMatrix *_matrix; uint16_t *_colors; int _max_loops; bool _off = true; + public: Scroller(int max_loops); bool TurnOn(); void SetColors(uint16_t *colors); - void SetMatrix(Adafruit_NeoMatrix *matrix); + void SetMatrix(FastLED_NeoMatrix *matrix); int AddLine(String line); + void SetParameters(int line,uint8_t color=1,uint8_t brightness=10,int timeout_off=2000,int timeout_on=2000,int speed=200); int AddLines(String* lines,int nlines); void DeleteLines(); bool ReplaceLine(int number,String line); int GetNumberOfLines(); - int Scroll(int tick); + int Scroll(); int TimesScrolled(); void PrintSerialLines(); void TurnOff(); - void loop(int tick); + void loop(ulong tick); ~Scroller(); }; #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 38eb49b..49369e0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,8 +1,8 @@ #include #include -#include -#include -#include +#include +#include +#include #include @@ -27,9 +27,11 @@ #define COMMAND_PARAMETER_LENGTH 30 #define MAX_TIMES_SCROLLED 5 -#define PIN 15 +#define PIN 27 -#include +WiFiClient espClient; +PubSubClient client(espClient); +unsigned long lastMqttConnectionAttempt=0; void handleRoot(); void processCommand(); @@ -39,23 +41,24 @@ const char thingName[] = "BADThing"; // -- Initial password to connect to the Thing, when it creates an own Access Point. const char wifiInitialApPassword[] = "BADesp32"; +#define STRING_LEN 128 +char mqttServerValue[STRING_LEN]; + DNSServer dnsServer; WebServer server(80); IotWebConf iotWebConf(thingName, &dnsServer, &server, wifiInitialApPassword); +IotWebConfParameter mqttServerParam = IotWebConfParameter("MQTT server", "mqttServer", mqttServerValue, STRING_LEN,"text","BADnet-gw.lan","BADnet-gw.lan",NULL); -enum Lines_names -{ - TIME_LINE, - DATE_LINE, - WEATHER_LINE, - NAMES_LINE, - LAST_LINE -}; -String Lines[LAST_LINE]; -Adafruit_NeoMatrix *matrix; +#define lcdw 32 +#define lcdh 8 +#define NUMMATRIX (lcdw*lcdh) + +CRGB matrixleds[NUMMATRIX]; + +FastLED_NeoMatrix *matrix; uint16_t colors[] = { - Adafruit_NeoMatrix::Color(255, 0, 0), Adafruit_NeoMatrix::Color(0, 255, 0), Adafruit_NeoMatrix::Color(0, 0, 255)}; + Framebuffer_GFX::Color(255, 0, 0), Framebuffer_GFX::Color(0, 255, 0), Framebuffer_GFX::Color(0, 0, 255)}; WiFiUDP ntpUDP; @@ -64,63 +67,30 @@ WiFiUDP ntpUDP; // update interval (in milliseconds, can be changed using setUpdateInterval() ). bool initialized = false; NTP ntp(ntpUDP); -HTTPClient client; -DynamicJsonDocument doc(1024); -String settings; - -enum when_names { - WORK_DAYS, - WEEKENDS, - TOMOROW, - ONCE -}; - -struct timer_def { - int when; int h; int m; int d; int mh; int y; -}; - -int ntimers,nextTimer = -1; -int nts; TimeZone DateTime; -TimeZone nextAlarmDateTime; -#define MAX_TIMERS 10 -timer_def Timers[MAX_TIMERS]; Scroller scroller(MAX_TIMES_SCROLLED); unsigned long last_millis; -bool showText = false; +bool showTextMqtt = false; int scrolledTicker = 0; bool updateNtpTime = false; +bool needMqttConnect = false; ESP32Timer ITimer0(0); ESP32Timer ITimer1(1); ESP32Timer ITimer2(2); +ulong tick; +void IRAM_ATTR TimerScrollTime1(void); + #define TIMER0_INTERVAL_MS 1000 -#define TIMER1_INTERVAL_MS 100 #define TIMER2_INTERVAL_MS 60000 -void IRAM_ATTR TimerCheckTime0(void) -{ - unsigned long m = millis(), delta; - - delta = (m - last_millis)/1000; - - DateTime += delta; - - if (nextAlarmDateTime.epoch() <= DateTime.epoch() && nextTimer != -1) { - showText = true; - scroller.TurnOn(); - } - - last_millis = m; -} - void IRAM_ATTR TimerScrollTime1(void) { - scrolledTicker++; + tick++; } void IRAM_ATTR TimerUpdateNTP2(void) @@ -128,262 +98,33 @@ void IRAM_ATTR TimerUpdateNTP2(void) updateNtpTime = true; } -String get_name_of_day(int m, int d) -{ - for (int i = 0; i < sizeof(cal_names) / sizeof(cal_names[0]); i++) - { - if (cal_names[i].m == m && cal_names[i].d == d) - return String(cal_names[i].name); - } - return String("Sviatok"); -} - -String get_weather_line() -{ - client.begin("http://api.openweathermap.org/data/2.5/weather?q=Trnava,sk&lang=sk&APPID=d15c61931a053026e98769dd9fc46ba3"); - int code = client.GET(); - if (code > 0) - { - - if (code == HTTP_CODE_OK) - { - float temp; - String w; - String desc; - - String payload = client.getString(); - deserializeJson(doc, payload); - JsonObject obj = doc.as(); - temp = obj["main"]["temp"].as(); - w = obj["weather"][0]["main"].as(); - desc = obj["weather"][0]["description"].as(); - temp -= 273.15; - return String(temp) + String("C ") + Ascifii::ToAscii(desc); - } - } - - return "Error"; -} - -String get_time_line() -{ - return String(ntp.formattedTime("%H:%M")); -} - -String get_date_line() -{ - return String(ntp.formattedTime("%d.%m")); -} - -String get_names_line() -{ - int d = DateTime.month(); - int m = DateTime.day(); - m++; - return get_name_of_day(m, d); -} - -void calculate_timers() -{ - timer_def *t; - int timer = -1; - struct tm tm; - time_t alarm; - TimeZone TZ,NextAlarm; - - Serial.println("---CALC TIMERS---"); - TZ = DateTime; - - for (int i=0; im; - tm.tm_hour = t->h; - - if (t->d !=0) { - tm.tm_mday = t->d; - tm.tm_mon = t->mh - 1; - tm.tm_year = t->y - 1900; - } else { - tm.tm_mday = 0; - tm.tm_mon = 0; - tm.tm_year = 0; - } - - if (t->d == 0) { - if (t->when == WORK_DAYS) { - int offset=24*3600; - int wday; - - tm.tm_mday = DateTime.day(); - tm.tm_mon = DateTime.month() - 1; - tm.tm_year = DateTime.year() - 1900; - wday = DateTime.weekDay(); - - if (wday == 0) offset = 3600*24; - if (wday == 6) offset = 2*3600*24; - - alarm = mktime(&tm); - TZ.setLocalTime(alarm); - - if (TZ.epoch() < DateTime.epoch() && wday == 5 ) offset = 3*3600*24; - if (TZ.epoch() > DateTime.epoch() && (wday >=1 && wday <=5)) offset=0; - - TZ += offset; - - } else if (t->when == WEEKENDS) { - int offset=24*3600; - int wday; - - tm.tm_mday = DateTime.day(); - tm.tm_mon = DateTime.month() - 1; - tm.tm_year = DateTime.year() - 1900; - wday = DateTime.weekDay(); - - if (wday >= 1 && wday <= 5) offset = (7-wday) *3600*24; - - alarm = mktime(&tm); - TZ.setLocalTime(alarm); - - if (TZ.epoch() > DateTime.epoch() && (wday == 6 || wday == 0 )) offset = 0; - - TZ += offset; - - } else if (t->when == ONCE ) { - alarm = mktime(&tm); - TZ.setLocalTime(alarm); - } - - if (TZ.epoch() > DateTime.epoch() && (TZ.epoch() < NextAlarm.epoch() || timer == -1)) { - Serial.println("TZ:" + TZ.toString()); - timer = i; - NextAlarm = TZ; - } - } - - } - - if (timer != -1) { - nextTimer = timer; - nextAlarmDateTime = NextAlarm; - Serial.println(DateTime.toString()); - Serial.println(nextAlarmDateTime.toString()); - } -} - -void read_config() -{ - File file = SPIFFS.open("/settings.json", "r"); - if (!file) - { - Serial.println("Failed to open settings file for reading"); - return; - } - - Serial.println("====File Content SETTINGS===="); - String s; - while (file.available()) - { - s += (char)file.read(); - } - Serial.println(s); - - file.close(); - - ntimers = 0; - settings = s; - Serial.println("SETTINGS: " + settings); - - deserializeJson(doc, settings); - JsonObject obj = doc.as(); - for (int i=0;i < obj["data"].size(); i++) { - int t = obj["data"][i]["kedy"].as(); - String c = obj["data"][i]["cas"].as(); - String datum = obj["data"][i]["datum"].as(); - - StringSplitter *splitter = new StringSplitter(c, ':', 2); - - int h = splitter->getItemAtIndex(0).toInt(); - int m = splitter->getItemAtIndex(1).toInt(); - int d = 0; - int mh = 0; - int y = 0; - - Serial.println(t); - Serial.println(c); - Serial.println(datum); - - if (datum != NULL) { - StringSplitter *splitter = new StringSplitter(datum, '.', 3); - - d = splitter->getItemAtIndex(0).toInt(); - mh = splitter->getItemAtIndex(1).toInt(); - y = splitter->getItemAtIndex(2).toInt(); - } - - Timers[ntimers].when = t; - Timers[ntimers].h = h; - Timers[ntimers].m = m; - Timers[ntimers].d = d; - Timers[ntimers].mh = mh; - Timers[ntimers].y = y; - - ntimers++; - } -} - - void setup_matrix() { - matrix = new Adafruit_NeoMatrix(32, 8, PIN, - NEO_MATRIX_BOTTOM + NEO_MATRIX_RIGHT + - NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG, - NEO_GBR + NEO_KHZ800); + matrix = new FastLED_NeoMatrix(matrixleds, lcdw, lcdh, 1, 1, + NEO_MATRIX_BOTTOM + NEO_MATRIX_RIGHT + NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG ); + FastLED.addLeds(matrixleds, NUMMATRIX); matrix->begin(); matrix->setTextWrap(false); - matrix->setBrightness(1); + matrix->setBrightness(20); matrix->setTextColor(colors[1]); + matrix->print("Start"); + matrix->show(); + delay(1000); + matrix->fillScreen(0); + matrix->print(""); + matrix->show(); } void returnOK() { server.send(200, "text/plain", ""); } -void handleSave() { - String data; - - Serial.println(server.uri()); - Serial.println(server.method()); - Serial.println(server.argName(0)); - Serial.println(server.arg(0)); - if (server.uri() != "/settings" && server.method() != HTTP_POST) { - return; - } - - data = server.arg(0); - - Serial.println("Data:" + data); - - File file = SPIFFS.open("/settings.json", "w"); - if (!file) - { - Serial.println("Failed to open file for writing"); - return; - } - - settings = data; - file.print(data.c_str()); - file.close(); - - server.send(200, "text/plain", ""); - read_config(); - calculate_timers(); +void wifiConnected() +{ + needMqttConnect = true; } - void setup() { Serial.begin(115200); @@ -392,26 +133,16 @@ void setup() //iotWebConf.setStatusPin(PIN); + iotWebConf.addParameter(&mqttServerParam); + iotWebConf.setWifiConnectionCallback(&wifiConnected); iotWebConf.init(); - if (!SPIFFS.begin(true)) - { - Serial.println("An Error has occurred while mounting SPIFFS"); - - return; - } - - if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerCheckTime0)) - Serial.println("Starting ITimer0 OK, millis() = " + String(millis())); - else - Serial.println("Can't set ITimer0. Select another freq. or timer"); - - // Interval in microsecs - if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerScrollTime1)) + if (ITimer1.attachInterruptInterval(SCROLLER_TICK_TIME * 1000, TimerScrollTime1)) Serial.println("Starting ITimer1 OK, millis() = " + String(millis())); else Serial.println("Can't set ITimer1. Select another freq. or timer"); + if (ITimer2.attachInterruptInterval(TIMER2_INTERVAL_MS * 1000, TimerUpdateNTP2)) Serial.println("Starting ITimer2 OK, millis() = " + String(millis())); else @@ -421,14 +152,13 @@ void setup() // -- Set up required URL handlers on the web server. server.on("/", handleRoot); server.on("/config", [] { iotWebConf.handleConfig(); }); - server.on("/settings", HTTP_POST, handleSave); server.onNotFound([]() { iotWebConf.handleNotFound(); }); setup_matrix(); - read_config(); scroller.SetColors(colors); scroller.SetMatrix(matrix); + } void handleRoot() @@ -440,79 +170,140 @@ void handleRoot() return; } - File file = SPIFFS.open("/index.html", "r"); - if (!file) + server.send(200, "text/html", "OK"); +} + +boolean reconnect() { + unsigned long now = millis(); + if (1000 > now - lastMqttConnectionAttempt) { - Serial.println("Failed to open file for reading"); - return; + // Do not repeat within 1 sec. + return false; } - - Serial.println("====File Content===="); - String s; - while (file.available()) - { - s += (char)file.read(); + // Loop until we're reconnected + Serial.print("Attempting MQTT connection..."); + // Create a random client ID + String clientId = "ESP32Client-SCROLLER"; + // Attempt to connect + if (client.connect(clientId.c_str())) { + Serial.println("connected"); + // Once connected, publish an announcement... + client.subscribe("home/scroller"); + return true; + } else { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" try again in 1 seconds"); + // Wait 5 seconds before retrying + lastMqttConnectionAttempt = now; + return false; } - s.replace("%%SETTINGS%%",settings); - Serial.print(s); +} - file.close(); - server.send(200, "text/html", s); +void decode_payload(String msg) +{ + StringSplitter *splitter = new StringSplitter(msg, ';', 2); + int n = 0; + int i = 0; + String s,m; + int color=1,brightness=10,speed=200, off=2000,on=2000; + + if (splitter->getItemCount() == 2) + s = splitter->getItemAtIndex(n++); + m = splitter->getItemAtIndex(n++); + + if (n == 2) { + StringSplitter *splitter = new StringSplitter(s, ':', 10); + String cmd,param; + while (i < splitter->getItemCount()) { + cmd = splitter->getItemAtIndex(i++); + param = splitter->getItemAtIndex(i++); + Serial.printf("cmd=%s,param=%s\n",cmd,param); + if (cmd == "c") color = param.toInt(); + if (cmd == "b") brightness = param.toInt(); + if (cmd == "s") speed = param.toInt(); + if (cmd == "off") off = param.toInt(); + if (cmd == "on") on = param.toInt(); + } + } + + i = scroller.AddLine(m); + if (n == 2) { + Serial.printf("color=%d,brightness=%d,off=%d,on=%d,speed=%d\n",color,brightness,off,on,speed); + scroller.SetParameters(i,color,brightness,off,on,speed); + } +} + +void callback(char* topic, byte* payload, unsigned int length) { + char msg[128]; + + Serial.print("Message arrived ["); + Serial.print(topic); + Serial.print("] "); + for (int i = 0; i < length; i++) { + Serial.print((char)payload[i]); + } + Serial.println(); + + strncpy(msg,(char *)payload,length); + msg[length] = '\0'; + + // Switch on the LED if an 1 was received as first character + scroller.TurnOff(); + scroller.DeleteLines(); + decode_payload(msg); + showTextMqtt = true; } void loop() { - unsigned long n = 0; - - // -- doLoop should be called as frequently as possible. - - if (WiFi.status() == WL_CONNECTED) - { - if (initialized == false) - { - Serial.println("---INIT---"); - - ntp.ruleDST("CEST", Last, Sun, Mar, 2, 120); // last sunday in march 2:00, timetone +120min (+1 GMT + 1h summertime offset) - ntp.ruleSTD("CET", Last, Sun, Oct, 3, 60); // last sunday in october 3:00, timezone +60min (+1 GMT) - ntp.begin(); - unsigned long sec = ntp.epoch(); - DateTime.setUTCTime(sec); - nextAlarmDateTime = DateTime; - - initialized = true; - } - - if (updateNtpTime) { - Serial.println("---NTP UPDATE---"); - - ntp.update(); - unsigned long sec = ntp.epoch(); - DateTime.setUTCTime(sec); - last_millis = millis(); - calculate_timers(); - updateNtpTime = false; - - - if (n++ % 10 == 0) - Lines[WEATHER_LINE] = get_weather_line(); - - Lines[TIME_LINE] = get_time_line(); - Lines[DATE_LINE] = get_date_line(); - Lines[NAMES_LINE] = get_names_line(); - - scroller.AddLines(Lines,LAST_LINE); - scroller.PrintSerialLines(); - - } - - if (showText) { - Serial.println("---SHOW TEXT----"); - scroller.loop(scrolledTicker); - - if (scroller.TimesScrolled() > MAX_TIMES_SCROLLED) showText = false; - } - } - iotWebConf.doLoop(); -} \ No newline at end of file + + if (needMqttConnect) + { + Serial.println("---INIT---"); + + ntp.ruleDST("CEST", Last, Sun, Mar, 2, 120); // last sunday in march 2:00, timetone +120min (+1 GMT + 1h summertime offset) + ntp.ruleSTD("CET", Last, Sun, Oct, 3, 60); // last sunday in october 3:00, timezone +60min (+1 GMT) + ntp.begin(); + unsigned long sec = ntp.epoch(); + DateTime.setUTCTime(sec); + client.setServer(mqttServerValue, 1883); + client.setCallback(callback); + + if (reconnect()) + { + needMqttConnect = false; + } + + } + else if ((iotWebConf.getState() == IOTWEBCONF_STATE_ONLINE) && (!client.connected())) + { + Serial.println("MQTT reconnect"); + client.setServer(mqttServerValue, 1883); + client.setCallback(callback); + reconnect(); + } + + if (iotWebConf.getState() == IOTWEBCONF_STATE_ONLINE) { + if (updateNtpTime) { + Serial.println("---NTP UPDATE---"); + + ntp.update(); + unsigned long sec = ntp.epoch(); + DateTime.setUTCTime(sec); + last_millis = millis(); + updateNtpTime = false; + } + + if (showTextMqtt) { + scroller.TurnOn(); + showTextMqtt = false; + } + + scroller.loop(tick); + client.loop(); + } +} +