diff --git a/include/CaptiveRequestHandler.h b/include/CaptiveRequestHandler.h new file mode 100644 index 00000000..97c74370 --- /dev/null +++ b/include/CaptiveRequestHandler.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +class CaptiveRequestHandler : public AsyncWebHandler { + public: + CaptiveRequestHandler(const char *host); + + virtual ~CaptiveRequestHandler(); + + bool canHandle(AsyncWebServerRequest *request) override; + + void handleRequest(AsyncWebServerRequest *request) override; + + private: + bool isLocalIp(String name); + bool isLocalName(String name); + + private: + char _local_name[32]; + IPAddress _local_ip; +}; diff --git a/include/CommonTypes.h b/include/CommonTypes.h index e0beebba..7ad65e65 100644 --- a/include/CommonTypes.h +++ b/include/CommonTypes.h @@ -1,5 +1,24 @@ #pragma once +enum TimerTask_t { WIFI_SCAN, + WIFI_MQTT_CONNECTION_CHECK, + SENSORS, + STEPPER1, + STEPPER2, + LOG1, + LOG2, + LOG3, + LOG4, + LOG5, + TIMER_COUNTDOWN, + TIME, + TIME_SYNC, + STATISTICS, + UPTIME, + UDP, + UDP_DB, + TEST }; + enum ErrorType_t { ET_NONE, ET_FUNCTION, diff --git a/include/Global.h b/include/Global.h index fec124c4..da313a07 100644 --- a/include/Global.h +++ b/include/Global.h @@ -16,6 +16,7 @@ #include "UptimeInterval.h" #include "Clock.h" +#include "MqttClient.h" #include "Utils\FileUtils.h" #include "Utils\JsonUtils.h" #include "Utils\StringUtils.h" @@ -63,31 +64,13 @@ extern AsyncWebServer server; extern DallasTemperature sensors; extern boolean but[NUM_BUTTONS]; + extern Bounce* buttons; /* * Global vars */ -enum { WIFI_SCAN, - WIFI_MQTT_CONNECTION_CHECK, - SENSORS, - STEPPER1, - STEPPER2, - LOG1, - LOG2, - LOG3, - LOG4, - LOG5, - TIMER_COUNTDOWN, - TIME, - TIME_SYNC, - STATISTICS, - UPTIME, - UDP, - UDP_DB, - TEST }; - extern boolean just_load; extern String configSetupJson; //все настройки @@ -199,18 +182,6 @@ extern void servo_(); extern void setLedStatus(LedStatus_t); -// Mqtt -extern void initMQTT(); -extern void loopMQTT(); -extern boolean connectMQTT(); - -extern boolean publishData(const String& topic, const String& data); -extern boolean publishChart(const String& topic, const String& data); -extern boolean publishStatus(const String& topic, const String& state); -extern boolean publishControl(String id, String topic, String state); - -extern void reconnectMQTT(); - //Scenario extern void eventGen(String event_name, String number); extern String add_set(String param_name); diff --git a/include/Module/Terminal.h b/include/Module/Terminal.h index 859f227d..11c5232e 100644 --- a/include/Module/Terminal.h +++ b/include/Module/Terminal.h @@ -152,12 +152,12 @@ class Terminal : public Print { uint8_t curY = 0xff; uint8_t curX = 0xff; - unsigned long lastReceived = 0; + unsigned long _lastReceived = 0; State state = ST_INACTIVE; Stream *_stream; EditLine _line; - char cc_buf[32] = {0}; - size_t cc_pos = 0; + char _cc_buf[32] = {0}; + size_t _cc_pos = 0; bool _color = false; bool _controlCodes = false; bool _echo = false; diff --git a/include/MqttClient.h b/include/MqttClient.h new file mode 100644 index 00000000..74977ef6 --- /dev/null +++ b/include/MqttClient.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +namespace MqttClient { + +void init(); +boolean connect(); +void reconnect(); +void loop(); + +void subscribe(); + +boolean publish(const String& topic, const String& data); +boolean publishData(const String& topic, const String& data); +boolean publishChart(const String& topic, const String& data); +boolean publishControl(String id, String topic, String state); +boolean publishChart_test(const String& topic, const String& data); +boolean publishStatus(const String& topic, const String& data); + +void publishWidgets(); +void publishState(); + +void handleSubscribedUpdates(char* topic, uint8_t* payload, size_t length); +const String getStateStr(); + +} // namespace MqttClient diff --git a/include/Utils/TimeUtils.h b/include/Utils/TimeUtils.h index f5af3064..82337b34 100644 --- a/include/Utils/TimeUtils.h +++ b/include/Utils/TimeUtils.h @@ -39,4 +39,14 @@ int timeZoneInSeconds(const byte timeZone); bool hasTimeSynced(); -int getBiasInSeconds(); \ No newline at end of file +int getBiasInSeconds(); + +/* +* Время (мс) прошедщее с @simce +*/ +unsigned long millis_since(unsigned long sinse); + +/* +* Интерввал времени (мс) между @start и @fimish +*/ +unsigned long millis_passed(unsigned long start, unsigned long finish); \ No newline at end of file diff --git a/src/CaptiveRequestHandler.cpp b/src/CaptiveRequestHandler.cpp new file mode 100644 index 00000000..111021fb --- /dev/null +++ b/src/CaptiveRequestHandler.cpp @@ -0,0 +1,33 @@ +#include "CaptiveRequestHandler.h" + +CaptiveRequestHandler::CaptiveRequestHandler(const char *host) { + strlcpy(_local_name, host, sizeof(_local_name)); + strcat(_local_name, ".local"); +} + +CaptiveRequestHandler::~CaptiveRequestHandler() { +} + +bool CaptiveRequestHandler::isLocalIp(String address) { + IPAddress ip; + return !ip.fromString(address) || (ip != _local_ip); +} + +bool CaptiveRequestHandler::isLocalName(String host_name) { + return host_name.equalsIgnoreCase(_local_name); +} + +bool CaptiveRequestHandler::canHandle(AsyncWebServerRequest *request) { + _local_ip = request->client()->localIP(); + + return !isLocalIp(request->getHeader("HOST")->value()) && !isLocalName(request->getHeader("HOST")->value()); +} + +void CaptiveRequestHandler::CaptiveRequestHandler::handleRequest(AsyncWebServerRequest *request) { + char buf[64]; + sprintf(buf, "http://%s%s", _local_name, request->url().c_str()); + auto response = request->beginResponse(302, "text/html"); + response->addHeader("Location", buf); + response->addHeader("Connection", "close"); + request->send(response); +}; diff --git a/src/Cmd.cpp b/src/Cmd.cpp index a86012fc..377eae5a 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -167,7 +167,7 @@ void buttonSet() { jsonWriteStr(configLiveJson, "button" + button_number, button_state); - publishStatus("button" + button_number, button_state); + MqttClient::publishStatus("button" + button_number, button_state); } void buttonChange() { @@ -181,7 +181,7 @@ void buttonChange() { } order_loop += "buttonSet " + button_number + " " + current_state + ","; jsonWriteStr(configLiveJson, "button" + button_number, current_state); - publishStatus("button" + button_number, current_state); + MqttClient::publishStatus("button" + button_number, current_state); } void pinSet() { @@ -230,7 +230,7 @@ void pwmSet() { jsonWriteStr(configLiveJson, "pwm" + pwm_number, pwm_state); - publishStatus("pwm" + pwm_number, pwm_state); + MqttClient::publishStatus("pwm" + pwm_number, pwm_state); } //================================================================================================================== //==========================================Модуль физической кнопки================================================ @@ -285,7 +285,7 @@ void digitSet() { String number = sCmd.next(); String value = sCmd.next(); jsonWriteStr(configLiveJson, "digit" + number, value); - publishStatus("digit" + number, value); + MqttClient::publishStatus("digit" + number, value); } //===================================================================================================================================== @@ -307,7 +307,7 @@ void timeSet() { String number = sCmd.next(); String value = sCmd.next(); jsonWriteStr(configLiveJson, "time" + number, value); - publishStatus("time" + number, value); + MqttClient::publishStatus("time" + number, value); } void handle_time_init() { @@ -347,7 +347,7 @@ void textSet() { } jsonWriteStr(configLiveJson, "text" + number, text); - publishStatus("text" + number, text); + MqttClient::publishStatus("text" + number, text); } //===================================================================================================================================== //=========================================Модуль шагового мотора====================================================================== @@ -503,7 +503,7 @@ void servoSet() { jsonWriteStr(configLiveJson, "servo" + servo_number, servo_state); - publishStatus("servo" + servo_number, servo_state); + MqttClient::publishStatus("servo" + servo_number, servo_state); } #endif diff --git a/src/Logging.cpp b/src/Logging.cpp index 5fb898b9..c6c40454 100644 --- a/src/Logging.cpp +++ b/src/Logging.cpp @@ -134,7 +134,8 @@ void sendLogData(String file, String topic) { log_date = ""; json_array = "{\"status\":[" + json_array + "]}"; Serial.println(json_array); - publishChart(topic, json_array); + + MqttClient::publishChart(topic, json_array); json_array = ""; printMemoryStatus("[I] send log date"); } diff --git a/src/Module/Terminal.cpp b/src/Module/Terminal.cpp new file mode 100644 index 00000000..17d96b91 --- /dev/null +++ b/src/Module/Terminal.cpp @@ -0,0 +1,322 @@ +#include "Module/Terminal.h" + +#include "Utils/TimeUtils.h" + +#define INPUT_MAX_LENGHT 255 + +Terminal::Terminal(Stream *stream) : _stream{stream}, + _line(INPUT_MAX_LENGHT), + _cc_pos(0), + _color(false), + _controlCodes(false), + _echo(false), + _eol(CRLF){}; + +void Terminal::setStream(Stream *stream) { + _stream = stream; +} + +Terminal::~Terminal() {} + +void Terminal::setOnReadLine(TerminalInputEventHandler h) { inputHandler_ = h; } + +void Terminal::setOnEvent(TerminalEventHandler h) { eventHandler_ = h; } + +bool Terminal::available() { + return _stream != nullptr ? _stream->available() : false; +} + +void Terminal::setEOL(EOLType_t eol) { + _eol = eol; +} + +void Terminal::enableEcho(bool enabled) { + _echo = enabled; +} + +void Terminal::enableColors(bool enabled) { + _color = enabled; +} + +void Terminal::enableControlCodes(bool enabled) { + _controlCodes = enabled; +} + +void Terminal::quit() {} + +void Terminal::loop() { + if (_stream == nullptr || !_stream->available()) return; + + sint8_t moveX = 0; + sint8_t moveY = 0; + + char c = _stream->read(); + + _lastReceived = millis(); + + if (state == ST_INACTIVE) { + // wait for CR + if (c == CHAR_CR) { + if (eventHandler_) { + eventHandler_(EVENT_OPEN, _stream); + state = ST_NORMAL; + } + } + // or ignore all other + return; + } + + if (c == CHAR_LF || c == CHAR_NULL || c == CHAR_BIN) + return; + + // Esc + if (c == CHAR_ESC || c == 195) { + state = ST_ESC_SEQ; + _cc_pos = 0; + for (size_t i = 0; i < 2; ++i) { + bool timeout = false; + while (!_stream->available() && + !(timeout = millis_since(_lastReceived) > 10)) { + delay(0); + } + if (timeout) { + state = ST_NORMAL; + break; + } + _lastReceived = millis(); + c = _stream->read(); + _cc_buf[_cc_pos] = c; + if ((c == '[') || ((c >= 'A' && c <= 'Z') || c == '~')) { + _cc_pos++; + _cc_buf[++_cc_pos] = '\x00'; + } + } + uint8_t i; + for (i = 0; i < 10; ++i) { + if (strcmp(_cc_buf, keyMap[i].cc) == 0) { + c = keyMap[i].ch; + state = ST_NORMAL; + } + } + } + + if (state == ST_ESC_SEQ) { + state = ST_NORMAL; + return; + } + + // WHEN NORMAL + if (state == ST_NORMAL) { + if (c == CHAR_ESC) { + if (!_line.available()) { + // QUIT + state = ST_INACTIVE; + if (eventHandler_) + eventHandler_(EVENT_CLOSE, _stream); + } else { + // CLEAR + _line.clear(); + if (_controlCodes) { + clear_line(); + } else { + println(); + } + } + return; + } + + switch (c) { + case CHAR_CR: + println(); + if (inputHandler_) + inputHandler_(_line.c_str()); + _line.clear(); + moveY++; + break; + case CHAR_TAB: + if (eventHandler_) + eventHandler_(EVENT_TAB, _stream); + return; + case KEY_LEFT: + if (_line.prev()) + moveX--; + break; + case KEY_RIGHT: + if (_line.next()) + moveX++; + break; + case KEY_HOME: + moveX = -1 * _line.home(); + break; + case KEY_END: + moveX = _line.end(); + break; + case CHAR_BS: + case KEY_DEL: + if (_line.backspace()) { + backsp(); + moveX--; + } + break; + default: + // printable ascii 7bit or printable 8bit ISO8859 + if ((c & '\x7F') >= 32 && (c & '\x7F') < 127) + if (_line.write(c)) { + if (_echo) write(c); + moveX++; + } + break; + } + + // if (controlCodesEnabled) + // move(startY + moveY, startX + moveX); + } +} + +bool Terminal::setLine(const uint8_t *ptr, size_t size) { + _line.clear(); + if (_line.write(ptr, size)) + print(_line.c_str()); + return true; +} + +CharBuffer &Terminal::getLine() { return _line; } + +void Terminal::start() { + if (_controlCodes) initscr(); + println(); +} + +void Terminal::initscr() { + write_P(SEQ_LOAD_G1); + attrset(A_NORMAL); + move(0, 0); + clear(); +} + +void Terminal::attrset(const uint16_t attr) { + uint8_t i; + + if (attr != this->attr) { + this->write_P(SEQ_ATTRSET); + + i = (attr & F_COLOR) >> 8; + + if (i >= 1 && i <= 8) { + this->write_P(SEQ_ATTRSET_FCOLOR); + this->write(i - 1 + '0'); + } + + i = (attr & B_COLOR) >> 12; + + if (i >= 1 && i <= 8) { + this->write_P(SEQ_ATTRSET_BCOLOR); + this->write(i - 1 + '0'); + } + + if (attr & A_REVERSE) + this->write_P(SEQ_ATTRSET_REVERSE); + if (attr & A_UNDERLINE) + this->write_P(SEQ_ATTRSET_UNDERLINE); + if (attr & A_BLINK) + this->write_P(SEQ_ATTRSET_BLINK); + if (attr & A_BOLD) + this->write_P(SEQ_ATTRSET_BOLD); + if (attr & A_DIM) + this->write_P(SEQ_ATTRSET_DIM); + this->write('m'); + this->attr = attr; + } +} + +void Terminal::clear() { write_P(SEQ_CLEAR); } + +void Terminal::clear_line() { + write(CHAR_CR); + write_P(ESC_CLEAR_EOL); +} + +void Terminal::move(uint8_t y, uint8_t x) { + write_P(SEQ_CSI); + writeByDigit(y + 1); + write(';'); + writeByDigit(x + 1); + write('H'); + curY = y; + curX = x; +} + +void Terminal::writeByDigit(uint8_t i) { + uint8_t ii; + if (i >= 10) { + if (i >= 100) { + ii = i / 100; + write(ii + '0'); + i -= 100 * ii; + } + ii = i / 10; + write(ii + '0'); + i -= 10 * ii; + } + write(i + '0'); +} + +void Terminal::backsp() { + write(CHAR_BS); + write(CHAR_SPACE); + write(CHAR_BS); +} + +size_t Terminal::println(const char *str) { + size_t n = print(str); + return n += println(); +} + +size_t Terminal::println(void) { + size_t n = 0; + switch (_eol) { + case CRLF: + n += write(CHAR_CR); + n += write(CHAR_LF); + break; + case LF: + n += write(CHAR_LF); + break; + case LFCR: + n += write(CHAR_LF); + n += write(CHAR_CR); + break; + case CR: + n += write(CHAR_CR); + break; + } + return n; +} + +size_t Terminal::write(uint8_t ch) { + size_t n = 0; + if (_stream) + n = _stream->write(ch); + return n; +} + +size_t Terminal::write_P(PGM_P str) { + uint8_t ch; + size_t n = 0; + while ((ch = pgm_read_byte(str + n)) != '\x0') { + _stream->write(ch); + n++; + } + return n; +} + +size_t Terminal::write(const uint8_t *buf, size_t size) { + size_t n = 0; + while (size--) { + if (_stream->write(*buf++)) + n++; + else + break; + } + return n; +} \ No newline at end of file diff --git a/src/Mqtt.cpp b/src/MqttClient.cpp similarity index 85% rename from src/Mqtt.cpp rename to src/MqttClient.cpp index d497a755..3d1bb95e 100644 --- a/src/Mqtt.cpp +++ b/src/MqttClient.cpp @@ -1,10 +1,11 @@ +#include "MqttClient.h" #include "Global.h" - -// #include static const char* MODULE = "Mqtt"; +namespace MqttClient { + // Errors int wifi_lost_error = 0; int mqtt_lost_error = 0; @@ -13,14 +14,7 @@ int mqtt_lost_error = 0; String mqttPrefix; String mqttRootDevice; -void handleSubscribedUpdates(char* topic, uint8_t* payload, size_t length); -const String getMqttStateStr(); -void sendAllData(); -void sendAllWigets(); -boolean publicStatus(String topic, String state); -void outcoming_date(); - -void initMQTT() { +void init() { mqtt.setCallback(handleSubscribedUpdates); ts.add( @@ -31,7 +25,7 @@ void initMQTT() { pm.info("OK"); setLedStatus(LED_OFF); } else { - connectMQTT(); + connect(); if (!just_load) mqtt_lost_error++; } } else { @@ -44,15 +38,17 @@ void initMQTT() { nullptr, true); } -void reconnectMQTT() { - if (mqttParamsChanged) { - mqtt.disconnect(); - connectMQTT(); - mqttParamsChanged = false; - } +void disconnect() { + pm.info("disconnect"); + mqtt.disconnect(); } -void loopMQTT() { +void reconnect() { + disconnect(); + connect(); +} + +void loop() { if (!isNetworkActive() || !mqtt.connected()) { return; } @@ -60,10 +56,7 @@ void loopMQTT() { } void subscribe() { - pm.info("Subscribe"); - // Для приема получения HELLOW и подтверждения связи - // Подписываемся на топики control - // Подписываемся на топики order + pm.info("subscribe"); mqtt.subscribe(mqttPrefix.c_str()); mqtt.subscribe((mqttRootDevice + "/+/control").c_str()); mqtt.subscribe((mqttRootDevice + "/order").c_str()); @@ -72,10 +65,11 @@ void subscribe() { mqtt.subscribe((mqttRootDevice + "/devs").c_str()); } -boolean connectMQTT() { +boolean connect() { if (!isNetworkActive()) { return false; } + pm.info("connect"); String addr = jsonReadStr(configSetupJson, "mqttServer"); if (!addr) { @@ -125,8 +119,8 @@ void handleSubscribedUpdates(char* topic, uint8_t* payload, size_t length) { if (payloadStr == "HELLO") { //данные которые отправляем при подключении или отбновлении страницы pm.info("Send web page updates"); - sendAllWigets(); - sendAllData(); + publishWidgets(); + publishState(); #ifdef LOGGING_ENABLED choose_log_date_and_send(); #endif @@ -193,9 +187,9 @@ boolean publishControl(String id, String topic, String state) { return mqtt.publish(path.c_str(), state.c_str(), false); } -boolean sendCHART_test(String topic, String data) { - topic = mqttRootDevice + "/" + topic + "/status"; - return mqtt.publish(topic.c_str(), data.c_str(), false); +boolean publishChart_test(const String& topic, const String& data) { + String path = mqttRootDevice + "/" + topic + "/status"; + return mqtt.publish(path.c_str(), data.c_str(), false); } boolean publishStatus(const String& topic, const String& data) { @@ -205,9 +199,8 @@ boolean publishStatus(const String& topic, const String& data) { return mqtt.publish(path.c_str(), json.c_str(), false); } -//=====================================================ОТПРАВЛЯЕМ ВИДЖЕТЫ======================================================== #ifdef LAYOUT_IN_RAM -void sendAllWigets() { +void publishWidgets() { if (all_widgets != "") { int counter = 0; String line; @@ -231,7 +224,7 @@ void sendAllWigets() { #endif #ifndef LAYOUT_IN_RAM -void sendAllWigets() { +void publishWidgets() { auto file = seekFile("/layout.txt"); if (!file) { return; @@ -245,9 +238,7 @@ void sendAllWigets() { } #endif -//=====================================================ОТПРАВЛЯЕМ ДАННЫЕ В ВИДЖЕТЫ ПРИ ОБНОВЛЕНИИ СТРАНИЦЫ======================================================== - -void sendAllData() { +void publishState() { // берет строку json и ключи превращает в топики а значения колючей в них посылает // {"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"} // "name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1" @@ -274,7 +265,7 @@ void sendAllData() { } } -const String getMqttStateStr() { +const String getStateStr() { switch (mqtt.state()) { case -4: return F("no respond"); @@ -311,3 +302,5 @@ const String getMqttStateStr() { break; } } + +} // namespace MqttClient \ No newline at end of file diff --git a/src/Sensors.cpp b/src/Sensors.cpp index e81f39a1..92c20f24 100644 --- a/src/Sensors.cpp +++ b/src/Sensors.cpp @@ -146,12 +146,16 @@ void ultrasonic_reading() { jsonWriteInt(configLiveJson, levelPr_value_name, level); eventGen(levelPr_value_name, ""); - publishStatus(levelPr_value_name, String(level)); + + MqttClient::publishStatus(levelPr_value_name, String(level)); + Serial.println("[I] sensor '" + levelPr_value_name + "' data: " + String(level)); jsonWriteInt(configLiveJson, ultrasonicCm_value_name, distance_cm); eventGen(ultrasonicCm_value_name, ""); - publishStatus(ultrasonicCm_value_name, String(distance_cm)); + + MqttClient::publishStatus(ultrasonicCm_value_name, String(distance_cm)); + Serial.println("[I] sensor '" + ultrasonicCm_value_name + "' data: " + String(distance_cm)); } } @@ -201,7 +205,7 @@ void analog_reading1() { jsonReadInt(configOptionJson, value_name + "_end_out")); jsonWriteInt(configLiveJson, value_name, analog); eventGen(value_name, ""); - publishStatus(value_name, String(analog)); + MqttClient::publishStatus(value_name, String(analog)); Serial.println("[I] sensor '" + value_name + "' data: " + String(analog)); } @@ -220,7 +224,7 @@ void analog_reading2() { jsonReadInt(configOptionJson, value_name + "_end_out")); jsonWriteInt(configLiveJson, value_name, analog); eventGen(value_name, ""); - publishStatus(value_name, String(analog)); + MqttClient::publishStatus(value_name, String(analog)); Serial.println("[I] sensor '" + value_name + "' data: " + String(analog)); } #endif @@ -249,7 +253,7 @@ void dallas_reading() { temp = sensors.getTempCByIndex(0); jsonWriteStr(configLiveJson, "dallas", String(temp)); eventGen("dallas", ""); - publishStatus("dallas", String(temp)); + MqttClient::publishStatus("dallas", String(temp)); Serial.println("[I] sensor 'dallas' send date " + String(temp)); } #endif @@ -280,7 +284,7 @@ void dhtT_reading() { float value = 0; static int counter; if (dht.getStatus() != 0 && counter < 5) { - publishStatus(dhtT_value_name, String(dht.getStatusString())); + MqttClient::publishStatus(dhtT_value_name, String(dht.getStatusString())); counter++; } else { counter = 0; @@ -288,7 +292,7 @@ void dhtT_reading() { if (String(value) != "nan") { eventGen(dhtT_value_name, ""); jsonWriteStr(configLiveJson, dhtT_value_name, String(value)); - publishStatus(dhtT_value_name, String(value)); + MqttClient::publishStatus(dhtT_value_name, String(value)); Serial.println("[I] sensor '" + dhtT_value_name + "' data: " + String(value)); } } @@ -318,7 +322,7 @@ void dhtH_reading() { float value = 0; static int counter; if (dht.getStatus() != 0 && counter < 5) { - publishStatus(dhtH_value_name, String(dht.getStatusString())); + MqttClient::publishStatus(dhtH_value_name, String(dht.getStatusString())); counter++; } else { counter = 0; @@ -326,7 +330,7 @@ void dhtH_reading() { if (String(value) != "nan") { eventGen(dhtH_value_name, ""); jsonWriteStr(configLiveJson, dhtH_value_name, String(value)); - publishStatus(dhtH_value_name, String(value)); + MqttClient::publishStatus(dhtH_value_name, String(value)); Serial.println("[I] sensor '" + dhtH_value_name + "' data: " + String(value)); } } @@ -344,13 +348,13 @@ void dhtP() { void dhtP_reading() { byte value; if (dht.getStatus() != 0) { - publishStatus("dhtPerception", String(dht.getStatusString())); + MqttClient::publishStatus("dhtPerception", String(dht.getStatusString())); } else { value = dht.computePerception(jsonReadStr(configLiveJson, dhtT_value_name).toFloat(), jsonReadStr(configLiveJson, dhtH_value_name).toFloat(), false); String final_line = perception(value); jsonWriteStr(configLiveJson, "dhtPerception", final_line); eventGen("dhtPerception", ""); - publishStatus("dhtPerception", final_line); + MqttClient::publishStatus("dhtPerception", final_line); if (mqtt.connected()) { Serial.println("[I] sensor 'dhtPerception' data: " + final_line); } @@ -402,13 +406,13 @@ void dhtC() { void dhtC_reading() { ComfortState cf; if (dht.getStatus() != 0) { - publishStatus("dhtComfort", String(dht.getStatusString())); + MqttClient::publishStatus("dhtComfort", String(dht.getStatusString())); } else { dht.getComfortRatio(cf, jsonReadStr(configLiveJson, dhtT_value_name).toFloat(), jsonReadStr(configLiveJson, dhtH_value_name).toFloat(), false); String final_line = get_comfort_status(cf); jsonWriteStr(configLiveJson, "dhtComfort", final_line); eventGen("dhtComfort", ""); - publishStatus("dhtComfort", final_line); + MqttClient::publishStatus("dhtComfort", final_line); Serial.println("[I] sensor 'dhtComfort' send date " + final_line); } } @@ -462,12 +466,12 @@ void dhtD() { void dhtD_reading() { float value; if (dht.getStatus() != 0) { - publishStatus("dhtDewpoint", String(dht.getStatusString())); + MqttClient::publishStatus("dhtDewpoint", String(dht.getStatusString())); } else { value = dht.computeDewPoint(jsonReadStr(configLiveJson, dhtT_value_name).toFloat(), jsonReadStr(configLiveJson, dhtH_value_name).toFloat(), false); jsonWriteInt(configLiveJson, "dhtDewpoint", value); eventGen("dhtDewpoint", ""); - publishStatus("dhtDewpoint", String(value)); + MqttClient::publishStatus("dhtDewpoint", String(value)); Serial.println("[I] sensor 'dhtDewpoint' data: " + String(value)); } } @@ -503,7 +507,7 @@ void bmp280T_reading() { value = temp_event.temperature; jsonWriteStr(configLiveJson, bmp280T_value_name, String(value)); eventGen(bmp280T_value_name, ""); - publishStatus(bmp280T_value_name, String(value)); + MqttClient::publishStatus(bmp280T_value_name, String(value)); Serial.println("[I] sensor '" + bmp280T_value_name + "' data: " + String(value)); } @@ -535,7 +539,7 @@ void bmp280P_reading() { value = value / 1.333224; jsonWriteStr(configLiveJson, bmp280P_value_name, String(value)); eventGen(bmp280P_value_name, ""); - publishStatus(bmp280P_value_name, String(value)); + MqttClient::publishStatus(bmp280P_value_name, String(value)); Serial.println("[I] sensor '" + bmp280P_value_name + "' data: " + String(value)); } @@ -560,7 +564,7 @@ void bme280T_reading() { value = bme.readTemperature(); jsonWriteStr(configLiveJson, bme280T_value_name, String(value)); eventGen(bme280T_value_name, ""); - publishStatus(bme280T_value_name, String(value)); + MqttClient::publishStatus(bme280T_value_name, String(value)); Serial.println("[I] sensor '" + bme280T_value_name + "' data: " + String(value)); } @@ -584,7 +588,7 @@ void bme280P_reading() { value = value / 1.333224; jsonWriteStr(configLiveJson, bme280P_value_name, String(value)); eventGen(bme280P_value_name, ""); - publishStatus(bme280P_value_name, String(value)); + MqttClient::publishStatus(bme280P_value_name, String(value)); Serial.println("[I] sensor '" + bme280P_value_name + "' data: " + String(value)); } @@ -607,7 +611,7 @@ void bme280H_reading() { value = bme.readHumidity(); jsonWriteStr(configLiveJson, bme280H_value_name, String(value)); eventGen(bme280H_value_name, ""); - publishStatus(bme280H_value_name, String(value)); + MqttClient::publishStatus(bme280H_value_name, String(value)); Serial.println("[I] sensor '" + bme280H_value_name + "' data: " + String(value)); } @@ -631,7 +635,7 @@ void bme280A_reading() { eventGen(bme280A_value_name, ""); - publishStatus(bme280A_value_name, String(value)); + MqttClient::publishStatus(bme280A_value_name, String(value)); Serial.println("[I] sensor '" + bme280A_value_name + "' data: " + String(value)); } diff --git a/src/Utils/TimeUtils.cpp b/src/Utils/TimeUtils.cpp index b52d9cd9..72eb4c9b 100644 --- a/src/Utils/TimeUtils.cpp +++ b/src/Utils/TimeUtils.cpp @@ -268,4 +268,30 @@ int timeZoneInSeconds(const byte timeZone) { break; } return res; -} \ No newline at end of file +} + +unsigned long millis_since(unsigned long sinse) { + return millis_passed(sinse, millis()); +} + +unsigned long millis_passed(unsigned long start, unsigned long finish) { + unsigned long result = 0; + if (start <= finish) { + unsigned long passed = finish - start; + if (passed <= __LONG_MAX__) { + result = static_cast(passed); + } else { + result = static_cast((__LONG_MAX__ - finish) + start + 1u); + } + } else { + unsigned long passed = start - finish; + if (passed <= __LONG_MAX__) { + result = static_cast(passed); + result = -1 * result; + } else { + result = static_cast((__LONG_MAX__ - start) + finish + 1u); + result = -1 * result; + } + } + return result; +} diff --git a/src/Utils/WiFiUtils.cpp b/src/Utils/WiFiUtils.cpp index 1d5dd506..e1727379 100644 --- a/src/Utils/WiFiUtils.cpp +++ b/src/Utils/WiFiUtils.cpp @@ -43,8 +43,9 @@ void startSTAMode() { } } while (keepConnecting && tries--); - if (WiFi.status() == WL_CONNECTED) { - initMQTT(); + if (isNetworkActive()) { + MqttClient::init(); + setLedStatus(LED_OFF); } else { startAPMode(); diff --git a/src/Web.cpp b/src/Web.cpp index f47dc71e..5f940a7d 100644 --- a/src/Web.cpp +++ b/src/Web.cpp @@ -1,5 +1,6 @@ #include "Global.h" +#include "CaptiveRequestHandler.h" #include "Utils/PresetUtils.h" static const char* MODULE = "Web"; @@ -7,10 +8,6 @@ static const char* MODULE = "Web"; static const uint8_t MIN_PRESET = 1; static const uint8_t MAX_PRESET = 21; -String getMqttStateStr(); - -const Item_t getPresetItem(uint8_t preset); - bool parseRequestForPreset(AsyncWebServerRequest* request, uint8_t& preset) { if (request->hasArg("preset")) { preset = request->getParam("preset")->value().toInt(); @@ -20,6 +17,8 @@ bool parseRequestForPreset(AsyncWebServerRequest* request, uint8_t& preset) { } void web_init() { + // server.addHandler(new CaptiveRequestHandler(jsonReadStr(configSetupJson, "name").c_str())).setFilter(ON_AP_FILTER); + server.on("/set", HTTP_GET, [](AsyncWebServerRequest* request) { uint8_t preset; if (parseRequestForPreset(request, preset)) { @@ -203,7 +202,7 @@ void web_init() { if (request->hasArg("mqttcheck")) { String buf = "{}"; - String payload = "" + getMqttStateStr(); + String payload = "" + MqttClient::getStateStr(); jsonWriteStr(buf, "title", payload); jsonWriteStr(buf, "class", "pop-up"); diff --git a/src/main.cpp b/src/main.cpp index 6fadabd2..a2d77deb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -85,7 +85,8 @@ void loop() { not_async_actions(); - loopMQTT(); + MqttClient::loop(); + loopCmd(); loopButton(); loopScenario(); @@ -96,7 +97,10 @@ void loop() { } void not_async_actions() { - reconnectMQTT(); + if (mqttParamsChanged) { + MqttClient::reconnect(); + mqttParamsChanged = false; + } do_upgrade_url(); do_upgrade();