From 274678f17a618ec8da2c0d74f7670b526794c4c0 Mon Sep 17 00:00:00 2001 From: Yuri Trikoz Date: Mon, 22 Jun 2020 14:01:12 +0300 Subject: [PATCH] Updates --- .../{17-moution.c.txt => 17-motion.c.txt} | 0 .../{17-moution.s.txt => 17-motion.s.txt} | 0 .../{18-moution.c.txt => 18-motion.c.txt} | 0 .../{18-moution.s.txt => 18-motion.s.txt} | 0 include/CommonTypes.h | 23 ++ include/Global.h | 23 +- include/Utils/FileUtils.h | 4 +- include/Utils/WiFiUtils.h | 4 +- src/Cmd.cpp | 2 +- src/Global.cpp | 9 +- src/Logging.cpp | 2 +- src/Mqtt.cpp | 290 +++++++++--------- src/Scenario.cpp | 155 +++++----- src/Sensors.cpp | 2 +- src/Utils/FileUtils.cpp | 26 ++ src/Utils/StringUtils.cpp | 25 +- src/Utils/WiFiUtils.cpp | 8 +- src/Web.cpp | 200 ++++++------ src/main.cpp | 13 +- src/udp.cpp | 2 +- 20 files changed, 429 insertions(+), 359 deletions(-) rename data/configs/{17-moution.c.txt => 17-motion.c.txt} (100%) rename data/configs/{17-moution.s.txt => 17-motion.s.txt} (100%) rename data/configs/{18-moution.c.txt => 18-motion.c.txt} (100%) rename data/configs/{18-moution.s.txt => 18-motion.s.txt} (100%) diff --git a/data/configs/17-moution.c.txt b/data/configs/17-motion.c.txt similarity index 100% rename from data/configs/17-moution.c.txt rename to data/configs/17-motion.c.txt diff --git a/data/configs/17-moution.s.txt b/data/configs/17-motion.s.txt similarity index 100% rename from data/configs/17-moution.s.txt rename to data/configs/17-motion.s.txt diff --git a/data/configs/18-moution.c.txt b/data/configs/18-motion.c.txt similarity index 100% rename from data/configs/18-moution.c.txt rename to data/configs/18-motion.c.txt diff --git a/data/configs/18-moution.s.txt b/data/configs/18-motion.s.txt similarity index 100% rename from data/configs/18-moution.s.txt rename to data/configs/18-motion.s.txt diff --git a/include/CommonTypes.h b/include/CommonTypes.h index a609f050..e0beebba 100644 --- a/include/CommonTypes.h +++ b/include/CommonTypes.h @@ -20,3 +20,26 @@ enum LedStatus_t { LED_SLOW, LED_FAST }; + +enum ConfigType_t { + CT_MACRO, + CT_SCENARIO +}; + +enum Item_t { + RELAY, + PWM, + DHT11, + DHT22, + ANALOG, + BMP280, + BME280, + DALLAS, + TERMOSTAT, + ULTRASONIC, + MOTION, + STEPPER, + SERVO, + FIRMWARE, + NUM_ITEMS +}; \ No newline at end of file diff --git a/include/Global.h b/include/Global.h index e4fe7f82..875653aa 100644 --- a/include/Global.h +++ b/include/Global.h @@ -52,7 +52,7 @@ extern TickerScheduler ts; extern WiFiClient espClient; -extern PubSubClient client_mqtt; +extern PubSubClient mqtt; extern StringCommand sCmd; @@ -121,7 +121,7 @@ extern String last_version; extern boolean upgrade_url; extern boolean upgrade; -extern boolean mqtt_connection; +extern boolean mqttParamsChanged; extern boolean udp_data_parse; extern boolean mqtt_send_settings_to_udp; extern boolean i2c_scanning; @@ -188,21 +188,24 @@ extern void choose_log_date_and_send(); extern void setChipId(); extern void printMemoryStatus(String text); extern void saveConfig(); -extern String getURL(const String &urls); +extern String getURL(const String& urls); extern void servo_(); extern void setLedStatus(LedStatus_t); // Mqtt -extern void MQTT_init(); -extern boolean MQTT_Connecting(); -extern boolean sendMQTT(String end_of_topik, String data); -extern boolean sendCHART(String topik, String data); -extern void sendSTATUS(String topik, String state); -extern void sendCONTROL(String id, String topik, String state); +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 publishControl(String id, String topic, String state); + +extern boolean sendSTATUS(String topic, String state); + extern void do_mqtt_connection(); -extern void handleMQTT(); //Scenario extern void eventGen(String event_name, String number); diff --git a/include/Utils/FileUtils.h b/include/Utils/FileUtils.h index 39fef037..da01fb56 100644 --- a/include/Utils/FileUtils.h +++ b/include/Utils/FileUtils.h @@ -51,4 +51,6 @@ String readFile(const String filename, size_t max_size); /* * Размер файла */ -String getFileSize(const String filename); \ No newline at end of file +String getFileSize(const String filename); + +bool copyFile(const String src, const String dst, bool overwrite = true); \ No newline at end of file diff --git a/include/Utils/WiFiUtils.h b/include/Utils/WiFiUtils.h index 4fd68ad2..da020af4 100644 --- a/include/Utils/WiFiUtils.h +++ b/include/Utils/WiFiUtils.h @@ -2,9 +2,11 @@ #include "Global.h" -boolean scanWiFi(String ssid); +boolean isNetworkActive(); void startSTAMode(); bool startAPMode(); +boolean scanWiFi(String ssid); + diff --git a/src/Cmd.cpp b/src/Cmd.cpp index 005c35d5..224a085f 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -526,7 +526,7 @@ void mqttOrderSend() { //Serial.print(all_line); //Serial.print("->"); //Serial.println(order); - client_mqtt.publish(all_line.c_str(), order.c_str(), false); + mqtt.publish(all_line.c_str(), order.c_str(), false); } void httpOrderSend() { diff --git a/src/Global.cpp b/src/Global.cpp index d4b9b154..d3f1c760 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -1,20 +1,15 @@ #include "Global.h" -/* -* Objects.cpp(с данными) -*/ - #ifdef WS_enable AsyncWebSocket ws; //AsyncEventSource events; #endif - TickerScheduler ts(TEST + 1); WiFiClient espClient; -PubSubClient client_mqtt(espClient); +PubSubClient mqtt(espClient); StringCommand sCmd; @@ -72,7 +67,7 @@ String last_version = ""; // Async actions boolean upgrade_url = false; boolean upgrade = false; -boolean mqtt_connection = false; +boolean mqttParamsChanged = false; boolean udp_data_parse = false; boolean mqtt_send_settings_to_udp = false; boolean i2c_scanning = false; diff --git a/src/Logging.cpp b/src/Logging.cpp index f0205d30..5fb898b9 100644 --- a/src/Logging.cpp +++ b/src/Logging.cpp @@ -134,7 +134,7 @@ void sendLogData(String file, String topic) { log_date = ""; json_array = "{\"status\":[" + json_array + "]}"; Serial.println(json_array); - sendCHART(topic, json_array); + publishChart(topic, json_array); json_array = ""; printMemoryStatus("[I] send log date"); } diff --git a/src/Mqtt.cpp b/src/Mqtt.cpp index 907f801f..d73c43ac 100644 --- a/src/Mqtt.cpp +++ b/src/Mqtt.cpp @@ -3,34 +3,40 @@ // #include +static const char* MODULE = "Mqtt"; + // Errors int wifi_lost_error = 0; int mqtt_lost_error = 0; -void callback(char* topic, uint8_t* payload, size_t length); -String stateMQTT(); +// Session params +String mqttPrefix; + +void handleSubscribedUpdates(char* topic, uint8_t* payload, size_t length); +const String getMqttStateStr(); void sendAllData(); void sendAllWigets(); -void sendSTATUS(String topik, String state); +boolean sendSTATUS(String topic, String state); void outcoming_date(); -//===============================================ИНИЦИАЛИЗАЦИЯ================================================ -void MQTT_init() { +void initMQTT() { + mqtt.setCallback(handleSubscribedUpdates); + ts.add( - WIFI_MQTT_CONNECTION_CHECK, MQTT_RECONNECT_INTERVAL, [&](void*) { - if (WiFi.status() == WL_CONNECTED) { - Serial.println("[VV] WiFi-ok"); - if (client_mqtt.connected()) { - Serial.println("[VV] MQTT-ok"); + WIFI_MQTT_CONNECTION_CHECK, MQTT_RECONNECT_INTERVAL, + [&](void*) { + if (isNetworkActive()) { + if (mqtt.connected()) { + pm.info("OK"); setLedStatus(LED_OFF); } else { - MQTT_Connecting(); + connectMQTT(); if (!just_load) mqtt_lost_error++; } } else { - Serial.println("[E] Lost WiFi connection"); - wifi_lost_error++; + pm.error("WiFi connection lost"); ts.remove(WIFI_MQTT_CONNECTION_CHECK); + wifi_lost_error++; startAPMode(); } }, @@ -38,150 +44,161 @@ void MQTT_init() { } void do_mqtt_connection() { - if (mqtt_connection) { - mqtt_connection = false; - client_mqtt.disconnect(); - MQTT_Connecting(); + if (mqttParamsChanged) { + mqtt.disconnect(); + connectMQTT(); + mqttParamsChanged = false; } } -//================================================ОБНОВЛЕНИЕ==================================================== -void handleMQTT() { - if (WiFi.status() == WL_CONNECTED) { - if (client_mqtt.connected()) { - client_mqtt.loop(); - } +void loopMQTT() { + if (!isNetworkActive() || !mqtt.connected()) { + return; } + mqtt.loop(); } -boolean MQTT_Connecting() { + +void subscribe() { + pm.info("Subscribe"); + // Для приема получения HELLOW и подтверждения связи + // Подписываемся на топики control + // Подписываемся на топики order + mqtt.subscribe(jsonReadStr(configSetupJson, "mqttPrefix").c_str()); + mqtt.subscribe((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/+/control").c_str()); + mqtt.subscribe((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/order").c_str()); + mqtt.subscribe((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/update").c_str()); + mqtt.subscribe((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/devc").c_str()); + mqtt.subscribe((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/devs").c_str()); +} + +boolean connectMQTT() { + if (!isNetworkActive()) { + return false; + } + + String addr = jsonReadStr(configSetupJson, "mqttServer"); + int port = jsonReadInt(configSetupJson, "mqttPort"); + String user = jsonReadStr(configSetupJson, "mqttUser"); + String pass = jsonReadStr(configSetupJson, "mqttPass"); + mqttPrefix = jsonReadStr(configSetupJson, "mqttPrefix"); + + if (!addr) { + pm.error("no broker address"); + return false; + } + pm.info("broker " + addr + ":" + String(port, DEC)); + setLedStatus(LED_FAST); + mqtt.setServer(addr.c_str(), port); bool res = false; - String mqtt_server = jsonReadStr(configSetupJson, "mqttServer"); - if ((mqtt_server != "")) { - Serial.println("[E] Lost MQTT connection, start reconnecting"); - setLedStatus(LED_FAST); - client_mqtt.setServer(mqtt_server.c_str(), jsonReadInt(configSetupJson, "mqttPort")); - if (WiFi.status() == WL_CONNECTED) { - if (!client_mqtt.connected()) { - Serial.println("[V] Connecting to MQTT server commenced"); - if (client_mqtt.connect(chipId.c_str(), jsonReadStr(configSetupJson, "mqttUser").c_str(), jsonReadStr(configSetupJson, "mqttPass").c_str())) { - Serial.println("[VV] MQTT connected"); - setLedStatus(LED_OFF); - client_mqtt.setCallback(callback); - client_mqtt.subscribe(jsonReadStr(configSetupJson, "mqttPrefix").c_str()); // Для приема получения HELLOW и подтверждения связи - client_mqtt.subscribe((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/+/control").c_str()); // Подписываемся на топики control - client_mqtt.subscribe((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/order").c_str()); // Подписываемся на топики order - client_mqtt.subscribe((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/update").c_str()); - client_mqtt.subscribe((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/devc").c_str()); - client_mqtt.subscribe((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/devs").c_str()); - Serial.println("[V] Callback set, subscribe done"); - res = true; - } else { - Serial.println("[E] try again in " + String(MQTT_RECONNECT_INTERVAL / 1000) + " sec"); - setLedStatus(LED_FAST); - } - } + if (!mqtt.connected()) { + if (mqtt.connect(chipId.c_str(), user.c_str(), pass.c_str())) { + pm.info("connected"); + setLedStatus(LED_OFF); + subscribe(); + res = true; + } else { + pm.error("could't connect, retry in " + String(MQTT_RECONNECT_INTERVAL / 1000) + "s"); + setLedStatus(LED_FAST); } - } else { - Serial.println("[E] No date for MQTT connection"); } return res; } -//=====================================================ВХОДЯЩИЕ ДАННЫЕ======================================================== -void callback(char* topic, uint8_t* payload, size_t length) { - Serial.print("[MQTT] "); - Serial.print(topic); - String topic_str = String(topic); +void handleSubscribedUpdates(char* topic, uint8_t* payload, size_t length) { + String topicStr = String(topic); + pm.info(topicStr); - String str; + String payloadStr; + payloadStr.reserve(length + 1); for (size_t i = 0; i < length; i++) { - str += (char)payload[i]; + payloadStr += (char)payload[i]; } - Serial.println(" => " + str); + pm.info(payloadStr); - if (str == "HELLO") outcoming_date(); + if (payloadStr == "HELLO") { + //данные которые отправляем при подключении или отбновлении страницы + pm.info("Send web page updates"); + sendAllWigets(); + sendAllData(); +#ifdef LOGGING_ENABLED + choose_log_date_and_send(); +#endif + } else if (topicStr.indexOf("control")) { + // название топика - команда, + // значение - параметр + //IoTmanager/800324-1458415/button99/control 1 + String topic = selectFromMarkerToMarker(topicStr, "/", 3); + topic = add_set(topic); + String number = selectToMarkerLast(topic, "Set"); + topic.replace(number, ""); - //превращает название топика в команду, а значение в параметр команды - if (topic_str.indexOf("control") > 0) { //IoTmanager/800324-1458415/button-sw2/control 1 //IoTmanager/800324-1458415/button99/control 1 - String topic = selectFromMarkerToMarker(topic_str, "/", 3); //button1 //button99 - topic = add_set(topic); //buttonSet1 //buttonSet99 - String number = selectToMarkerLast(topic, "Set"); //1 //99 - topic.replace(number, ""); //buttonSet //buttonSet - String final_line = topic + " " + number + " " + str; //buttonSet 1 1 //buttonSet 99 1 - order_loop += final_line + ","; - } - - if (topic_str.indexOf("order") > 0) { - str.replace("_", " "); - //Serial.println(str); - order_loop += str + ","; - } - if (topic_str.indexOf("update") > 0) { - if (str == "1") { + order_loop += topic; + order_loop += " "; + order_loop += number; + order_loop += " "; + order_loop += payloadStr; + order_loop += ","; + } else if (topicStr.indexOf("order")) { + payloadStr.replace("_", " "); + order_loop += payloadStr; + order_loop += ","; + } else if (topicStr.indexOf("update")) { + if (payloadStr == "1") { upgrade = true; } - } - if (topic_str.indexOf("devc") > 0) { - writeFile("firmware.c.txt", str); + } else if (topicStr.indexOf("devc")) { + writeFile("firmware.c.txt", payloadStr); Device_init(); - } - if (topic_str.indexOf("devs") > 0) { - writeFile("firmware.s.txt", str); + } else if (topicStr.indexOf("devs")) { + writeFile("firmware.s.txt", payloadStr); Scenario_init(); } } -//данные которые отправляем при подключении или отбновлении страницы -void outcoming_date() { - sendAllWigets(); - sendAllData(); - -#ifdef LOGGING_ENABLED - choose_log_date_and_send(); -#endif - - Serial.println("[V] Sending all date to iot manager completed"); +boolean publish(const String& topic, const String& data) { + if (mqtt.beginPublish(topic.c_str(), data.length(), false)) { + mqtt.print(data); + return mqtt.endPublish(); + } + return false; } -//======================================CONFIG================================================== -boolean sendMQTT(String end_of_topik, String data) { - String topik = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/" + end_of_topik; - boolean send_status = client_mqtt.beginPublish(topik.c_str(), data.length(), false); - client_mqtt.print(data); - client_mqtt.endPublish(); - return send_status; +boolean publishData(const String& topic, const String& data) { + String path = mqttPrefix + "/" + chipId + "/" + topic; + if (!publish(path, data)) { + pm.error("on publish data"); + return false; + } + return true; } -boolean sendCHART(String topik, String data) { - topik = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/" + topik + "/" + "status"; - boolean send_status = client_mqtt.beginPublish(topik.c_str(), data.length(), false); - client_mqtt.print(data); - client_mqtt.endPublish(); - return send_status; +boolean publishChart(const String& topic, const String& data) { + String path = mqttPrefix + "/" + chipId + "/" + topic + "/status"; + if (!publish(path, data)) { + pm.error("on publish chart"); + return false; + } + return true; } -boolean sendCHART_test(String topik, String data) { - topik = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/" + topik + "/" + "status"; - boolean send_status = client_mqtt.publish(topik.c_str(), data.c_str(), false); - return send_status; +boolean publishControl(String id, String topic, String state) { + String path = mqttPrefix + "/" + id + "/" + topic + "/control"; + return mqtt.publish(path.c_str(), state.c_str(), false); } -//======================================STATUS================================================== -void sendSTATUS(String topik, String state) { - topik = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/" + topik + "/" + "status"; +boolean sendCHART_test(String topic, String data) { + topic = mqttPrefix + "/" + chipId + "/" + topic + "/" + "status"; + return mqtt.publish(topic.c_str(), data.c_str(), false); +} + +boolean sendSTATUS(String topic, String state) { + topic = mqttPrefix + "/" + chipId + "/" + topic + "/" + "status"; String json_ = "{}"; jsonWriteStr(json_, "status", state); - client_mqtt.publish(topik.c_str(), json_.c_str(), false); -} - -//======================================CONTROL================================================== -void sendCONTROL(String id, String topik, String state) { - String all_line = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + id + "/" + topik + "/control"; - client_mqtt.publish(all_line.c_str(), state.c_str(), false); + return mqtt.publish(topic.c_str(), json_.c_str(), false); } //=====================================================ОТПРАВЛЯЕМ ВИДЖЕТЫ======================================================== - #ifdef LAYOUT_IN_RAM void sendAllWigets() { if (all_widgets != "") { @@ -214,8 +231,8 @@ void sendAllWigets() { } while (file.position() != file.size()) { String payload = file.readStringUntil('\n'); - Serial.println("[V] " + payload); - sendMQTT("config", payload); + pm.info("publish: " + payload); + publishData("config", payload); } file.close(); } @@ -244,41 +261,40 @@ void sendAllData() { //берет строку json и ключи превра } } -String stateMQTT() { - int state = client_mqtt.state(); - switch (state) { +const String getMqttStateStr() { + switch (mqtt.state()) { case -4: - return "the server didn't respond within the keepalive time"; + return F("no respond"); break; case -3: - return "the network connection was broken"; + return F("connection was broken"); break; case -2: - return "the network connection failed"; + return F("connection failed"); break; case -1: - return "the client is disconnected cleanly"; + return F("client disconnected "); break; case 0: - return "the client is connected"; + return F("client connected"); break; case 1: - return "the server doesn't support the requested version of MQTT"; + return F("doesn't support the requested version"); break; case 2: - return "the server rejected the client identifier"; + return F("rejected the client identifier"); break; case 3: - return "the server was unable to accept the connection"; + return F("unable to accept the connection"); break; case 4: - return "the username/password were rejected"; + return F("wrong username/password"); break; case 5: - return "the client was not authorized to connect"; + return F("not authorized to connect"); break; default: - return "unspecified"; + return F("unspecified"); break; } } diff --git a/src/Scenario.cpp b/src/Scenario.cpp index 37dfecb0..ab9e4d0c 100644 --- a/src/Scenario.cpp +++ b/src/Scenario.cpp @@ -1,96 +1,95 @@ #include "Global.h" void handleScenario() { + if (jsonReadStr(configSetupJson, "scen") == "1") { + if ((jsonReadStr(configOptionJson, "scenario_status") != "")) { + int i = 0; + String str = scenario; //читаем переменную с сценариями (то что из файла на странице) + str += "\n"; + str.replace("\r\n", "\n"); + str.replace("\r", "\n"); + while (str.length() != 0) { + //----------------------------------------------------------------------------------------------------------------------- + String tmp = selectToMarker(str, "end"); //выделяем первый сценарий из файла вместе с командами + if (tmp == "") return; + i++; - if (jsonReadStr(configSetupJson, "scen") == "1") { - if ((jsonReadStr(configOptionJson, "scenario_status") != "")) { - int i = 0; - String str = scenario; //читаем переменную с сценариями (то что из файла на странице) - str += "\n"; - str.replace("\r\n", "\n"); - str.replace("\r", "\n"); - while (str.length() != 0) { - //----------------------------------------------------------------------------------------------------------------------- - String tmp = selectToMarker (str, "end"); //выделяем первый сценарий из файла вместе с командами - if (tmp == "") return; - i++; + if (scenario_line_status[i] == 1) { + //Serial.println(i); + String condition = selectToMarker(tmp, "\n"); //выделяем первую строку самого сценария button1 = 1 (условие) + String param_name = selectFromMarkerToMarker(condition, " ", 0); + String order = jsonReadStr(configOptionJson, "scenario_status"); //читаем весь файл событий + String param = selectToMarker(order, ","); //читаем первое событие из файла событий + if (param_name == param) { //если поступившее событие равно событию заданному buttonSet1 в файле начинаем его обработку - if (scenario_line_status[i] == 1) { - //Serial.println(i); - String condition = selectToMarker (tmp, "\n"); //выделяем первую строку самого сценария button1 = 1 (условие) - String param_name = selectFromMarkerToMarker(condition, " " , 0); - String order = jsonReadStr(configOptionJson, "scenario_status"); //читаем весь файл событий - String param = selectToMarker (order, ","); //читаем первое событие из файла событий - if (param_name == param) { //если поступившее событие равно событию заданному buttonSet1 в файле начинаем его обработку + String sign = selectFromMarkerToMarker(condition, " ", 1); //читаем знак (=) + String value = selectFromMarkerToMarker(condition, " ", 2); //читаем значение (1) + if (value.indexOf("digit") != -1) { + // value = add_set(value); + value = jsonReadStr(configLiveJson, value); + } + if (value.indexOf("time") != -1) { + // value = add_set(value); + value = jsonReadStr(configLiveJson, value); + } + boolean flag = false; //если одно из значений совпало то только тогда начинаем выполнять комнады + if (sign == "=") { + if (jsonReadStr(configLiveJson, param_name) == value) flag = true; + } + if (sign == "!=") { + if (jsonReadStr(configLiveJson, param_name) != value) flag = true; + } + if (sign == "<") { + if (jsonReadStr(configLiveJson, param_name).toInt() < value.toInt()) flag = true; + } + if (sign == ">") { + if (jsonReadStr(configLiveJson, param_name).toInt() > value.toInt()) flag = true; + } + if (sign == ">=") { + if (jsonReadStr(configLiveJson, param_name).toInt() >= value.toInt()) flag = true; + } + if (sign == "<=") { + if (jsonReadStr(configLiveJson, param_name).toInt() <= value.toInt()) flag = true; + } - String sign = selectFromMarkerToMarker(condition, " " , 1); //читаем знак (=) - String value = selectFromMarkerToMarker(condition, " " , 2); //читаем значение (1) - if (value.indexOf("digit") != -1) { - // value = add_set(value); - value = jsonReadStr(configLiveJson, value); - } - if (value.indexOf("time") != -1) { - // value = add_set(value); - value = jsonReadStr(configLiveJson, value); - } - boolean flag = false; //если одно из значений совпало то только тогда начинаем выполнять комнады - if (sign == "=") { - if (jsonReadStr(configLiveJson, param_name) == value) flag = true; - } - if (sign == "!=") { - if (jsonReadStr(configLiveJson, param_name) != value) flag = true; - } - if (sign == "<") { - if (jsonReadStr(configLiveJson, param_name).toInt() < value.toInt()) flag = true; - } - if (sign == ">") { - if (jsonReadStr(configLiveJson, param_name).toInt() > value.toInt()) flag = true; - } - if (sign == ">=") { - if (jsonReadStr(configLiveJson, param_name).toInt() >= value.toInt()) flag = true; - } - if (sign == "<=") { - if (jsonReadStr(configLiveJson, param_name).toInt() <= value.toInt()) flag = true; - } + if (flag) { + tmp = deleteBeforeDelimiter(tmp, "\n"); //удаляем строку самого сценария оставляя только команды + stringExecution(tmp); //выполняем все команды - if (flag) { - tmp = deleteBeforeDelimiter(tmp, "\n"); //удаляем строку самого сценария оставляя только команды - stringExecution(tmp); //выполняем все команды - - Serial.println("[SCENARIO] '" + condition + "'"); - //Serial.println(" " + tmp); + Serial.println("[SCENARIO] '" + condition + "'"); + //Serial.println(" " + tmp); + } + } + } + str = deleteBeforeDelimiter(str, "end\n"); //удаляем первый сценарий + //----------------------------------------------------------------------------------------------------------------------- } - } + String tmp2 = jsonReadStr(configOptionJson, "scenario_status"); //читаем файл событий + tmp2 = deleteBeforeDelimiter(tmp2, ","); //удаляем выполненное событие + jsonWriteStr(configOptionJson, "scenario_status", tmp2); //записываем обновленный файл событий + i = 0; } - str = deleteBeforeDelimiter(str, "end\n"); //удаляем первый сценарий - //----------------------------------------------------------------------------------------------------------------------- - } - String tmp2 = jsonReadStr(configOptionJson, "scenario_status"); //читаем файл событий - tmp2 = deleteBeforeDelimiter(tmp2, ","); //удаляем выполненное событие - jsonWriteStr(configOptionJson, "scenario_status", tmp2); //записываем обновленный файл событий - i = 0; } - } } -void eventGen (String event_name, String number) { //событие выглядит как имя плюс set плюс номер: button+Set+1 +void eventGen(String event_name, String number) { //событие выглядит как имя плюс set плюс номер: button+Set+1 - if (jsonReadStr(configSetupJson, "scen") == "1") { - String tmp = jsonReadStr(configOptionJson, "scenario_status") ; //генерирование события - //Serial.println(event_name); - jsonWriteStr(configOptionJson, "scenario_status", tmp + event_name + number + ","); - } + if (jsonReadStr(configSetupJson, "scen") == "1") { + String tmp = jsonReadStr(configOptionJson, "scenario_status"); //генерирование события + //Serial.println(event_name); + jsonWriteStr(configOptionJson, "scenario_status", tmp + event_name + number + ","); + } } String add_set(String param_name) { - String num1 = param_name.substring(param_name.length() - 1); - String num2 = param_name.substring(param_name.length() - 2, param_name.length() - 1); - if (isDigitStr(num1) && isDigitStr(num2)) { - param_name = param_name.substring(0, param_name.length() - 2) + "Set" + num2 + num1; - } else { - if (isDigitStr(num1)) { - param_name = param_name.substring(0, param_name.length() - 1) + "Set" + num1; + String num1 = param_name.substring(param_name.length() - 1); + String num2 = param_name.substring(param_name.length() - 2, param_name.length() - 1); + if (isDigitStr(num1) && isDigitStr(num2)) { + param_name = param_name.substring(0, param_name.length() - 2) + "Set" + num2 + num1; + } else { + if (isDigitStr(num1)) { + param_name = param_name.substring(0, param_name.length() - 1) + "Set" + num1; + } } - } - return param_name; + return param_name; } \ No newline at end of file diff --git a/src/Sensors.cpp b/src/Sensors.cpp index 74422070..2e3f47bd 100644 --- a/src/Sensors.cpp +++ b/src/Sensors.cpp @@ -351,7 +351,7 @@ void dhtP_reading() { jsonWriteStr(configLiveJson, "dhtPerception", final_line); eventGen("dhtPerception", ""); sendSTATUS("dhtPerception", final_line); - if (client_mqtt.connected()) { + if (mqtt.connected()) { Serial.println("[I] sensor 'dhtPerception' data: " + final_line); } } diff --git a/src/Utils/FileUtils.cpp b/src/Utils/FileUtils.cpp index 429eacda..5671c37d 100644 --- a/src/Utils/FileUtils.cpp +++ b/src/Utils/FileUtils.cpp @@ -54,6 +54,32 @@ String addFile(const String filename, const String str) { return "Sucсess"; } +bool copyFile(const String src, const String dst, bool overwrite) { + String source = filepath(src); + String destination = filepath(dst); + if (!LittleFS.exists(source)) { + pm.error("source not exist: " + source); + return false; + } + if (LittleFS.exists(destination)) { + if (!overwrite) { + pm.error("destination already exist: " + destination); + return false; + } + LittleFS.remove(destination); + } + auto srcFile = LittleFS.open(source, "r"); + auto dstFile = LittleFS.open(destination, "w"); + + static uint8_t buf[512]; + while (srcFile.read(buf, 512)) { + dstFile.write(buf, 512); + } + srcFile.close(); + dstFile.close(); + return true; +} + String writeFile(const String filename, const String str) { auto file = LittleFS.open(filepath(filename), "w"); if (!file) { diff --git a/src/Utils/StringUtils.cpp b/src/Utils/StringUtils.cpp index 48df7eba..8340a0b1 100644 --- a/src/Utils/StringUtils.cpp +++ b/src/Utils/StringUtils.cpp @@ -35,16 +35,23 @@ String selectToMarkerPlus(String str, String found, int plus) { return str.substring(0, p + plus); } -String selectFromMarkerToMarker(String str, String found, int number) { - if (str.indexOf(found) == -1) return "not found"; // если строки поиск нет сразу выход - str += found; // добавим для корректного поиска - uint8_t i = 0; // Индекс перебора +String selectFromMarkerToMarker(String str, String tofind, int number) { + if (str.indexOf(tofind) == -1) { + return "not found"; + } + str += tofind; // добавим для корректного поиска + uint8_t i = 0; // Индекс перебора do { - if (i == number) return selectToMarker(str, found); // если индекс совпал с позицией законцим вернем резултат - str = deleteBeforeDelimiter(str, found); // отбросим проверенный блок до разделителя - i++; // увеличим индекс - } while (str.length() != 0); // повторим пока строка не пустая - return "not found"; // Достигли пустой строки и ничего не нашли + if (i == number) { + // если индекс совпал с позицией + return selectToMarker(str, tofind); + } + // отбросим проверенный блок до разделителя + str = deleteBeforeDelimiter(str, tofind); + i++; + } while (str.length() != 0); + + return "not found"; } uint8_t hexStringToUint8(String hex) { diff --git a/src/Utils/WiFiUtils.cpp b/src/Utils/WiFiUtils.cpp index ca1ac77a..1d5dd506 100644 --- a/src/Utils/WiFiUtils.cpp +++ b/src/Utils/WiFiUtils.cpp @@ -44,7 +44,7 @@ void startSTAMode() { } while (keepConnecting && tries--); if (WiFi.status() == WL_CONNECTED) { - MQTT_init(); + initMQTT(); setLedStatus(LED_OFF); } else { startAPMode(); @@ -105,4 +105,8 @@ boolean scanWiFi(String ssid) { } } return res; -} \ No newline at end of file +} + +boolean isNetworkActive() { + return WiFi.status() == WL_CONNECTED; +} diff --git a/src/Web.cpp b/src/Web.cpp index 3f2e412a..c2ea46c3 100644 --- a/src/Web.cpp +++ b/src/Web.cpp @@ -1,103 +1,93 @@ #include "Global.h" -String stateMQTT(); +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(); + return preset >= MIN_PRESET && preset <= MAX_PRESET; + } + return false; +} + +static const char* item_names[NUM_ITEMS] = {"relay", "pwm", + "dht11", "dht22", "analog", + "bmp280", "bme280", "dallas", + "termostat", "ultrasonic", + "motion", "stepper", + "servo", "firmware"}; + +const char* getItemName(Item_t item) { + return item_names[item]; +} + +static const char* config_file_fmt = "configs/%d-%s.%s.txt"; + +const String getPresetFile(uint8_t preset, ConfigType_t type) { + Item_t item = getPresetItem(preset); + char buf[64]; + sprintf(buf, config_file_fmt, preset, getItemName(item), type == CT_MACRO ? "c" : "s"); + return String(buf); +} + +const Item_t getPresetItem(uint8_t preset) { + Item_t res = NUM_ITEMS; + if (preset >= 1 && preset <= 7) { + res = RELAY; + } else if (preset == 8) { + res = PWM; + } else if (preset == 9) { + res = DHT11; + } else if (preset == 10) { + res = DHT22; + } else if (preset == 11) { + res = ANALOG; + } else if (preset == 12) { + res = BMP280; + } else if (preset == 13) { + res = BME280; + } else if (preset == 14) { + res = DALLAS; + } else if (preset == 15) { + res = TERMOSTAT; + } else if (preset == 16) { + res = ULTRASONIC; + } else if (preset >= 17 || preset <= 18) { + res = MOTION; + } else if (preset == 19) { + res = STEPPER; + } else if (preset == 20) { + res = SERVO; + } else if (preset == 21) { + res = FIRMWARE; + } + return res; +} void web_init() { server.on("/set", HTTP_GET, [](AsyncWebServerRequest* request) { - String value; - //============================device settings===================================== - if (request->hasArg("preset")) { - //-------------------------------------------------------------------------------- - String value; - value = request->getParam("preset")->value(); - if (value == "1") { - writeFile("firmware.c.txt", readFile("configs/1-relay.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/1-relay.s.txt", 2048)); - } - if (value == "2") { - writeFile("firmware.c.txt", readFile("configs/2-relay.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/2-relay.s.txt", 2048)); - } - if (value == "3") { - writeFile("firmware.c.txt", readFile("configs/3-relay.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/3-relay.s.txt", 2048)); - } - if (value == "4") { - writeFile("firmware.c.txt", readFile("configs/4-relay.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/4-relay.s.txt", 2048)); - } - if (value == "5") { - writeFile("firmware.c.txt", readFile("configs/5-relay.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/5-relay.s.txt", 2048)); - } - if (value == "6") { - writeFile("firmware.c.txt", readFile("configs/6-relay.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/6-relay.s.txt", 2048)); - } - if (value == "7") { - writeFile("firmware.c.txt", readFile("configs/7-relay.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/7-relay.s.txt", 2048)); - } - if (value == "8") { - writeFile("firmware.c.txt", readFile("configs/8-pwm.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/8-pwm.s.txt", 2048)); - } - if (value == "9") { - writeFile("firmware.c.txt", readFile("configs/9-dht11.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/9-dht11.s.txt", 2048)); - } - if (value == "10") { - writeFile("firmware.c.txt", readFile("configs/10-dht22.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/10-dht22.s.txt", 2048)); - } - if (value == "11") { - writeFile("firmware.c.txt", readFile("configs/11-analog.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/11-analog.s.txt", 2048)); - } - if (value == "12") { - writeFile("firmware.c.txt", readFile("configs/12-bmp280.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/12-bmp280.s.txt", 2048)); - } - if (value == "13") { - writeFile("firmware.c.txt", readFile("configs/13-bme280.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/13-bme280.s.txt", 2048)); - } - if (value == "14") { - writeFile("firmware.c.txt", readFile("configs/14-dallas.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/14-dallas.s.txt", 2048)); - } - if (value == "15") { - writeFile("firmware.c.txt", readFile("configs/15-termostat.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/15-termostat.s.txt", 2048)); - } - if (value == "16") { - writeFile("firmware.c.txt", readFile("configs/16-ultrasonic.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/16-ultrasonic.s.txt", 2048)); - } - if (value == "17") { - writeFile("firmware.c.txt", readFile("configs/17-moution.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/17-moution.s.txt", 2048)); - } - if (value == "18") { - writeFile("firmware.c.txt", readFile("configs/18-moution.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/18-moution.s.txt", 2048)); - } - if (value == "19") { - writeFile("firmware.c.txt", readFile("configs/19-stepper.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/19-stepper.s.txt", 2048)); - } - if (value == "20") { - writeFile("firmware.c.txt", readFile("configs/20-servo.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/20-servo.s.txt", 2048)); - } - if (value == "21") { - writeFile("firmware.c.txt", readFile("configs/firmware.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/firmware.s.txt", 2048)); - } + uint8_t preset; + if (parseRequestForPreset(request, preset)) { + String srcMacro = preset == 21 ? "configs/firmware.c.txt" : getPresetFile(preset, CT_MACRO); + String srcScenario = preset == 21 ? "configs/firmware.s.txt" : getPresetFile(preset, CT_SCENARIO); + pm.info("activate " + srcMacro); + pm.info("activate " + srcScenario); + copyFile(srcMacro, "firmware.c.txt"); + copyFile(srcScenario, "firmware.s.txt"); + Device_init(); Scenario_init(); + request->redirect("/?set.device"); } + //-------------------------------------------------------------------------------- if (request->hasArg("devinit")) { Device_init(); @@ -105,7 +95,7 @@ void web_init() { } //-------------------------------------------------------------------------------- if (request->hasArg("scen")) { - value = request->getParam("scen")->value(); + String value = request->getParam("scen")->value(); if (value == "0") { jsonWriteStr(configSetupJson, "scen", value); saveConfig(); @@ -132,7 +122,7 @@ void web_init() { #endif //==============================udp settings============================================= if (request->hasArg("udponoff")) { - value = request->getParam("udponoff")->value(); + String value = request->getParam("udponoff")->value(); if (value == "0") { jsonWriteStr(configSetupJson, "udponoff", value); saveConfig(); @@ -214,7 +204,7 @@ void web_init() { } //-------------------------------------------------------------------------------- if (request->hasArg("blink")) { - value = request->getParam("blink")->value(); + String value = request->getParam("blink")->value(); if (value == "0") { jsonWriteStr(configSetupJson, "blink", value); saveConfig(); @@ -229,32 +219,32 @@ void web_init() { if (request->hasArg("mqttServer")) { jsonWriteStr(configSetupJson, "mqttServer", request->getParam("mqttServer")->value()); saveConfig(); - mqtt_connection = true; + mqttParamsChanged = true; request->send(200, "text/text", "ok"); } if (request->hasArg("mqttPort")) { int port = (request->getParam("mqttPort")->value()).toInt(); jsonWriteInt(configSetupJson, "mqttPort", port); saveConfig(); - mqtt_connection = true; + mqttParamsChanged = true; request->send(200, "text/text", "ok"); } if (request->hasArg("mqttPrefix")) { jsonWriteStr(configSetupJson, "mqttPrefix", request->getParam("mqttPrefix")->value()); saveConfig(); - mqtt_connection = true; + mqttParamsChanged = true; request->send(200, "text/text", "ok"); } if (request->hasArg("mqttUser")) { jsonWriteStr(configSetupJson, "mqttUser", request->getParam("mqttUser")->value()); saveConfig(); - mqtt_connection = true; + mqttParamsChanged = true; request->send(200, "text/text", "ok"); } if (request->hasArg("mqttPass")) { jsonWriteStr(configSetupJson, "mqttPass", request->getParam("mqttPass")->value()); saveConfig(); - mqtt_connection = true; + mqttParamsChanged = true; request->send(200, "text/text", "ok"); } //-------------------------------------------------------------------------------- @@ -263,12 +253,16 @@ void web_init() { request->send(200, "text/text", "ok"); } //-------------------------------------------------------------------------------- + if (request->hasArg("mqttcheck")) { - String tmp = "{}"; - jsonWriteStr(tmp, "title", "" + stateMQTT()); - jsonWriteStr(tmp, "class", "pop-up"); - request->send(200, "text/text", tmp); + String buf = "{}"; + String payload = "" + getMqttStateStr(); + jsonWriteStr(buf, "title", payload); + jsonWriteStr(buf, "class", "pop-up"); + + request->send(200, "text/text", buf); } + //==============================push settings============================================= #ifdef PUSH_ENABLED if (request->hasArg("pushingboxid")) { diff --git a/src/main.cpp b/src/main.cpp index 2bc15218..d88adfe6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,7 +36,9 @@ void setup() { pm.info("Uptime"); uptime_init(); - pm.info("Telemery: " + !TELEMETRY_UPDATE_INTERVAL ? "Disabled" : "Enabled"); + if (!TELEMETRY_UPDATE_INTERVAL) { + pm.info("Telemetry: Disabled"); + } telemetry_init(); pm.info("Updater"); @@ -83,7 +85,7 @@ void loop() { not_async_actions(); - handleMQTT(); + loopMQTT(); handleCMD_loop(); handleButton(); handleScenario(); @@ -133,9 +135,9 @@ void safeDataToFile(String data, String Folder) { jsonWriteStr(configLiveJson, "test", fileName); } -void sendCONFIG(String topik, String widgetConfig, String key, String date) { +void sendConfig(String topic, String widgetConfig, String key, String date) { yield(); - topik = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/" + topik + "/status"; + topic = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId + "/" + topic + "/status"; String outer = "{\"widgetConfig\":"; String inner = "{\""; inner = inner + key; @@ -144,8 +146,6 @@ void sendCONFIG(String topik, String widgetConfig, String key, String date) { inner = inner + "\""; inner = inner + "}}"; String t = outer + inner; - //Serial.println(t); - //client_mqtt.publish(MQTT::Publish(topik, t).set_qos(1)); yield(); } @@ -156,7 +156,6 @@ void setChipId() { #ifdef ESP8266 #ifdef LED_PIN - void setLedStatus(LedStatus_t status) { pinMode(LED_PIN, OUTPUT); switch (status) { diff --git a/src/udp.cpp b/src/udp.cpp index f1cdddaf..95c8c4ff 100644 --- a/src/udp.cpp +++ b/src/udp.cpp @@ -114,7 +114,7 @@ void do_udp_data_parse() { jsonWriteStr(configSetupJson, "mqttPass", jsonReadStr(received_udp_line, "mqttPass")); saveConfig(); Serial.println("[V] new mqtt setting received from udp and saved"); - mqtt_connection = true; + mqttParamsChanged = true; } if (received_udp_line.indexOf("iotm;") >= 0) { add_dev_in_list("dev.csv", selectFromMarkerToMarker(received_udp_line, ";", 1), selectFromMarkerToMarker(received_udp_line, ";", 2), received_ip);