From 86e18f1e991d5c0830df4e261424c3a1e7dd92b3 Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Thu, 18 Jun 2020 23:43:06 +0200 Subject: [PATCH 01/17] First working platformio version --- include/Cmd.h | 36 --- include/{set.h => Consts.h} | 2 - include/FileSystem.h | 6 - include/Global.h | 165 ++++++++++++++ include/Init.h | 5 - include/Logging.h | 7 - include/Mqtt.h | 11 - include/Scenario.h | 5 - include/Sensors.h | 3 - include/Strings_.h | 3 +- include/TimeUtils.h | 14 -- include/Timers.h | 10 - include/Upgrade.h | 3 - include/WiFiUtils.h | 4 - include/Widgets.h | 8 - include/i2c_bus.h | 7 - include/main.h | 31 --- include/push_pushingbox.h | 3 +- lib/ESPrelay/.gitattributes | 17 -- lib/ESPrelay/TheThingsMQTT.cpp | 215 ------------------ lib/ESPrelay/TheThingsMQTT.h | 58 ----- lib/ESPrelay/TickerScheduler.h | 79 ------- lib/ESPrelay/subscribe_and_publish.ino | 182 --------------- lib/TickerScheduler/README.md | 81 +++++++ .../TickerScheduler.cpp | 6 +- lib/TickerScheduler/TickerScheduler.h | 91 ++++++++ .../example/blink/blink/blink.ino | 29 +++ platformio.ini | 3 +- src/Cmd.cpp | 11 +- src/FileSystem.cpp | 7 +- src/Init.cpp | 11 +- src/Logging.cpp | 11 +- src/Mqtt.cpp | 15 +- src/Scenario.cpp | 5 +- src/Sensors.cpp | 4 +- src/TimeUtils.cpp | 5 +- src/Timers.cpp | 10 +- src/Upgrade.cpp | 9 +- src/Web_server.cpp | 3 +- src/WiFiUtils.cpp | 133 ++++++----- src/Widgets.cpp | 5 +- src/i2c_bus.cpp | 5 +- src/iot_firmware.cpp | 5 +- src/main.cpp | 39 ++-- src/udp.cpp | 5 + 45 files changed, 511 insertions(+), 856 deletions(-) delete mode 100644 include/Cmd.h rename include/{set.h => Consts.h} (99%) delete mode 100644 include/FileSystem.h create mode 100644 include/Global.h delete mode 100644 include/Init.h delete mode 100644 include/Logging.h delete mode 100644 include/Mqtt.h delete mode 100644 include/Scenario.h delete mode 100644 include/Sensors.h delete mode 100644 include/TimeUtils.h delete mode 100644 include/Timers.h delete mode 100644 include/Upgrade.h delete mode 100644 include/WiFiUtils.h delete mode 100644 include/Widgets.h delete mode 100644 include/i2c_bus.h delete mode 100644 include/main.h delete mode 100644 lib/ESPrelay/.gitattributes delete mode 100644 lib/ESPrelay/TheThingsMQTT.cpp delete mode 100644 lib/ESPrelay/TheThingsMQTT.h delete mode 100644 lib/ESPrelay/TickerScheduler.h delete mode 100644 lib/ESPrelay/subscribe_and_publish.ino create mode 100644 lib/TickerScheduler/README.md rename lib/{ESPrelay => TickerScheduler}/TickerScheduler.cpp (91%) create mode 100644 lib/TickerScheduler/TickerScheduler.h create mode 100644 lib/TickerScheduler/example/blink/blink/blink.ino diff --git a/include/Cmd.h b/include/Cmd.h deleted file mode 100644 index 47577e82..00000000 --- a/include/Cmd.h +++ /dev/null @@ -1,36 +0,0 @@ - -#pragma once - -#include "Arduino.h" - -extern void CMD_init(); -extern void button(); -extern void buttonSet(); -extern void buttonChange(); -extern void pinSet(); -extern void pinChange(); -extern void handle_time_init(); -extern void pwm(); -extern void switch_(); -extern void pwmSet(); -extern void stepper(); -extern void stepperSet(); -extern void servo_(); -extern void servoSet(); -extern void serialBegin(); -extern void serialWrite(); -extern void logging(); -extern void inputDigit(); -extern void digitSet(); -extern void inputTime(); -extern void button(); -extern void timeSet(); -extern void text(); -extern void textSet(); -extern void mqttOrderSend(); -extern void httpOrderSend(); -extern void firmware(); -extern void update_firmware(); -extern void Scenario_init(); -extern void txtExecution(String file); -extern void stringExecution(String str); diff --git a/include/set.h b/include/Consts.h similarity index 99% rename from include/set.h rename to include/Consts.h index a6d4d9fd..e6ced715 100644 --- a/include/set.h +++ b/include/Consts.h @@ -1,5 +1,3 @@ -#pragma once - #include /******************************************************************* diff --git a/include/FileSystem.h b/include/FileSystem.h deleted file mode 100644 index ccec5ffb..00000000 --- a/include/FileSystem.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include -#include - -extern void File_system_init(); \ No newline at end of file diff --git a/include/Global.h b/include/Global.h new file mode 100644 index 00000000..e4b84378 --- /dev/null +++ b/include/Global.h @@ -0,0 +1,165 @@ +#pragma once + +#include + +#include "Consts.h" + +// Cmd +extern void CMD_init(); +extern void button(); +extern void buttonSet(); +extern void buttonChange(); +extern void pinSet(); +extern void pinChange(); +extern void handle_time_init(); +extern void pwm(); +extern void switch_(); +extern void pwmSet(); +extern void stepper(); +extern void stepperSet(); +extern void servo_(); +extern void servoSet(); +extern void serialBegin(); +extern void serialWrite(); +extern void logging(); +extern void inputDigit(); +extern void digitSet(); +extern void inputTime(); +extern void button(); +extern void timeSet(); +extern void text(); +extern void textSet(); +extern void mqttOrderSend(); +extern void httpOrderSend(); +extern void firmware(); +extern void update_firmware(); +extern void Scenario_init(); +extern void txtExecution(String file); +extern void stringExecution(String str); + +// FileSystem +extern void File_system_init(); + +// i2c_bu +extern void do_i2c_scanning(); +extern String i2c_scan(); + +// Init +extern void All_init(); +extern void statistics_init(); +extern void Scenario_init(); +extern void Device_init(); +extern void prsets_init(); +extern void up_time(); + +// Logging +extern void logging(); +extern void deleteOldDate(String file, int seted_number_of_lines, String date_to_add); +extern void clean_log_date(); +extern void choose_log_date_and_send(); + +// Main +void getMemoryLoad(String text); + +extern String jsonReadStr(String& json, String name); +extern int jsonReadInt(String& json, String name); +extern String jsonWriteInt(String& json, String name, int volume); +extern String jsonWriteStr(String& json, String name, String volume); +extern void saveConfig(); +extern String jsonWriteFloat(String& json, String name, float volume); + +extern String getURL(String urls); + +extern String writeFile(String fileName, String strings); +extern String readFile(String fileName, size_t len); +extern String addFile(String fileName, String strings); + +//STRING +extern String selectToMarkerLast(String str, String found); +extern String selectToMarker(String str, String found); +extern String deleteAfterDelimiter(String str, String found); +extern String deleteBeforeDelimiter(String str, String found); +extern String deleteBeforeDelimiterTo(String str, String found); + +extern String selectFromMarkerToMarker(String str, String found, int number); + +extern void servo_(); +extern boolean isDigitStr(String str); +extern String jsonWriteStr(String& json, String name, String volume); +extern void led_blink(String satus); +extern int count(String str, String found); + + +// 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 do_mqtt_connection(); +extern void handleMQTT(); +extern String selectFromMarkerToMarker(String str, String found, int number); + +// WiFiUtils +extern void WIFI_init(); +extern void All_init(); +extern bool StartAPMode(); +extern void ROUTER_Connecting(); + +//Scenario +extern void eventGen(String event_name, String number); +extern String add_set(String param_name); + +//Sensors +extern void sensors_init(); + +//Timers +extern void Timer_countdown_init(); +extern void timerStart_(); +extern void addTimer(String number, String time); +extern void timerStop_(); +extern void delTimer(String number); +extern int readTimer(int number); + +//TimeUtils +extern void Time_Init(); +extern int timeToMin(String Time); +extern String GetDataDigital(); +extern String GetDate(); +extern String GetTimeWOsec(); +extern String GetTime(); +extern String GetTimeUnix(); +extern void reconfigTime(); +extern void saveConfig(); +extern String GetTimeUnix(); +extern void time_check(); + +//Upgrade +extern void initUpgrade(); + +//widget +extern void createWidget(String widget_name, String page_name, String page_number, String file, String topic); +extern void createWidgetParam(String widget_name, String page_name, String page_number, String file, String topic, String name1, String param1, String name2, String param2, String name3, String param3); +extern void choose_widget_and_create(String widget_name, String page_name, String page_number, String type, String topik); +extern void createChart(String widget_name, String page_name, String page_number, String file, String topic, String maxCount); + +// Push + +extern void Push_init(); + +// UDP +extern void UDP_init(); +extern void do_udp_data_parse(); +extern void do_mqtt_send_settings_to_udp(); +// WebServer +extern void Web_server_init(); + +//iot_firmware +extern void not_async_actions(); +extern void handleCMD_loop(); +extern void handleButton(); +extern void handleScenario(); +extern void handleUdp(); +extern void do_upgrade_url(); +extern void do_upgrade(); \ No newline at end of file diff --git a/include/Init.h b/include/Init.h deleted file mode 100644 index c593153c..00000000 --- a/include/Init.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -extern void Scenario_init(); -extern void Device_init(); -extern void prsets_init(); diff --git a/include/Logging.h b/include/Logging.h deleted file mode 100644 index 5a969e48..00000000 --- a/include/Logging.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -extern void logging(); -extern void deleteOldDate(String file, int seted_number_of_lines, String date_to_add); -extern void clean_log_date(); \ No newline at end of file diff --git a/include/Mqtt.h b/include/Mqtt.h deleted file mode 100644 index 21805a4e..00000000 --- a/include/Mqtt.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -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 do_mqtt_connection(); \ No newline at end of file diff --git a/include/Scenario.h b/include/Scenario.h deleted file mode 100644 index 06875256..00000000 --- a/include/Scenario.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -extern void eventGen(String event_name, String number); \ No newline at end of file diff --git a/include/Sensors.h b/include/Sensors.h deleted file mode 100644 index 84a96345..00000000 --- a/include/Sensors.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void sensors_init(); \ No newline at end of file diff --git a/include/Strings_.h b/include/Strings_.h index 106957e0..21865168 100644 --- a/include/Strings_.h +++ b/include/Strings_.h @@ -1,5 +1,6 @@ #pragma once +//Strings // #include #include @@ -135,4 +136,4 @@ inline void char_array::printinput() { inline void char_array::changedefaultsize() { printf("Input new default input string size: "); scanf("%i", charinput); -} \ No newline at end of file +} diff --git a/include/TimeUtils.h b/include/TimeUtils.h deleted file mode 100644 index 6527d93d..00000000 --- a/include/TimeUtils.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include - -extern int timeToMin(String Time); -extern String GetDataDigital(); -extern String GetDate(); -extern String GetTimeWOsec(); -extern String GetTime(); -extern String GetTimeUnix(); -extern void reconfigTime(); -extern void saveConfig(); -extern String GetTimeUnix(); -extern void time_check(); diff --git a/include/Timers.h b/include/Timers.h deleted file mode 100644 index 0b74a588..00000000 --- a/include/Timers.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include - -extern void Timer_countdown_init(); -extern void addTimer(String number, String time); -extern int readTimer(int number); -extern void delTimer(String number); -extern void timerStop(); -extern void delTimer(String number); \ No newline at end of file diff --git a/include/Upgrade.h b/include/Upgrade.h deleted file mode 100644 index 6a399da7..00000000 --- a/include/Upgrade.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -extern void initUpgrade(); diff --git a/include/WiFiUtils.h b/include/WiFiUtils.h deleted file mode 100644 index de80d0e0..00000000 --- a/include/WiFiUtils.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -extern bool StartAPMode(); -extern void ROUTER_Connecting(); \ No newline at end of file diff --git a/include/Widgets.h b/include/Widgets.h deleted file mode 100644 index fdb7e103..00000000 --- a/include/Widgets.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include - -extern void createWidget(String widget_name, String page_name, String page_number, String file, String topic); -extern void createWidgetParam(String widget_name, String page_name, String page_number, String file, String topic, String name1, String param1, String name2, String param2, String name3, String param3); -extern void choose_widget_and_create(String widget_name, String page_name, String page_number, String type, String topik); -extern void createChart(String widget_name, String page_name, String page_number, String file, String topic, String maxCount); diff --git a/include/i2c_bus.h b/include/i2c_bus.h deleted file mode 100644 index 68440aae..00000000 --- a/include/i2c_bus.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -extern void do_i2c_scanning(); - -extern String i2c_scan(); \ No newline at end of file diff --git a/include/main.h b/include/main.h deleted file mode 100644 index 27d7c0f7..00000000 --- a/include/main.h +++ /dev/null @@ -1,31 +0,0 @@ - -#pragma once - -#include - -void getMemoryLoad(String text); - -extern String jsonReadStr(String& json, String name); -extern int jsonReadInt(String& json, String name); -extern String jsonWriteInt(String& json, String name, int volume); -extern String jsonWriteStr(String& json, String name, String volume); -extern void saveConfig(); -extern String jsonWriteFloat(String& json, String name, float volume); - -extern String getURL(String urls); - -extern String writeFile(String fileName, String strings); -extern String readFile(String fileName, size_t len); -extern String addFile(String fileName, String strings); - -extern String selectFromMarkerToMarker(String str, String found, int number); -extern String selectToMarker(String str, String found); -extern String deleteAfterDelimiter(String str, String found); -extern String deleteBeforeDelimiter(String str, String found); -extern String deleteBeforeDelimiterTo(String str, String found); - -extern void servo_(); -extern boolean isDigitStr(String str); -extern String jsonWriteStr(String& json, String name, String volume); - -extern void led_blink(String satus); \ No newline at end of file diff --git a/include/push_pushingbox.h b/include/push_pushingbox.h index ff3f9cf9..1d03b9ca 100644 --- a/include/push_pushingbox.h +++ b/include/push_pushingbox.h @@ -1,7 +1,6 @@ #pragma once -#include "main.h" -#include "set.h" +#include "Global.h" inline void Push_init() { server.on("/pushingboxDate", HTTP_GET, [](AsyncWebServerRequest* request) { diff --git a/lib/ESPrelay/.gitattributes b/lib/ESPrelay/.gitattributes deleted file mode 100644 index bdb0cabc..00000000 --- a/lib/ESPrelay/.gitattributes +++ /dev/null @@ -1,17 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.cs diff=csharp - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/lib/ESPrelay/TheThingsMQTT.cpp b/lib/ESPrelay/TheThingsMQTT.cpp deleted file mode 100644 index 4faf78f3..00000000 --- a/lib/ESPrelay/TheThingsMQTT.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* -Copyright (c) 2016 TheThings. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Original Maker: Mateo Velez - Metavix for TheThings Inc -Modified and Maintened by: Jose Garcia - TheThings Inc - -*/ - -#include "TheThingsMQTT.h" - - -TheThings::TheThings(char* token){ - initialize(token, NULL); -} - - -TheThings::TheThings(char* token, char* clientName) { - initialize(token, clientName); -} - - -void TheThings::begin(void (*callback)(char*,uint8_t*,unsigned int)) { - this->callback = callback; - _client.setServer(_server, MQTT_PORT); - _client.setCallback(callback); -} - - -bool TheThings::add(char* variableLabel, float value) { - return add(variableLabel, value, "NULL", "NULL"); -} - - -bool TheThings::add(char* variableLabel, float value, char *context) { - return add(variableLabel, value, context, "NULL"); -} - - -bool TheThings::add(char* variableLabel, float value, char *context, char *timestamp) { - (val+currentValue)->_variableLabel = variableLabel; - (val+currentValue)->_value = value; - (val+currentValue)->_context = context; - (val+currentValue)->_timestamp = timestamp; - currentValue++; - if (currentValue > MAX_VALUES) { - Serial.println(F("You are sending more than the maximum of consecutive variables")); - currentValue = MAX_VALUES; - } - return true; -} - - -bool TheThings::connected(){ - return _client.connected(); -} - - -char* TheThings::getMac(){ - // Obtains the MAC of the device - Serial.println("entra"); - byte mac[6]; - WiFi.macAddress(mac); - char macAddr[18]; - sprintf(macAddr, "%2X%2X%2X%2X%2X%2X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - return macAddr; -} - - -void TheThings::initialize(char* token, char* clientName){ - _server = SERVER; - _token = token; - currentValue = 0; - val = (Value *)malloc(MAX_VALUES*sizeof(Value)); - if(clientName!=NULL){ - _clientName = clientName; - } -} - - -bool TheThings::loop() { - if (!_client.connected()) { - reconnect(); - } - return _client.loop(); -} - - -void TheThings::reconnect() { - while (!_client.connected()) { - Serial.print("Attempting MQTT connection..."); - if (_client.connect(_clientName, _token, NULL)) { - Serial.println("connected"); - break; - } else { - Serial.print("failed, rc="); - Serial.print(_client.state()); - Serial.println(" try again in 3 seconds"); - delay(3000); - } - } -} - - -void TheThings::setDebug(bool debug){ - _debug = debug; -} - - -void TheThings:: setBroker(char* broker){ - if (_debug){ - Serial.println("Broker set for Business Account"); - } - _server = broker; -} - - -bool TheThings::subscribe() { - char topic[150]; - sprintf(topic, "%s%s", FIRST_PART_TOPIC, _token); - if (!_client.connected()) { - reconnect(); - } - if (_debug){ - Serial.println("Subscribed to: "); - Serial.println(topic); - } - return _client.subscribe(topic); -} - - -bool TheThings::publish() { - - char topic[150]; - char payload[500]; - String str; - sprintf(topic, "%s%s", FIRST_PART_TOPIC, _token); - sprintf(payload, "["); - for (int i = 0; i <= currentValue; ) { - str = String((val+i)->_value, 1); - sprintf(payload,"%s{\"key\":\"%s\",\"value\":%s",payload,(val+i)->_variableLabel, str.c_str()); - if ((val+i)->_timestamp != "NULL") { - sprintf(payload, "%s, \"timestamp\": %s", payload, (val+i)->_timestamp); - } - if ((val+i)->_context != "NULL") { - sprintf(payload, "%s, \"context\": {%s}", payload, (val+i)->_context); - } - i++; - if (i >= currentValue) { - sprintf(payload, "%s}]", payload); - break; - } else { - sprintf(payload, "%s},", payload); - } - } - if (_debug){ - Serial.println("publishing to TOPIC: "); - Serial.println(topic); - Serial.print("JSON dict: "); - Serial.println(payload); - } - currentValue = 0; - return _client.publish(topic, payload, 512); -} - - -bool TheThings::wifiConnection(char* ssid, char* pass) { - WiFi.begin(ssid, pass); - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); - } - Serial.println(F("WiFi connected")); - Serial.println(F("IP address: ")); - Serial.println(WiFi.localIP()); - if(_clientName==NULL){ - _clientName = getMac(); - } -} - -bool TheThings::wifiConnection2() { - WiFiManager wifiManager; - wifiManager.setTimeout(180); - - //if(!wifiManager.autoConnect("AutoConnectAP")) { - if(!wifiManager.autoConnect()) { - Serial.println("failed to connect and hit timeout"); - delay(3000); - ESP.reset(); - delay(5000); - } -} - -int TheThings::state() { - return _client.state(); -} - diff --git a/lib/ESPrelay/TheThingsMQTT.h b/lib/ESPrelay/TheThingsMQTT.h deleted file mode 100644 index c176003d..00000000 --- a/lib/ESPrelay/TheThingsMQTT.h +++ /dev/null @@ -1,58 +0,0 @@ - -#ifndef TheThingsMQTT_H -#define TheThingsMQTT_H -//#include -#include -#include - -#define MQTT_PORT 1883 -#define SERVER "mqtt.thethings.io" -#define MAX_VALUES 5 -#define FIRST_PART_TOPIC "v2/things/" - -#define META_DEBUG Serial - -typedef struct Value { - char* _variableLabel; - float _value; - char* _context; - char* _timestamp; -} Value; - -class TheThings { - private: - void (*callback)(char*, uint8_t*, unsigned int); - char* getMac(); - void initialize(char* token, char* clientName); - WiFiClient espClient; - PubSubClient _client = PubSubClient(espClient); - WiFiManager wifiManager; - char* _clientName = NULL; - bool _debug = false; - uint8_t currentValue; - char* _password; - char* _server; - char* _ssid; - char* _token; - Value* val; - - public: - TheThings(char* token); - TheThings(char* token, char* clientName); - bool add(char* variableLabel, float value); - bool add(char* variableLabel, float value, char* context); - bool add(char* variableLabel, float value, char* context, char* timestamp); - void begin(void (*callback)(char*, uint8_t*, unsigned int)); - bool connected(); - bool loop(); - bool subscribe(); - bool publish(); - void setBroker(char* broker); - void reconnect(); - void setDebug(bool debug); - bool wifiConnection(char* ssid, char* pass); - bool wifiConnection2(); - int state(); -}; - -#endif diff --git a/lib/ESPrelay/TickerScheduler.h b/lib/ESPrelay/TickerScheduler.h deleted file mode 100644 index 71acb3b0..00000000 --- a/lib/ESPrelay/TickerScheduler.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include -#include - -class Ticker { - typedef void (*ticker_callback_t)(bool *); - - private: - bool is_attached = false; - uint32_t period = 0; - uint32_t last_tick = 0; - ticker_callback_t callback; - bool *callback_argument; - - public: - void Tick() { - if (is_attached && millis() - last_tick >= period) { - callback(callback_argument); - last_tick = millis(); - } - } - - void detach() { - this->is_attached = true; - } - - template - void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg) { - this->period = milliseconds; - this->callback = callback; - this->callback_argument = arg; - this->is_attached = true; - } -}; - -#ifdef ARDUINO_ARCH_ESP8266 -#include - -#include -#endif - -void tickerFlagHandle(volatile bool *flag); - -#ifdef _GLIBCXX_FUNCTIONAL -typedef std::function tscallback_t; -#else -typedef void (*tscallback_t)(void *); -#endif - -struct TickerSchedulerItem { - Ticker t; - volatile bool flag = false; - tscallback_t cb; - void *cb_arg; - uint32_t period; - volatile bool is_used = false; -}; - -class TickerScheduler { - private: - uint8_t size; - TickerSchedulerItem *items = NULL; - - void handleTicker(tscallback_t, void *, volatile bool *flag); - static void handleTickerFlag(volatile bool *flag); - - public: - TickerScheduler(uint8_t size); - ~TickerScheduler(); - - bool add(uint8_t i, uint32_t period, tscallback_t, void *, boolean shouldFireNow = false); - bool remove(uint8_t i); - bool enable(uint8_t i); - bool disable(uint8_t i); - void enableAll(); - void disableAll(); - void update(); -}; diff --git a/lib/ESPrelay/subscribe_and_publish.ino b/lib/ESPrelay/subscribe_and_publish.ino deleted file mode 100644 index 3148ccd4..00000000 --- a/lib/ESPrelay/subscribe_and_publish.ino +++ /dev/null @@ -1,182 +0,0 @@ -/**************************************** - * Include Libraries - ****************************************/ -#include "TheThingsMQTT.h" -#include "TickerScheduler.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -/**************************************** - * Define Constants - ****************************************/ -#define TOKEN "" // Your TheThings TOKEN -#define WIFINAME "" //Your SSID -#define WIFIPASS "" // Your Wifi Pass - -TheThings client(TOKEN); - -#define DHTPIN 14 // Pin which is cosnnected to the DHT sensor. -// Uncomment the type of sensor in use: -//#define DHTTYPE DHT11 // DHT 11 -#define DHTTYPE DHT22 // DHT 22 (AM2302) -//#define DHTTYPE DHT21 // DHT 21 (AM2301) - -DHT_Unified dht(DHTPIN, DHTTYPE); - -uint32_t delayMS; -#define TRIGGER_PIN 0 -#define FRECUENCY 2000 -char *AP="TEST_BQ"; -String prefix="rel"; -const char WiFiAPPSK[] = "prueba"; - -WiFiManager wifiManager; - -#define RELAY1 12 -#define RELAY2 13 - -#define MEASUREMENT_TIME 30000 // Time in milisecons - -float Temperature,Humidity; -TickerScheduler ts(1); - -/**************************************** - * Auxiliar Functions - ****************************************/ - -//void configWiFi(){ -// wifiManager.resetSettings(); -// if(!wifiManager.autoConnect(AP,WiFiAPPSK)) { -// Serial.println("Reconfiguration called"); -// delay(3000); -// //reset and try again, or maybe put it to deep sleep -// ESP.reset(); -// delay(15000); -// } -//} - -void callback(char* topic, byte* payload, unsigned int length) { - Serial.print("Message arrived"); - // handle message arrived - String text = ""; - for (int i = 0; i < length; i++) - text.concat((char)payload[i]); - Serial.println(text); - text.replace(" ", ""); - text.toUpperCase(); - if (text.indexOf("\"KEY\":\"REL1\"") >= 0) { - if (text.indexOf("\"VALUE\":\"ON\"") >= 0) digitalWrite(RELAY1,HIGH); - else if (text.indexOf("\"VALUE\":\"OFF\"") >= 0) digitalWrite(RELAY1,LOW); - } - else if (text.indexOf("\"KEY\":\"REL2\"") >= 0) { - if (text.indexOf("\"VALUE\":\"ON\"") >= 0) digitalWrite(RELAY2,HIGH); - else if (text.indexOf("\"VALUE\":\"OFF\"") >= 0) digitalWrite(RELAY2,LOW); - } -} - -float temperatureMeasurement(sensors_event_t event, DHT_Unified dht){ - // Get temperature event and print its value. - dht.temperature().getEvent(&event); - if (isnan(event.temperature)) { - Serial.println("Error reading temperature!"); - } - else { - Serial.print("Temperature: "); - Serial.print(event.temperature); - Serial.println(" *C"); - return event.temperature; - } -} - -float humidityMeasurement(sensors_event_t event, DHT_Unified dht){ - // Get humidity event and print its value. - dht.humidity().getEvent(&event); - if (isnan(event.relative_humidity)) { - Serial.println("Error reading humidity!"); - } - else { - Serial.print("Humidity: "); - Serial.print(event.relative_humidity); - Serial.println("%"); - return event.relative_humidity; - } -} - -void measureAndSend(){ - sensors_event_t event; - Temperature=temperatureMeasurement(event,dht); - Humidity=humidityMeasurement(event,dht); - client.add("Temperature", Temperature); - client.add("Humidity", Humidity); - client.publish(); -} - -/**************************************** - * Main Functions - ****************************************/ - - -void setup() { - // put your setup code here, to run once: - Serial.begin(115200); - delay(100); - pinMode(RELAY1,OUTPUT); - pinMode(RELAY2,OUTPUT); - - dht.begin(); - sensor_t sensor; - - - -// pinMode(TRIGGER_PIN, INPUT); -// attachInterrupt(digitalPinToInterrupt(TRIGGER_PIN), configWiFi, RISING); -// -// //sets timeout until configuration portal gets turned off -// //useful to make it all retry or go to sleep -// //in seconds -// wifiManager.setTimeout(280); -// -// //fetches ssid and pass and tries to connect -// //if it does not connect it starts an access point with the specified name -// //here "AutoConnectAP" -// //and goes into a blocking loop awaiting configuration -// if(!wifiManager.autoConnect(AP,WiFiAPPSK)) { -// Serial.println("failed to connect and hit timeout"); -// delay(3000); -// //reset and try again, or maybe put it to deep sleep -// //ESP.reset(); -// delay(FRECUENCY); -// } -// //if you get here you have connected to the WiFi -// Serial.println("connected...yeey :)"); - - client.wifiConnection(WIFINAME, WIFIPASS); - - //client.wifiConnection2(); - client.begin(callback); - client.subscribe(); //Insert the dataSource and Variable's Labels - - ts.add(0, MEASUREMENT_TIME, [&](void*) { measureAndSend(); }, nullptr, false); - ts.enableAll(); - - } - -void loop() { - // put your main code here, to run repeatedly: - ts.update(); - - if(!client.connected()){ - client.reconnect(); - client.subscribe(); //Insert the dataSource and Variable's Labels - } - client.loop(); - -} diff --git a/lib/TickerScheduler/README.md b/lib/TickerScheduler/README.md new file mode 100644 index 00000000..33f0182e --- /dev/null +++ b/lib/TickerScheduler/README.md @@ -0,0 +1,81 @@ +# TickerScheduler +Simple scheduler for ESP8266 Arduino based on Ticker + +### Initialization + +`TickerScheduler(uint size);` + +| Param | Description | +| --- | --- | +| size | Amount of task Tickers to initialize | + +**Example**: + +`TickerScheduler ts(5)` + + +### Add task + +`boolean add(uint i, uint32_t period, tscallback_t f, boolean shouldFireNow = false); ` + +| Param | Description | +| --- | --- | +| i | Task ID | +| period | Task execution period in ms | +| f | Task callback | +| shouldFireNow| `true` if you want to execute task right after first scheduler update or wait next scheduled start | + +**Returns**: + +`true` - task added sucessfully + +`false` - task was not added + +**Example**: + +`ts.add(0, 3000, sendData)` + +### Execute scheduler in `loop()` + +`ts.update()` + +### Remove task + +`boolean remove(uint i)` + +**Returns**: + +`true` - task removed sucessfully + +`false` - task was not removed + +| Param | Description | +| --- | --- | +| i | Task ID | + +### Enable/Disable task + +`boolean enable(uint i)` + +`boolean disable(uint i)` + +**Returns**: + +`true` - task enabled/disabled sucessfully + +`false` - task was not enabled/disabled + +| Param | Description | +| --- | --- | +| i | Task ID | + +### Enable / disable all tasks + +`void enableAll()` + +`void disableAll()` + +### TODO + +* Task callback parameters support +* ... diff --git a/lib/ESPrelay/TickerScheduler.cpp b/lib/TickerScheduler/TickerScheduler.cpp similarity index 91% rename from lib/ESPrelay/TickerScheduler.cpp rename to lib/TickerScheduler/TickerScheduler.cpp index b3badc25..af47ffa1 100644 --- a/lib/ESPrelay/TickerScheduler.cpp +++ b/lib/TickerScheduler/TickerScheduler.cpp @@ -19,13 +19,13 @@ TickerScheduler::~TickerScheduler() this->size = 0; } -void TickerScheduler::handleTickerFlag(volatile bool * flag) +void TickerScheduler::handleTickerFlag(bool * flag) { if (!*flag) *flag = true; } -void TickerScheduler::handleTicker(tscallback_t f, void * arg, volatile bool * flag) +void TickerScheduler::handleTicker(tscallback_t f, void * arg, bool * flag) { if (*flag) { @@ -81,7 +81,7 @@ bool TickerScheduler::enable(uint8_t i) if (i >= this->size || !this->items[i].is_used) return false; - volatile bool * flag = &this->items[i].flag; + bool * flag = &this->items[i].flag; this->items[i].t.attach_ms(this->items[i].period, TickerScheduler::handleTickerFlag, flag); return true; diff --git a/lib/TickerScheduler/TickerScheduler.h b/lib/TickerScheduler/TickerScheduler.h new file mode 100644 index 00000000..98ae1f05 --- /dev/null +++ b/lib/TickerScheduler/TickerScheduler.h @@ -0,0 +1,91 @@ +#ifndef TICKERSCHEDULER_H +#define TICKERSCHEDULER_H + +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#endif +#include + + +#ifdef ARDUINO_ARCH_AVR +class Ticker +{ + typedef void(*ticker_callback_t)(bool*); + +private: + bool is_attached = false; + uint32_t period = 0; + uint32_t last_tick = 0; + ticker_callback_t callback; + bool *callback_argument; +public: + void Tick() + { + if (is_attached && millis() - last_tick >= period) + { + callback(callback_argument); + last_tick = millis(); + } + } + + void detach() + { + this->is_attached = true; + } + + template void attach_ms(uint32_t milliseconds, void(*callback)(TArg), TArg arg) + { + this->period = milliseconds; + this->callback = callback; + this->callback_argument = arg; + this->is_attached = true; + } +}; +#endif + +//#ifdef ARDUINO_ARCH_ESP8266 +#include +#include +//#endif + +void tickerFlagHandle(volatile bool * flag); + +#ifdef _GLIBCXX_FUNCTIONAL +typedef std::function tscallback_t; +#else +typedef void(*tscallback_t)(void*); +#endif + +struct TickerSchedulerItem +{ + Ticker t; + bool flag = false; + tscallback_t cb; + void * cb_arg; + uint32_t period; + volatile bool is_used = false; +}; + +class TickerScheduler +{ +private: + uint8_t size; + TickerSchedulerItem *items = NULL; + + void handleTicker(tscallback_t, void *, bool * flag); + static void handleTickerFlag(bool * flag); + +public: + TickerScheduler(uint8_t size); + ~TickerScheduler(); + + bool add(uint8_t i, uint32_t period, tscallback_t, void *, boolean shouldFireNow = false); + bool remove(uint8_t i); + bool enable(uint8_t i); + bool disable(uint8_t i); + void enableAll(); + void disableAll(); + void update(); +}; + +#endif diff --git a/lib/TickerScheduler/example/blink/blink/blink.ino b/lib/TickerScheduler/example/blink/blink/blink.ino new file mode 100644 index 00000000..49afc470 --- /dev/null +++ b/lib/TickerScheduler/example/blink/blink/blink.ino @@ -0,0 +1,29 @@ +#include + +#define LED1 4 +#define LED2 5 + +TickerScheduler ts(2); + +void blink1() { + digitalWrite(LED1, !digitalRead(LED1)); +} + +void blink2() { + digitalWrite(LED2, !digitalRead(LED2)); +} + +void setup() { + pinMode(LED1, OUTPUT); + digitalWrite(LED1, LOW); + + pinMode(LED2, OUTPUT); + digitalWrite(LED2, LOW); + + ts.add(0, 1000, [&](void *) { blink1(); }, nullptr, true); + ts.add(1, 3000, [&](void *) { blink2(); }, nullptr, true); +} + +void loop() { + ts.update(); +} diff --git a/platformio.ini b/platformio.ini index edffafe0..84ab6931 100644 --- a/platformio.ini +++ b/platformio.ini @@ -17,9 +17,8 @@ lib_deps= ESP32Servo Bounce2 PubSubClient - iothubclientlonghaultests_bld ESP8266-StringCommand - + [env:esp32dev] platform = espressif32 board = esp32dev diff --git a/src/Cmd.cpp b/src/Cmd.cpp index 8708d58f..c9a0c566 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -1,11 +1,6 @@ -#include "Cmd.h" +#include "Global.h" -#include "Scenario.h" -#include "TimeUtils.h" -#include "Widgets.h" -#include "main.h" #include "push_pushingbox.h" -#include "set.h" void CMD_init() { sCmd.addCommand("button", button); @@ -74,8 +69,8 @@ void CMD_init() { sCmd.addCommand("inputTime", inputTime); sCmd.addCommand("timeSet", timeSet); - sCmd.addCommand("timerStart", timerStart); - sCmd.addCommand("timerStop", timerStop); + sCmd.addCommand("timerStart", timerStart_); + sCmd.addCommand("timerStop", timerStop_); sCmd.addCommand("text", text); sCmd.addCommand("textSet", textSet); diff --git a/src/FileSystem.cpp b/src/FileSystem.cpp index 2f2a8f61..92eb6f31 100644 --- a/src/FileSystem.cpp +++ b/src/FileSystem.cpp @@ -1,9 +1,4 @@ - -#include -#include - -#include "main.h" -#include "set.h" +#include "Global.h" void File_system_init() { Serial.begin(115200); diff --git a/src/Init.cpp b/src/Init.cpp index 7d507425..9a81f8a8 100644 --- a/src/Init.cpp +++ b/src/Init.cpp @@ -1,11 +1,4 @@ -#include "Init.h" - -#include "Logging.h" -#include "Scenario.h" -#include "Timers.h" -#include "Widgets.h" -#include "main.h" -#include "set.h" +#include "Global.h" void All_init() { server.on("/init", HTTP_GET, [](AsyncWebServerRequest* request) { @@ -73,7 +66,7 @@ void Device_init() { int array_sz = sizeof(sensors_reading_map) / sizeof(sensors_reading_map[0]); - for (int i = 0; i <= array_sz; i++) { + for (int i = 0; i < array_sz; i++) { sensors_reading_map[i] = 0; } diff --git a/src/Logging.cpp b/src/Logging.cpp index b23028ce..996786ce 100644 --- a/src/Logging.cpp +++ b/src/Logging.cpp @@ -1,10 +1,6 @@ -#include "Logging.h" +#include "Global.h" -#include "Mqtt.h" -#include "TimeUtils.h" -#include "Widgets.h" -#include "main.h" -#include "set.h" +void sendLogData(String file, String topic); #ifdef logging_enable //===============================================Логирование============================================================ @@ -105,7 +101,8 @@ void choose_log_date_and_send() { String all_line = logging_value_names_list; while (all_line.length() != 0) { String tmp = selectToMarker(all_line, ","); - sendLogData("log." + tmp + ".txt", tmp + "_ch"); + sendLogData("log." + tmp + ".txt", tmp + "_ch" + ); all_line = deleteBeforeDelimiter(all_line, ","); } all_line = ""; diff --git a/src/Mqtt.cpp b/src/Mqtt.cpp index 6a947ae8..feb78d41 100644 --- a/src/Mqtt.cpp +++ b/src/Mqtt.cpp @@ -1,10 +1,11 @@ -#include "Mqtt.h" +#include "Global.h" -#include - -#include "WiFi.h" -#include "main.h" -#include "set.h" +void callback(char* topic, byte* payload, unsigned int length); +String stateMQTT(); +void sendAllData(); +void sendAllWigets(); +void sendSTATUS(String topik, String state); +void outcoming_date(); //===============================================ИНИЦИАЛИЗАЦИЯ================================================ void MQTT_init() { @@ -217,7 +218,7 @@ void sendAllWigets() { } configFile.seek(0, SeekSet); //поставим курсор в начало файла while (configFile.position() != configFile.size()) { - String widget_to_send = configFile.readStringUntil("\r\n"); + String widget_to_send = configFile.readStringUntil('\n'); Serial.println("[V] " + widget_to_send); sendMQTT("config", widget_to_send); } diff --git a/src/Scenario.cpp b/src/Scenario.cpp index 85c023c6..12294285 100644 --- a/src/Scenario.cpp +++ b/src/Scenario.cpp @@ -1,7 +1,4 @@ -#include "Scenario.h" - -#include "main.h" -#include "set.h" +#include "Global.h" void handleScenario() { if (jsonReadStr(configSetup, "scenario") == "1") { diff --git a/src/Sensors.cpp b/src/Sensors.cpp index d5cc2319..890dc2a2 100644 --- a/src/Sensors.cpp +++ b/src/Sensors.cpp @@ -1,6 +1,4 @@ -#include "Sensors.h" - -#include "set.h" +#include "Global.h" void sensors_init() { ts.add( diff --git a/src/TimeUtils.cpp b/src/TimeUtils.cpp index b64a5a3f..4f7036d0 100644 --- a/src/TimeUtils.cpp +++ b/src/TimeUtils.cpp @@ -1,7 +1,4 @@ -#include "TimeUtils.h" - -#include "main.h" -#include "set.h" +#include "Global.h" void Time_Init() { server.on("/time", HTTP_GET, [](AsyncWebServerRequest* request) { diff --git a/src/Timers.cpp b/src/Timers.cpp index c2ff61b4..6c249891 100644 --- a/src/Timers.cpp +++ b/src/Timers.cpp @@ -1,8 +1,4 @@ -#include "Timers.h" - -#include "Scenario.h" -#include "main.h" -#include "set.h" +#include "Global.h" void Timer_countdown_init() { ts.add( @@ -33,7 +29,7 @@ void Timer_countdown_init() { nullptr, true); } -void timerStart() { +void timerStart_() { String number = sCmd.next(); String period_of_time = sCmd.next(); String type = sCmd.next(); @@ -64,7 +60,7 @@ void addTimer(String number, String time) { //Serial.println("ura"); } -void timerStop() { +void timerStop_() { String number = sCmd.next(); delTimer(number); } diff --git a/src/Upgrade.cpp b/src/Upgrade.cpp index 5a815aee..8d83c739 100644 --- a/src/Upgrade.cpp +++ b/src/Upgrade.cpp @@ -1,7 +1,4 @@ -#include "Upgrade.h" - -#include "main.h" -#include "set.h" +#include "Global.h" static const char* UPGRADE_URL PROGMEM = "http://91.204.228.124:1100/update/"; @@ -20,11 +17,11 @@ void initUpgrade() { String last_version = WiFi.status() == WL_CONNECTED ? getURL(getUpgradeUrl()) : ""; jsonWriteStr(configSetup, "last_version", last_version); - Serial.printf("[i] Last firmware version: %s\n", last_version); + Serial.printf("[i] Last firmware version: %s\n", last_version.c_str()); server.on("/check", HTTP_GET, [last_version](AsyncWebServerRequest* request) { upgrade_url = true; - Serial.printf("[i] Last firmware version: %s\n", last_version); + Serial.printf("[i] Last firmware version: %s\n", last_version.c_str()); String tmp = "{}"; if (WiFi.status() == WL_CONNECTED) { if (mb_4_of_memory) { diff --git a/src/Web_server.cpp b/src/Web_server.cpp index 98a6b2b5..3bb2070e 100644 --- a/src/Web_server.cpp +++ b/src/Web_server.cpp @@ -1,5 +1,4 @@ -#include "main.h" -#include "set.h" +#include "Global.h" void Web_server_init() { #ifdef OTA_enable diff --git a/src/WiFiUtils.cpp b/src/WiFiUtils.cpp index 15ebc535..ffb7b783 100644 --- a/src/WiFiUtils.cpp +++ b/src/WiFiUtils.cpp @@ -1,53 +1,64 @@ -#include "main.h" -#include "set.h" +#include "Global.h" -void WIFI_init() { +boolean RouterFind(String ssid); + +void WIFI_init() +{ // --------------------Получаем ssid password со страницы - server.on("/ssid", HTTP_GET, [](AsyncWebServerRequest* request) { - if (request->hasArg("ssid")) { + server.on("/ssid", HTTP_GET, [](AsyncWebServerRequest *request) { + if (request->hasArg("ssid")) + { jsonWriteStr(configSetup, "ssid", request->getParam("ssid")->value()); } - if (request->hasArg("password")) { + if (request->hasArg("password")) + { jsonWriteStr(configSetup, "password", request->getParam("password")->value()); } - saveConfig(); // Функция сохранения данных во Flash - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении + saveConfig(); // Функция сохранения данных во Flash + request->send(200, "text/text", "OK"); // отправляем ответ о выполнении }); // --------------------Получаем ssidAP passwordAP со страницы - server.on("/ssidap", HTTP_GET, [](AsyncWebServerRequest* request) { - if (request->hasArg("ssidAP")) { + server.on("/ssidap", HTTP_GET, [](AsyncWebServerRequest *request) { + if (request->hasArg("ssidAP")) + { jsonWriteStr(configSetup, "ssidAP", request->getParam("ssidAP")->value()); } - if (request->hasArg("passwordAP")) { + if (request->hasArg("passwordAP")) + { jsonWriteStr(configSetup, "passwordAP", request->getParam("passwordAP")->value()); } - saveConfig(); // Функция сохранения данных во Flash - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении + saveConfig(); // Функция сохранения данных во Flash + request->send(200, "text/text", "OK"); // отправляем ответ о выполнении }); // --------------------Получаем логин и пароль для web со страницы - server.on("/web", HTTP_GET, [](AsyncWebServerRequest* request) { - if (request->hasArg("web_login")) { + server.on("/web", HTTP_GET, [](AsyncWebServerRequest *request) { + if (request->hasArg("web_login")) + { jsonWriteStr(configSetup, "web_login", request->getParam("web_login")->value()); } - if (request->hasArg("web_pass")) { + if (request->hasArg("web_pass")) + { jsonWriteStr(configSetup, "web_pass", request->getParam("web_pass")->value()); } - saveConfig(); // Функция сохранения данных во Flash + saveConfig(); // Функция сохранения данных во Flash //Web_server_init(); - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении + request->send(200, "text/text", "OK"); // отправляем ответ о выполнении }); - server.on("/restart", HTTP_GET, [](AsyncWebServerRequest* request) { - if (request->hasArg("device")) { - if (request->getParam("device")->value() == "ok") ESP.restart(); + server.on("/restart", HTTP_GET, [](AsyncWebServerRequest *request) { + if (request->hasArg("device")) + { + if (request->getParam("device")->value() == "ok") + ESP.restart(); } - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении + request->send(200, "text/text", "OK"); // отправляем ответ о выполнении }); ROUTER_Connecting(); } -void ROUTER_Connecting() { +void ROUTER_Connecting() +{ led_blink("slow"); WiFi.mode(WIFI_STA); @@ -57,17 +68,22 @@ void ROUTER_Connecting() { String _password = jsonReadStr(configSetup, "password"); //WiFi.persistent(false); - if (_ssid == "" && _password == "") { + if (_ssid == "" && _password == "") + { WiFi.begin(); - } else { + } + else + { WiFi.begin(_ssid.c_str(), _password.c_str()); Serial.print("ssid: "); Serial.println(_ssid); } // Делаем проверку подключения до тех пор пока счетчик tries // не станет равен нулю или не получим подключение - while (--tries && WiFi.status() != WL_CONNECTED) { - if (WiFi.status() == WL_CONNECT_FAILED) { + while (--tries && WiFi.status() != WL_CONNECTED) + { + if (WiFi.status() == WL_CONNECT_FAILED) + { Serial.println("[E] password is not correct"); tries = 1; jsonWriteInt(optionJson, "pass_status", 1); @@ -77,9 +93,12 @@ void ROUTER_Connecting() { } Serial.println(); - if (WiFi.status() != WL_CONNECTED) { + if (WiFi.status() != WL_CONNECTED) + { StartAPMode(); - } else { + } + else + { Serial.println("[V] WiFi connected"); Serial.print("[V] IP address: http://"); Serial.print(WiFi.localIP()); @@ -90,7 +109,8 @@ void ROUTER_Connecting() { } } -bool StartAPMode() { +bool StartAPMode() +{ Serial.println("WiFi up AP"); WiFi.disconnect(); @@ -105,11 +125,13 @@ bool StartAPMode() { Serial.println(myIP); jsonWriteStr(configJson, "ip", myIP.toString()); - if (jsonReadInt(optionJson, "pass_status") != 1) { + if (jsonReadInt(optionJson, "pass_status") != 1) + { ts.add( - ROUTER_SEARCHING, 10 * 1000, [&](void*) { + ROUTER_SEARCHING, 10 * 1000, [&](void *) { Serial.println("->try find router"); - if (RouterFind(jsonReadStr(configSetup, "ssid"))) { + if (RouterFind(jsonReadStr(configSetup, "ssid"))) + { ts.remove(ROUTER_SEARCHING); WiFi.scanDelete(); ROUTER_Connecting(); @@ -121,43 +143,52 @@ bool StartAPMode() { return true; } -boolean RouterFind(String ssid) { +boolean RouterFind(String ssid) +{ + bool res = false; + int n = WiFi.scanComplete(); Serial.println("n = " + String(n)); - if (n == -2) { //Сканирование не было запущено, запускаем + if (n == -2) + { //Сканирование не было запущено, запускаем Serial.println("[WIFI][i] scanning has not been triggered, starting scanning"); - WiFi.scanNetworks(true, false); //async, show_hidden - return false; + WiFi.scanNetworks(true, false); //async, show_hidde } - if (n == -1) { //Сканирование все еще выполняется + else if (n == -1) + { //Сканирование все еще выполняется Serial.println("[WIFI][i] scanning still in progress"); - return false; } - if (n == 0) { //ни одна сеть не найдена + else if (n == 0) + { //ни одна сеть не найдена Serial.println("[WIFI][i] no any wifi sations, starting scanning"); WiFi.scanNetworks(true, false); - return false; } - if (n > 0) { - for (int i = 0; i <= n; i++) { - if (WiFi.SSID(i) == ssid) { + else if (n > 0) + { + for (int i = 0; i <= n; i++) + { + if (WiFi.SSID(i) == ssid) + { WiFi.scanDelete(); - return true; - } else { + res = true; + } + else + { Serial.print(i); Serial.print(")"); - //Serial.print(ssid); - //Serial.print("<=>"); - if (i == n) { + if (i == n) + { Serial.print(WiFi.SSID(i)); Serial.println("; "); - } else { + } + else + { Serial.print(WiFi.SSID(i)); Serial.println("; "); } } } WiFi.scanDelete(); - return false; } + return res; } diff --git a/src/Widgets.cpp b/src/Widgets.cpp index b9de8aa5..b7d841aa 100644 --- a/src/Widgets.cpp +++ b/src/Widgets.cpp @@ -1,7 +1,4 @@ -#include "Widgets.h" - -#include "main.h" -#include "set.h" +#include "Global.h" void createWidget(String widget_name, String page_name, String page_number, String file, String topic) { String widget; diff --git a/src/i2c_bus.cpp b/src/i2c_bus.cpp index e44155c8..b48335c6 100644 --- a/src/i2c_bus.cpp +++ b/src/i2c_bus.cpp @@ -1,7 +1,4 @@ -#include "i2c_bus.h" - -#include "main.h" -#include "set.h" +#include "Global.h" void do_i2c_scanning() { if (i2c_scanning) { diff --git a/src/iot_firmware.cpp b/src/iot_firmware.cpp index f265ebcd..b13f4b00 100644 --- a/src/iot_firmware.cpp +++ b/src/iot_firmware.cpp @@ -1,7 +1,4 @@ -#include "Cmd.h" -#include "FileSystem.h" -#include "Sensors.h" -#include "set.h" +#include "Global.h" void setup() { File_system_init(); diff --git a/src/main.cpp b/src/main.cpp index 7b923734..025f81f1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,4 @@ -#include "main.h" - -#include "set.h" +#include "Global.h" String jsonReadStr(String& json, String name) { DynamicJsonBuffer jsonBuffer; @@ -61,6 +59,9 @@ void saveConfig() { writeFile("config.json", configSetup); } +//============================================================================================================ +//=============================================STRING=================================================== + // --------Выделяем строку от конца строки до маркера----------------------------------------------------------- String selectToMarkerLast(String str, String found) { int p = str.lastIndexOf(found); @@ -121,25 +122,24 @@ int count(String str, String found) { return i; // Достигли пустой строки и ничего не нашли } + boolean isDigitStr(String str) { - if (str.length() == 1) { - return Digit(str); - } - if (str.length() > 1) { - for (int i = 0; i < str.length(); i++) { - if (!Digit(String(str.charAt(i)))) return false; + for (int i = 0; i < str.length(); i++) { + if (!isDigit(str.charAt(i))) { + return false; } - return true; - } -} -boolean Digit(String str) { - if (str == "0" || str == "1" || str == "2" || str == "3" || str == "4" || str == "5" || str == "6" || str == "7" || str == "8" || str == "9") { - return true; - } else { - return false; } + return str.length(); } +// boolean digit(String str) { +// if (str == "0" || str == "1" || str == "2" || str == "3" || str == "4" || str == "5" || str == "6" || str == "7" || str == "8" || str == "9") { +// return true; +// } else { +// return false; +// } +// } + String getURL(String urls) { String answer = ""; HTTPClient http; @@ -153,10 +153,10 @@ String getURL(String urls) { http.end(); return answer; } -//=================================================================================================================== +//=================================================================================================================== //===========================================FILES=================================================================== // ------------- Добавление файла ----------------------------------------------------------------------------------- -String safeDataToFile(String data, String Folder) { +void safeDataToFile(String data, String Folder) { //String fileName = GetDate(); String fileName; fileName.toLowerCase(); @@ -168,6 +168,7 @@ String safeDataToFile(String data, String Folder) { Serial.println(fileName); jsonWriteStr(configJson, "test", fileName); } + // ------------- Чтение файла в строку ------------------------------------------------------------------------------- String readFile(String fileName, size_t len) { File configFile = SPIFFS.open("/" + fileName, "r"); diff --git a/src/udp.cpp b/src/udp.cpp index 7b5d6928..0ede7729 100644 --- a/src/udp.cpp +++ b/src/udp.cpp @@ -1,3 +1,8 @@ +#include "Global.h" + +void handleUdp_esp32(); +void add_dev_in_list(String fileName, String id, String dev_name, String ip); + #ifdef UDP_enable void UDP_init() { server.on("/udp", HTTP_GET, [](AsyncWebServerRequest * request) { From 5bec53e6c24e71259f777222412c5c036508176a Mon Sep 17 00:00:00 2001 From: Yuri Trikoz Date: Fri, 19 Jun 2020 01:50:19 +0300 Subject: [PATCH 02/17] global vars --- include/Consts.h | 236 +++++--------------------------------- include/Global.h | 195 +++++++++++++++++++++++++++++-- include/push_pushingbox.h | 2 +- src/Global.cpp | 100 ++++++++++++++++ src/Init.cpp | 10 +- 5 files changed, 321 insertions(+), 222 deletions(-) create mode 100644 src/Global.cpp diff --git a/include/Consts.h b/include/Consts.h index e6ced715..e7ede351 100644 --- a/include/Consts.h +++ b/include/Consts.h @@ -1,223 +1,45 @@ -#include +#pragma once + +#define firmware_version "2.3.3" + +/* +* Firmware settings +*/ +#define mb_4_of_memory 1 +#define wifi_mqtt_reconnecting 20000 +#define blink_pin 2 +#define tank_level_times_to_send 10 //после скольки выстрелов делать отправку данных +#define statistics_update 1000 * 60 * 60 * 2 -/******************************************************************* - **********************FIRMWARE SETTINGS**************************** - ******************************************************************/ -String firmware_version = "2.3.3"; -boolean mb_4_of_memory = true; //#define OTA_enable //#define MDNS_enable //#define WS_enable //#define layout_in_ram #define UDP_enable -/*==========================SENSORS===============================*/ + +/* +* Sensor +*/ //#define level_enable //#define analog_enable //#define dallas_enable -//#define dht_enable //подъедает оперативку сука +//#define dht_enable //#define bmp_enable //#define bme_enable -/*=========================LOGGING================================*/ + +/* +* Logging +*/ #define logging_enable -/*==========================GEARS=================================*/ + +/* +* Gears +*/ #define stepper_enable #define servo_enable -/*=========================OTHER==================================*/ + +/* +* Other +*/ #define serial_enable #define push_enable -/*================================================================*/ -#define wifi_mqtt_reconnecting 20000 -#define blink_pin 2 -#define tank_level_times_to_send 10 //после скольки выстрелов делать отправку данных -#define statistics_update 1000 * 60 * 60 * 2 -/*================================================================*/ - -//===============общие библиотеки и объекты=============================== -#include -#include -#include -#include -#include -#include - -//===============библиотеки и объекты для ESP8266======================= -#ifdef ESP8266 -#include -#include -#include -#include -ESP8266HTTPUpdateServer httpUpdater; -#include -WiFiUDP Udp; -#include -Servo myServo1; -Servo myServo2; -#ifdef MDNS_enable -#include -#endif -#endif - -//===============библиотеки и объекты для ESP32=========================== -#ifdef ESP32 -#include -#include -#include -#include -#include -#include -#include -AsyncUDP udp; -#include -Servo myServo1; -Servo myServo2; -#ifdef MDNS_enable -#include -#endif -#endif - -#ifdef OTA_enable -#include -#endif - -AsyncWebServer server(80); - -#ifdef WS_enable -AsyncWebSocket ws("/ws"); -#endif - -AsyncEventSource events("/events"); -#include -#include -enum { ROUTER_SEARCHING, - WIFI_MQTT_CONNECTION_CHECK, - SENSORS, - STEPPER1, - STEPPER2, - LOG1, - LOG2, - LOG3, - LOG4, - LOG5, - TIMER_COUNTDOWN, - TIME, - TIME_SYNC, - STATISTICS, - UDP, - UDP_DB, - TEST }; -TickerScheduler ts(TEST + 1); - -#include -WiFiClient espClient; -PubSubClient client_mqtt(espClient); - -#include -StringCommand sCmd; - -#include -#define NUM_BUTTONS 6 -boolean but[NUM_BUTTONS]; -Bounce *buttons = new Bounce[NUM_BUTTONS]; - -#ifdef level_enable -#include "GyverFilters.h" //настраивается в GyverHacks.h - MEDIAN_FILTER_SIZE -GMedian medianFilter; -#endif - -#ifdef dallas_enable -#include -#include -OneWire *oneWire; -DallasTemperature sensors; -#endif - -#ifdef dht_enable -#include -DHTesp dht; -#endif - -#include - -#ifdef bmp_enable -#include -Adafruit_BMP280 bmp; // use I2C interface -Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor(); -Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor(); -#endif - -#ifdef bme_enable -#include -Adafruit_BME280 bme; // use I2C interface -Adafruit_Sensor *bme_temp = bme.getTemperatureSensor(); -Adafruit_Sensor *bme_pressure = bme.getPressureSensor(); -Adafruit_Sensor *bme_humidity = bme.getHumiditySensor(); -#endif - -//#include -//SoftwareSerial mySerial(14, 12); - -//===============FIRMWARE VARS======================== -boolean just_load = true; -const char *hostName = "IoT Manager"; -//JSON -String configSetup = "{}"; -String configJson = "{}"; -String optionJson = "{}"; -//MQTT -String chipID = ""; -String prex; -String all_widgets = ""; -String scenario; -String order_loop; -//SENSORS -String analog_value_names_list; -int enter_to_analog_counter; - -String level_value_name; - -String dhtT_value_name; -String dhtH_value_name; - -String bmp280T_value_name; -String bmp280P_value_name; - -String bme280T_value_name; -String bme280P_value_name; -String bme280H_value_name; -String bme280A_value_name; - -int sensors_reading_map[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -//============================0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14 - -//LOGGING -String logging_value_names_list; -int enter_to_logging_counter; -//NTP and TIME -String current_time; -//SCENARIO -int scenario_line_status[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; -//ERRORS -int wifi_lost_error = 0; -int mqtt_lost_error = 0; -String last_version; -//ASYNC ACTIONS -boolean upgrade_url = false; -boolean upgrade = false; -boolean mqtt_connection = false; -boolean udp_data_parse = false; -boolean mqtt_send_settings_to_udp = false; -boolean i2c_scanning = false; -//UDP -boolean udp_busy = false; -unsigned int udp_port = 4210; -#ifdef ESP8266 -IPAddress udp_multicastIP(255, 255, 255, 255); -#endif -#ifdef ESP32 -IPAddress udp_multicastIP(239, 255, 255, 255); -#endif -String received_ip; -String received_udp_line; -int udp_period; -//i2c -String i2c_list; diff --git a/include/Global.h b/include/Global.h index e4b84378..4f224d5a 100644 --- a/include/Global.h +++ b/include/Global.h @@ -1,9 +1,191 @@ #pragma once #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "Consts.h" +/* +* ESP8266 +*/ +#ifdef ESP8266 +#include +#include +#include +#include +ESP8266HTTPUpdateServer httpUpdater; +#include +WiFiUDP Udp; +#include +#ifdef MDNS_enable +#include +#endif +#endif + +/* +* ESP32 +*/ +#ifdef ESP32 +#include +#include +#include +#include +#include +#include +#include +extern AsyncUDP udp; +#include +#ifdef MDNS_enable +#include +#endif +#endif + +extern Servo myServo1; +extern Servo myServo2; + +#ifdef OTA_enable +#include +#endif + +extern AsyncWebServer server; + +// Global vars +extern boolean just_load; +extern const char *hostName; + +extern String configSetup; +extern String configJson; +extern String optionJson; + +extern String chipID; +extern String prex; +extern String all_widgets; +extern String scenario; +extern String order_loop; + +extern String analog_value_names_list; +extern int enter_to_analog_counter; + +extern String level_value_name; + +extern String dhtT_value_name; +extern String dhtH_value_name; + +extern String bmp280T_value_name; +extern String bmp280P_value_name; + +extern String bme280T_value_name; +extern String bme280P_value_name; +extern String bme280H_value_name; +extern String bme280A_value_name; + +extern String logging_value_names_list; +extern int enter_to_logging_counter; + +extern String current_time; + +extern int scenario_line_status[40]; + +extern int wifi_lost_error; +extern int mqtt_lost_error; + +extern String last_version; + +extern boolean upgrade_url; +extern boolean upgrade; +extern boolean mqtt_connection; +extern boolean udp_data_parse; +extern boolean mqtt_send_settings_to_udp; +extern boolean i2c_scanning; + +#ifdef WS_enable +extern AsyncWebSocket ws; +#endif + +extern AsyncEventSource events; + +extern int sensors_reading_map[15]; + +enum { ROUTER_SEARCHING, + WIFI_MQTT_CONNECTION_CHECK, + SENSORS, + STEPPER1, + STEPPER2, + LOG1, + LOG2, + LOG3, + LOG4, + LOG5, + TIMER_COUNTDOWN, + TIME, + TIME_SYNC, + STATISTICS, + UDP, + UDP_DB, + TEST }; + +extern TickerScheduler ts; + +extern WiFiClient espClient; +extern PubSubClient client_mqtt; +extern StringCommand sCmd; + +#define NUM_BUTTONS 6 +extern boolean but[NUM_BUTTONS]; +extern Bounce *buttons; + +extern boolean udp_busy; +extern unsigned int udp_port; +extern IPAddress udp_multicastIP; +extern String received_ip; +extern String received_udp_line; +extern int udp_period; + +#ifdef level_enable +#include "GyverFilters.h" //настраивается в GyverHacks.h - MEDIAN_FILTER_SIZE +GMedian medianFilter; +#endif + +#ifdef dallas_enable +#include +#include +OneWire *oneWire; +DallasTemperature sensors; +#endif + +#ifdef dht_enable +#include +DHTesp dht; +#endif + +#include + +#ifdef bmp_enable +#include +Adafruit_BMP280 bmp; // use I2C interface +Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor(); +Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor(); +#endif + +#ifdef bme_enable +#include +Adafruit_BME280 bme; // use I2C interface +Adafruit_Sensor *bme_temp = bme.getTemperatureSensor(); +Adafruit_Sensor *bme_pressure = bme.getPressureSensor(); +Adafruit_Sensor *bme_humidity = bme.getHumiditySensor(); +#endif + +//#include +//SoftwareSerial mySerial(14, 12); + // Cmd extern void CMD_init(); extern void button(); @@ -61,12 +243,12 @@ extern void choose_log_date_and_send(); // Main void getMemoryLoad(String text); -extern String jsonReadStr(String& json, String name); -extern int jsonReadInt(String& json, String name); -extern String jsonWriteInt(String& json, String name, int volume); -extern String jsonWriteStr(String& json, String name, String volume); +extern String jsonReadStr(String &json, String name); +extern int jsonReadInt(String &json, String name); +extern String jsonWriteInt(String &json, String name, int volume); +extern String jsonWriteStr(String &json, String name, String volume); extern void saveConfig(); -extern String jsonWriteFloat(String& json, String name, float volume); +extern String jsonWriteFloat(String &json, String name, float volume); extern String getURL(String urls); @@ -85,11 +267,10 @@ extern String selectFromMarkerToMarker(String str, String found, int number); extern void servo_(); extern boolean isDigitStr(String str); -extern String jsonWriteStr(String& json, String name, String volume); +extern String jsonWriteStr(String &json, String name, String volume); extern void led_blink(String satus); extern int count(String str, String found); - // Mqtt extern void MQTT_init(); extern boolean MQTT_Connecting(); diff --git a/include/push_pushingbox.h b/include/push_pushingbox.h index 1d03b9ca..a96626ef 100644 --- a/include/push_pushingbox.h +++ b/include/push_pushingbox.h @@ -2,7 +2,7 @@ #include "Global.h" -inline void Push_init() { +void Push_init() { server.on("/pushingboxDate", HTTP_GET, [](AsyncWebServerRequest* request) { if (request->hasArg("pushingbox_id")) { jsonWriteStr(configSetup, "pushingbox_id", request->getParam("pushingbox_id")->value()); diff --git a/src/Global.cpp b/src/Global.cpp new file mode 100644 index 00000000..9a24eeda --- /dev/null +++ b/src/Global.cpp @@ -0,0 +1,100 @@ +#include "Global.h" + +TickerScheduler ts(TEST + 1); + +WiFiClient espClient; +PubSubClient client_mqtt(espClient); +StringCommand sCmd; + +// Web +AsyncWebServer server(80); + +#ifdef WS_enable +AsyncWebSocket ws("/ws"); +#endif + +AsyncEventSource events("/events"); + +// Global vars +boolean just_load = true; +const char *hostName = "IoT Manager"; + +// Json +String configSetup = "{}"; +String configJson = "{}"; +String optionJson = "{}"; + +// Mqtt +String chipID = ""; +String prex; +String all_widgets = ""; +String scenario; +String order_loop; + +// Sensors +String analog_value_names_list; +int enter_to_analog_counter; + +String level_value_name; + +String dhtT_value_name; +String dhtH_value_name; + +String bmp280T_value_name; +String bmp280P_value_name; + +String bme280T_value_name; +String bme280P_value_name; +String bme280H_value_name; +String bme280A_value_name; + +int sensors_reading_map[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +// Logging +String logging_value_names_list; +int enter_to_logging_counter; + +// Ntp and time +String current_time; + +// Scenario +int scenario_line_status[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + +// Errors +int wifi_lost_error = 0; +int mqtt_lost_error = 0; + +String last_version; + +// Async actions +boolean upgrade_url = false; +boolean upgrade = false; +boolean mqtt_connection = false; +boolean udp_data_parse = false; +boolean mqtt_send_settings_to_udp = false; +boolean i2c_scanning = false; + +// Servo +Servo myServo1; +Servo myServo2; + +//Buttons +boolean but[NUM_BUTTONS]; +Bounce *buttons = new Bounce[NUM_BUTTONS]; + +// Udp +boolean udp_busy = false; +unsigned int udp_port = 4210; +#ifdef ESP8266 +IPAddress udp_multicastIP(255, 255, 255, 255); +#endif +#ifdef ESP32 +IPAddress udp_multicastIP(239, 255, 255, 255); +AsyncUDP udp; +#endif +String received_ip; +String received_udp_line; +int udp_period; + +// i2c +String i2c_list; diff --git a/src/Init.cpp b/src/Init.cpp index 9a81f8a8..2cac31c4 100644 --- a/src/Init.cpp +++ b/src/Init.cpp @@ -66,7 +66,7 @@ void Device_init() { int array_sz = sizeof(sensors_reading_map) / sizeof(sensors_reading_map[0]); - for (int i = 0; i < array_sz; i++) { + for (int i = 0; i < array_sz; i++) { sensors_reading_map[i] = 0; } @@ -219,20 +219,16 @@ void statistics() { urls += "iot-manager_esp32"; #endif urls += "&"; - //----------------------------------------------------------------- #ifdef ESP8266 urls += ESP.getResetReason(); - //Serial.println(ESP.getResetReason()); #endif #ifdef ESP32 urls += "Power on"; #endif urls += "&"; - //----------------------------------------------------------------- - urls += "ver: " + firmware_version; - //----------------------------------------------------------------- + urls += "ver: "; + urls += String(firmware_version); String stat = getURL(urls); - //Serial.println(stat); } } From 5494f612676871402a32f1750b30ff556967dbcf Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Fri, 19 Jun 2020 02:31:56 +0200 Subject: [PATCH 03/17] full size test --- include/Consts.h | 12 +- include/Global.h | 95 +++-- .../examples/GFilterRA/GFilterRA.ino | 16 + .../GLinear_arrays/GLinear_arrays.ino | 32 ++ .../examples/GLinear_arrays/excel.jpg | Bin 0 -> 48954 bytes .../GLinear_running/GLinear_running.ino | 34 ++ .../alphabeta_example/alphabeta_example.ino | 24 ++ .../filters_comparsion/filters_comparsion.ino | 30 ++ .../kalman_example/kalman_example.ino | 31 ++ .../median3_example/median3_example.ino | 21 ++ .../median_example/median_example.ino | 23 ++ lib/GyverFilters/keywords.txt | 28 ++ lib/GyverFilters/library.properties | 9 + lib/GyverFilters/src/GyverFilters.h | 26 ++ lib/GyverFilters/src/filters/alfaBeta.h | 37 ++ lib/GyverFilters/src/filters/kalman.h | 38 ++ lib/GyverFilters/src/filters/linear.h | 30 ++ lib/GyverFilters/src/filters/median.h | 35 ++ lib/GyverFilters/src/filters/median3.h | 30 ++ .../src/filters/runningAverage.cpp | 43 +++ lib/GyverFilters/src/filters/runningAverage.h | 24 ++ platformio.ini | 6 + src/Global.cpp | 4 + src/Sensors.cpp | 328 ++++++++++++------ src/main.cpp | 2 - 25 files changed, 807 insertions(+), 151 deletions(-) create mode 100644 lib/GyverFilters/examples/GFilterRA/GFilterRA.ino create mode 100644 lib/GyverFilters/examples/GLinear_arrays/GLinear_arrays.ino create mode 100644 lib/GyverFilters/examples/GLinear_arrays/excel.jpg create mode 100644 lib/GyverFilters/examples/GLinear_running/GLinear_running.ino create mode 100644 lib/GyverFilters/examples/alphabeta_example/alphabeta_example.ino create mode 100644 lib/GyverFilters/examples/filters_comparsion/filters_comparsion.ino create mode 100644 lib/GyverFilters/examples/kalman_example/kalman_example.ino create mode 100644 lib/GyverFilters/examples/median3_example/median3_example.ino create mode 100644 lib/GyverFilters/examples/median_example/median_example.ino create mode 100644 lib/GyverFilters/keywords.txt create mode 100644 lib/GyverFilters/library.properties create mode 100644 lib/GyverFilters/src/GyverFilters.h create mode 100644 lib/GyverFilters/src/filters/alfaBeta.h create mode 100644 lib/GyverFilters/src/filters/kalman.h create mode 100644 lib/GyverFilters/src/filters/linear.h create mode 100644 lib/GyverFilters/src/filters/median.h create mode 100644 lib/GyverFilters/src/filters/median3.h create mode 100644 lib/GyverFilters/src/filters/runningAverage.cpp create mode 100644 lib/GyverFilters/src/filters/runningAverage.h diff --git a/include/Consts.h b/include/Consts.h index e7ede351..c9ef6d63 100644 --- a/include/Consts.h +++ b/include/Consts.h @@ -20,12 +20,12 @@ /* * Sensor */ -//#define level_enable -//#define analog_enable -//#define dallas_enable -//#define dht_enable -//#define bmp_enable -//#define bme_enable +#define level_enable +#define analog_enable +#define dallas_enable +#define dht_enable +#define bmp_enable +#define bme_enable /* * Logging diff --git a/include/Global.h b/include/Global.h index 4f224d5a..e992709a 100644 --- a/include/Global.h +++ b/include/Global.h @@ -114,23 +114,26 @@ extern AsyncEventSource events; extern int sensors_reading_map[15]; -enum { ROUTER_SEARCHING, - WIFI_MQTT_CONNECTION_CHECK, - SENSORS, - STEPPER1, - STEPPER2, - LOG1, - LOG2, - LOG3, - LOG4, - LOG5, - TIMER_COUNTDOWN, - TIME, - TIME_SYNC, - STATISTICS, - UDP, - UDP_DB, - TEST }; +enum +{ + ROUTER_SEARCHING, + WIFI_MQTT_CONNECTION_CHECK, + SENSORS, + STEPPER1, + STEPPER2, + LOG1, + LOG2, + LOG3, + LOG4, + LOG5, + TIMER_COUNTDOWN, + TIME, + TIME_SYNC, + STATISTICS, + UDP, + UDP_DB, + TEST +}; extern TickerScheduler ts; @@ -150,34 +153,30 @@ extern String received_udp_line; extern int udp_period; #ifdef level_enable -#include "GyverFilters.h" //настраивается в GyverHacks.h - MEDIAN_FILTER_SIZE -GMedian medianFilter; +#include "GyverFilters.h" +GMedian<10, int> medianFilter; #endif -#ifdef dallas_enable #include #include -OneWire *oneWire; -DallasTemperature sensors; -#endif +extern OneWire *oneWire; +extern DallasTemperature sensors; -#ifdef dht_enable #include DHTesp dht; -#endif #include #ifdef bmp_enable #include -Adafruit_BMP280 bmp; // use I2C interface +Adafruit_BMP280 bmp; // use I2C interface Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor(); Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor(); #endif #ifdef bme_enable #include -Adafruit_BME280 bme; // use I2C interface +Adafruit_BME280 bme; // use I2C interface Adafruit_Sensor *bme_temp = bme.getTemperatureSensor(); Adafruit_Sensor *bme_pressure = bme.getPressureSensor(); Adafruit_Sensor *bme_humidity = bme.getHumiditySensor(); @@ -256,6 +255,10 @@ extern String writeFile(String fileName, String strings); extern String readFile(String fileName, size_t len); extern String addFile(String fileName, String strings); +// Main Utils - явно +extern uint8_t hexStringToUint8(String hex); +extern uint16_t hexStringToUint16(String hex); + //STRING extern String selectToMarkerLast(String str, String found); extern String selectToMarker(String str, String found); @@ -293,8 +296,45 @@ extern void eventGen(String event_name, String number); extern String add_set(String param_name); //Sensors +// И как раз тут хорошо просто в Sensors.h это пихать - а не в один здоровенный ФАЙЛ extern void sensors_init(); +extern void level(); +extern void level_reading(); + +extern void analog(); +extern void analog_reading1(); +extern void analog_reading2(); +extern void dallas_reading(); +extern void dhtT_reading(); + +extern void dallas(); + +extern void bmp280T(); +extern void bmp280P(); +extern void bmp280T_reading(); +extern void bmp280P_reading(); + +extern void bme280T(); +extern void bme280P(); +extern void bme280H(); +extern void bme280A(); + +extern void bme280T_reading(); +extern void bme280P_reading(); +extern void bme280H_reading(); +extern void bme280A_reading(); + +extern void dhtT(); +extern void dhtH(); +extern void dhtP(); +extern void dhtC(); +extern void dhtD(); +extern void dhtH_reading(); +extern void dhtP_reading(); +extern void dhtC_reading(); +extern void dhtD_reading(); + //Timers extern void Timer_countdown_init(); extern void timerStart_(); @@ -326,7 +366,6 @@ extern void choose_widget_and_create(String widget_name, String page_name, Strin extern void createChart(String widget_name, String page_name, String page_number, String file, String topic, String maxCount); // Push - extern void Push_init(); // UDP diff --git a/lib/GyverFilters/examples/GFilterRA/GFilterRA.ino b/lib/GyverFilters/examples/GFilterRA/GFilterRA.ino new file mode 100644 index 00000000..c6db1517 --- /dev/null +++ b/lib/GyverFilters/examples/GFilterRA/GFilterRA.ino @@ -0,0 +1,16 @@ +#include "GyverFilters.h" +GFilterRA analog0; // фильтр назовём analog0 + +void setup() { + Serial.begin(9600); + + // установка коэффициента фильтрации (0.0... 1.0). Чем меньше, тем плавнее фильтр + analog0.setCoef(0.01); + + // установка шага фильтрации (мс). Чем меньше, тем резче фильтр + analog0.setStep(10); +} + +void loop() { + Serial.println(analog0.filteredTime(analogRead(0))); +} diff --git a/lib/GyverFilters/examples/GLinear_arrays/GLinear_arrays.ino b/lib/GyverFilters/examples/GLinear_arrays/GLinear_arrays.ino new file mode 100644 index 00000000..6c407ec4 --- /dev/null +++ b/lib/GyverFilters/examples/GLinear_arrays/GLinear_arrays.ino @@ -0,0 +1,32 @@ +/* + Пример линейной аппроксимации методом наименьших квадратов + Два массива: по оси Х и по оси У + Линейная аппроксимация повозоляет получить уравнение прямой, + равноудалённой от точек на плоскости ХУ. Удобно для расчёта + роста изменяющейся шумящей величины. Уравнение вида у = A*x + B + В папке с данным примером есть скриншот из excel, + иллюстрирующий работу аппроксимации с такими же исходными +*/ + +// два массива с данными (одинаковой размероности и размера) +int x_array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; +int y_array[] = {1, 5, 2, 8, 3, 9, 10, 5, 15, 12}; + +#include +GLinear test; // указываем тип данных в <> + +void setup() { + Serial.begin(9600); + + // передаём массивы и размер одного из них + test.compute((int*)x_array, (int*)y_array, sizeof(x_array)); + + // Уравнение вида у = A*x + B + Serial.println(test.getA()); // получить коэффициент А + Serial.println(test.getB()); // получить коэффициент В + Serial.println(test.getDelta()); // получить изменение (аппроксимированное) +} + +void loop() { + +} \ No newline at end of file diff --git a/lib/GyverFilters/examples/GLinear_arrays/excel.jpg b/lib/GyverFilters/examples/GLinear_arrays/excel.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9cd711176987f941c3ad8a3de488a7f519868db9 GIT binary patch literal 48954 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 literal 0 HcmV?d00001 diff --git a/lib/GyverFilters/examples/GLinear_running/GLinear_running.ino b/lib/GyverFilters/examples/GLinear_running/GLinear_running.ino new file mode 100644 index 00000000..575c50dc --- /dev/null +++ b/lib/GyverFilters/examples/GLinear_running/GLinear_running.ino @@ -0,0 +1,34 @@ +/* + Пример линейной аппроксимации методом наименьших квадратов + Два массива: по оси Х и по оси У + Наполнение массивов осуществляется динамически: сдвигом и записью в крайнюю ячейку, + то есть аппроксимация по последним ARRAY_SIZE изменениям!! +*/ +#define ARRAY_SIZE 10 // размер пространства для аппроксимации + +// два массива с данными (одинаковой размероности и размера) +int x_array[ARRAY_SIZE] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // ось x от 1 до 10, допустим СЕКУНД +int y_array[ARRAY_SIZE]; // значения по оси У будем брать с датчика + +#include +GLinear test; // указываем тип данных в <> + +void setup() { + Serial.begin(9600); +} + +void loop() { + for (byte i = 0; i < ARRAY_SIZE - 1; i++) { // счётчик от 0 до ARRAY_SIZE + y_array[i] = y_array[i + 1]; // сдвинуть массив давлений КРОМЕ ПОСЛЕДНЕЙ ЯЧЕЙКИ на шаг назад + } + // последний элемент массива теперь - новое значение (просто с аналог. датчика) + y_array[ARRAY_SIZE - 1] = analogRead(0); + + // передаём массивы и размер одного из них + test.compute((int*)x_array, (int*)y_array, sizeof(x_array)); + + // по нашим исходным данным это будет производная, т.е. "изменение единиц в секунду" + Serial.println(test.getDelta()); // получить изменение (аппроксимированное) + + delay(1000); // секундная задержка +} diff --git a/lib/GyverFilters/examples/alphabeta_example/alphabeta_example.ino b/lib/GyverFilters/examples/alphabeta_example/alphabeta_example.ino new file mode 100644 index 00000000..8f43b77a --- /dev/null +++ b/lib/GyverFilters/examples/alphabeta_example/alphabeta_example.ino @@ -0,0 +1,24 @@ +/* + Пример альфа-бета фильтра +*/ + +#include "GyverFilters.h" + +// параметры: период дискретизации (измерений), process variation, noise variation +GABfilter testFilter(0.08, 40, 1); + +void setup() { + Serial.begin(9600); +} + +void loop() { + delay(80); + int value = analogRead(0); + value += random(2) * random(-1, 2) * random(10, 70); + Serial.print("$"); + Serial.print(value); + Serial.print(" "); + value = testFilter.filtered((int)value); + Serial.print(value); + Serial.println(";"); +} diff --git a/lib/GyverFilters/examples/filters_comparsion/filters_comparsion.ino b/lib/GyverFilters/examples/filters_comparsion/filters_comparsion.ino new file mode 100644 index 00000000..b981993a --- /dev/null +++ b/lib/GyverFilters/examples/filters_comparsion/filters_comparsion.ino @@ -0,0 +1,30 @@ +/* + Сравнение калмана и бегущего среднего +*/ +#include "GyverFilters.h" + +// параметры: разброс измерения, разброс оценки, скорость изменения значений +// разброс измерения: шум измерений +// разброс оценки: подстраивается сам, можно поставить таким же как разброс измерения +// скорость изменения значений: 0.001-1, варьировать самому + +GKalman kalman(90, 90, 0.5); +GFilterRA average(0.5, 80); + +void setup() { + Serial.begin(9600); +} + +void loop() { + int value = analogRead(0); + value += random(2) * random(-1, 2) * random(50, 100); + Serial.print("$"); + Serial.print(value); + Serial.print(" "); + + Serial.print((int)kalman.filtered(value)); + Serial.print(" "); + Serial.print((int)average.filtered(value)); + Serial.println(";"); + delay(80); +} diff --git a/lib/GyverFilters/examples/kalman_example/kalman_example.ino b/lib/GyverFilters/examples/kalman_example/kalman_example.ino new file mode 100644 index 00000000..802307af --- /dev/null +++ b/lib/GyverFilters/examples/kalman_example/kalman_example.ino @@ -0,0 +1,31 @@ +/* + Пример простого одномерного фильтра +*/ + +#include "GyverFilters.h" + +// параметры: разброс измерения, разброс оценки, скорость изменения значений +// разброс измерения: шум измерений +// разброс оценки: подстраивается сам, можно поставить таким же как разброс измерения +// скорость изменения значений: 0.001-1, варьировать самому + +GKalman testFilter(40, 40, 0.5); + +// также может быть объявлен как (разброс измерения, скорость изменения значений) +// GKalman testFilter(40, 0.5); + +void setup() { + Serial.begin(9600); +} + +void loop() { + delay(80); + int value = analogRead(0); + value += random(2) * random(-1, 2) * random(10, 70); + Serial.print("$"); + Serial.print(value); + Serial.print(" "); + value = testFilter.filtered((int)value); + Serial.print(value); + Serial.println(";"); +} diff --git a/lib/GyverFilters/examples/median3_example/median3_example.ino b/lib/GyverFilters/examples/median3_example/median3_example.ino new file mode 100644 index 00000000..c99176bc --- /dev/null +++ b/lib/GyverFilters/examples/median3_example/median3_example.ino @@ -0,0 +1,21 @@ +/* + Пример использования быстрого медианного фильтра 3 порядка +*/ + +#include "GyverFilters.h" +GMedian3 testFilter; // указываем тип данных в <> + +void setup() { + Serial.begin(9600); +} + +void loop() { + int value = analogRead(0); + // добавляем шум "выбросы" + value += random(2) * random(2) * random(-1, 2) * random(50, 250); + Serial.print(value); + Serial.print(','); + value = testFilter.filtered(value); + Serial.println(value); + delay(80); +} diff --git a/lib/GyverFilters/examples/median_example/median_example.ino b/lib/GyverFilters/examples/median_example/median_example.ino new file mode 100644 index 00000000..c3fb0067 --- /dev/null +++ b/lib/GyverFilters/examples/median_example/median_example.ino @@ -0,0 +1,23 @@ +/* + Пример использования медианного фильтра. +*/ + +#include "GyverFilters.h" + +// указываем размер окна и тип данных в <> +GMedian<10, int> testFilter; + +void setup() { + Serial.begin(9600); +} + +void loop() { + delay(80); + int value = analogRead(0); + // добавляем шум "выбросы" + value += random(2) * random(2) * random(-1, 2) * random(50, 250); + Serial.print(value); + Serial.print(','); + value = testFilter.filtered(value); + Serial.println(value); +} \ No newline at end of file diff --git a/lib/GyverFilters/keywords.txt b/lib/GyverFilters/keywords.txt new file mode 100644 index 00000000..57f38dbc --- /dev/null +++ b/lib/GyverFilters/keywords.txt @@ -0,0 +1,28 @@ +####################################### +# Syntax Coloring Map For GyverFilters +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +GyverFilters KEYWORD1 +GFilterRA KEYWORD1 +GMedian3 KEYWORD1 +GMedian KEYWORD1 +GABfilter KEYWORD1 +GKalman KEYWORD1 +GLinear KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +setCoef KEYWORD2 +setStep KEYWORD2 +filteredTime KEYWORD2 +filtered KEYWORD2 +setParameters KEYWORD2 +getA KEYWORD2 +getB KEYWORD2 +getDelta KEYWORD2 \ No newline at end of file diff --git a/lib/GyverFilters/library.properties b/lib/GyverFilters/library.properties new file mode 100644 index 00000000..7c211d3d --- /dev/null +++ b/lib/GyverFilters/library.properties @@ -0,0 +1,9 @@ +name=GyverFilters +version=2.0 +author=AlexGyver +maintainer=AlexGyver +sentence=Library with few filters for data. +paragraph=Includes median, running average, AB, simplified Kalman and linear approximation filtering algorithms. +category=Data Processing +url=https://github.com/AlexGyver/GyverLibs +architectures=* \ No newline at end of file diff --git a/lib/GyverFilters/src/GyverFilters.h b/lib/GyverFilters/src/GyverFilters.h new file mode 100644 index 00000000..e03e4bf5 --- /dev/null +++ b/lib/GyverFilters/src/GyverFilters.h @@ -0,0 +1,26 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +/* + GyverFilters - библиотека с некоторыми удобными фильтрами: + - GFilterRA - компактная альтернатива фильтра экспоненциальное бегущее среднее (Running Average) + - GMedian3 - быстрый медианный фильтр 3-го порядка (отсекает выбросы) + - GMedian - медианный фильтр N-го порядка. Порядок настраивается в GyverFilters.h - MEDIAN_FILTER_SIZE + - GABfilter - альфа-бета фильтр (разновидность Калмана для одномерного случая) + - GKalman - упрощённый Калман для одномерного случая (на мой взгляд лучший из фильтров) + - GLinear - линейная аппроксимация методом наименьших квадратов для двух массивов + + Версии + - 1.6 от 12.11.2019 + - 1.7: исправлен GLinear + - 1.8: небольшие улучшения + - 2.0: + - Улучшен и исправлен median и median3 + - Улучшен linear + - Смотрите примеры! Использование этих фильтров чуть изменилось +*/ \ No newline at end of file diff --git a/lib/GyverFilters/src/filters/alfaBeta.h b/lib/GyverFilters/src/filters/alfaBeta.h new file mode 100644 index 00000000..51b09726 --- /dev/null +++ b/lib/GyverFilters/src/filters/alfaBeta.h @@ -0,0 +1,37 @@ +#pragma once +#include + +// альфа-бета фильтр +class GABfilter { +public: + // период дискретизации (измерений), process variation, noise variation + GABfilter(float delta, float sigma_process, float sigma_noise) {setParameters(delta, sigma_process, sigma_noise);} + + // период дискретизации (измерений), process variation, noise variation + void setParameters(float delta, float sigma_process, float sigma_noise) { + dt = delta; + float lambda = (float)sigma_process * dt * dt / sigma_noise; + float r = (4 + lambda - (float)sqrt(8 * lambda + lambda * lambda)) / 4; + a = (float)1 - r * r; + b = (float)2 * (2 - a) - 4 * (float)sqrt(1 - a); + } + + // возвращает фильтрованное значение + float filtered(float value) { + xm = value; + xk = xk_1 + ((float) vk_1 * dt ); + vk = vk_1; + rk = xm - xk; + xk += (float)a * rk; + vk += (float)( b * rk ) / dt; + xk_1 = xk; + vk_1 = vk; + return xk_1; + } + +private: + float dt; + float xk_1, vk_1, a, b; + float xk, vk, rk; + float xm; +}; \ No newline at end of file diff --git a/lib/GyverFilters/src/filters/kalman.h b/lib/GyverFilters/src/filters/kalman.h new file mode 100644 index 00000000..10458090 --- /dev/null +++ b/lib/GyverFilters/src/filters/kalman.h @@ -0,0 +1,38 @@ +#pragma once +#include + +// упрощённый Калман для одномерного случая +class GKalman { +public: + // разброс измерения, разброс оценки, скорость изменения значений + GKalman(float mea_e, float est_e, float q) { setParameters(mea_e, est_e, q); } + + // разброс измерения, скорость изменения значений (разброс измерения принимается равным разбросу оценки) + GKalman(float mea_e, float q) {GKalman::setParameters(mea_e, mea_e, q);} + + // разброс измерения, разброс оценки, скорость изменения значений + void setParameters(float mea_e, float est_e, float q) { + _err_measure = mea_e; + _err_estimate = est_e; + _q = q; + } + + // разброс измерения, скорость изменения значений (разброс измерения принимается равным разбросу оценки) + void setParameters(float mea_e, float q) {setParameters(mea_e, mea_e, q);} + + // возвращает фильтрованное значение + float filtered(float value) { + float _kalman_gain, _current_estimate; + _kalman_gain = _err_estimate / (_err_estimate + _err_measure); + _current_estimate = _last_estimate + _kalman_gain * (value - _last_estimate); + _err_estimate = (1.0 - _kalman_gain)*_err_estimate + fabs(_last_estimate-_current_estimate)*_q; + _last_estimate=_current_estimate; + return _current_estimate; + } + +private: + float _err_measure = 0.0; + float _err_estimate = 0.0; + float _q = 0.0; + float _last_estimate = 0.0; +}; \ No newline at end of file diff --git a/lib/GyverFilters/src/filters/linear.h b/lib/GyverFilters/src/filters/linear.h new file mode 100644 index 00000000..65a134f3 --- /dev/null +++ b/lib/GyverFilters/src/filters/linear.h @@ -0,0 +1,30 @@ +#pragma once +#include + +// линейная аппроксимация методом наименьших квадратов +template < typename TYPE > +class GLinear { +public: + GLinear(){}; + void compute(TYPE *x_array, TYPE *y_array, int arrSize) { // аппроксимировать + int32_t sumX = 0, sumY = 0, sumX2 = 0, sumXY = 0; + arrSize /= sizeof(int); + for (int i = 0; i < arrSize; i++) { // для всех элементов массива + sumX += x_array[i]; + sumY += (long)y_array[i]; + sumX2 += x_array[i] * x_array[i]; + sumXY += (long)y_array[i] * x_array[i]; + } + a = (long)arrSize * sumXY; // расчёт коэффициента наклона приямой + a = a - (long)sumX * sumY; + a = (float)a / (arrSize * sumX2 - sumX * sumX); + b = (float)(sumY - (float)a * sumX) / arrSize; + delta = a * arrSize; // расчёт изменения + } + float getA() {return a;} // получить коэффициент А + float getB() {return b;} // получить коэффициент В + float getDelta() {return delta;} // получить аппроксимированное изменение + +private: + float a, b, delta; +}; \ No newline at end of file diff --git a/lib/GyverFilters/src/filters/median.h b/lib/GyverFilters/src/filters/median.h new file mode 100644 index 00000000..f7580806 --- /dev/null +++ b/lib/GyverFilters/src/filters/median.h @@ -0,0 +1,35 @@ +#pragma once + +// медианный фильтр N-го порядка +template < int SIZE, typename TYPE > +class GMedian { +public: + TYPE filtered(TYPE newVal) { + buffer[_count] = newVal; + if ((_count < _numRead - 1) && (buffer[_count] > buffer[_count + 1])) { + for (int i = _count; i < _numRead - 1; i++) { + if (buffer[i] > buffer[i + 1]) { + float buff = buffer[i]; + buffer[i] = buffer[i + 1]; + buffer[i + 1] = buff; + } + } + } else { + if ((_count > 0) and (buffer[_count - 1] > buffer[_count])) { + for (int i = _count; i > 0; i--) { + if (buffer[i] < buffer[i - 1]) { + float buff = buffer[i]; + buffer[i] = buffer[i - 1]; + buffer[i - 1] = buff; + } + } + } + } + if (++_count >= _numRead) _count = 0; + return buffer[(int)_numRead / 2]; + } +private: + TYPE buffer[SIZE]; + byte _count = 0; + byte _numRead = SIZE; +}; \ No newline at end of file diff --git a/lib/GyverFilters/src/filters/median3.h b/lib/GyverFilters/src/filters/median3.h new file mode 100644 index 00000000..8b99cc1e --- /dev/null +++ b/lib/GyverFilters/src/filters/median3.h @@ -0,0 +1,30 @@ +#pragma once + +// быстрый медианный фильтр 3-го порядка +template < typename TYPE > +class GMedian3 { +public: + TYPE filtered(TYPE value) { // возвращает фильтрованное значение + buffer[_counter] = value; + if (++_counter > 2) _counter = 0; + + TYPE middle; + + if ((buffer[0] <= buffer[1]) && (buffer[0] <= buffer[2])) { + middle = (buffer[1] <= buffer[2]) ? buffer[1] : buffer[2]; + } + else { + if ((buffer[1] <= buffer[0]) && (buffer[1] <= buffer[2])) { + middle = (buffer[0] <= buffer[2]) ? buffer[0] : buffer[2]; + } + else { + middle = (buffer[0] <= buffer[1]) ? buffer[0] : buffer[1]; + } + } + return middle; + } + +private: + TYPE buffer[3]; + uint8_t _counter = 0; +}; \ No newline at end of file diff --git a/lib/GyverFilters/src/filters/runningAverage.cpp b/lib/GyverFilters/src/filters/runningAverage.cpp new file mode 100644 index 00000000..9a1b2b03 --- /dev/null +++ b/lib/GyverFilters/src/filters/runningAverage.cpp @@ -0,0 +1,43 @@ +#include + +GFilterRA::GFilterRA() {} + +GFilterRA::GFilterRA(float coef, uint16_t interval) { + _coef = coef; + _filterInterval = interval; +} + +GFilterRA::GFilterRA(float coef) { + _coef = coef; +} + +void GFilterRA::setCoef(float coef) { + _coef = coef; +} +void GFilterRA::setStep(uint16_t interval) { + _filterInterval = interval; +} + +float GFilterRA::filteredTime(int16_t value) { + if (millis() - _filterTimer >= _filterInterval) { + _filterTimer = millis(); + return GFilterRA::filtered(value); + } +} + +float GFilterRA::filteredTime(float value) { + if (millis() - _filterTimer >= _filterInterval) { + _filterTimer = millis(); + return GFilterRA::filtered(value); + } +} + +float GFilterRA::filtered(int16_t value) { + _lastValue += (float)(value - _lastValue) * _coef; + return _lastValue; +} + +float GFilterRA::filtered(float value) { + _lastValue += (float)(value - _lastValue) * _coef; + return _lastValue; +} \ No newline at end of file diff --git a/lib/GyverFilters/src/filters/runningAverage.h b/lib/GyverFilters/src/filters/runningAverage.h new file mode 100644 index 00000000..7910a0fe --- /dev/null +++ b/lib/GyverFilters/src/filters/runningAverage.h @@ -0,0 +1,24 @@ +#pragma once +#include + +// экспоненциальное бегущее среднее +class GFilterRA +{ +public: + GFilterRA(); // инициализация фильтра + GFilterRA(float coef); // расширенная инициализация фильтра (коэффициент) + GFilterRA(float coef, uint16_t interval); // расширенная инициализация фильтра (коэффициент, шаг фильтрации) + void setCoef(float coef); // настройка коэффициента фильтрации (0.00 - 1.00). Чем меньше, тем плавнее + void setStep(uint16_t interval); // установка шага фильтрации (мс). Чем меньше, тем резче фильтр + + float filteredTime(int16_t value); // возвращает фильтрованное значение с опорой на встроенный таймер + float filtered(int16_t value); // возвращает фильтрованное значение + + float filteredTime(float value); // возвращает фильтрованное значение с опорой на встроенный таймер + float filtered(float value); // возвращает фильтрованное значение + +private: + float _coef = 0.0, _lastValue = 0.0; + uint32_t _filterTimer = 0; + uint16_t _filterInterval = 0; +}; \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 84ab6931..16f15936 100644 --- a/platformio.ini +++ b/platformio.ini @@ -18,6 +18,12 @@ lib_deps= Bounce2 PubSubClient ESP8266-StringCommand + DallasTemperature + DHT sensor library for ESPx + Adafruit BMP280 Library + Adafruit BME280 Library + +#board_build.partitions = partitions_custom.csv [env:esp32dev] platform = espressif32 diff --git a/src/Global.cpp b/src/Global.cpp index 9a24eeda..4df4e3e7 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -98,3 +98,7 @@ int udp_period; // i2c String i2c_list; + +extern OneWire *oneWire; +extern DallasTemperature sensors; + diff --git a/src/Sensors.cpp b/src/Sensors.cpp index 890dc2a2..a5a228bb 100644 --- a/src/Sensors.cpp +++ b/src/Sensors.cpp @@ -1,45 +1,66 @@ #include "Global.h" -void sensors_init() { +String perception(byte value); +void bmp280T_reading(); +String get_comfort_status(ComfortState cf); + +void sensors_init() +{ ts.add( - SENSORS, 1000, [&](void*) { + SENSORS, 1000, [&](void *) { static int counter; counter++; #ifdef level_enable - if (sensors_reading_map[0] == 1) level_reading(); + if (sensors_reading_map[0] == 1) + level_reading(); #endif - if (counter > 10) { + if (counter > 10) + { counter = 0; #ifdef analog_enable - if (sensors_reading_map[1] == 1) analog_reading1(); - if (sensors_reading_map[2] == 1) analog_reading2(); + if (sensors_reading_map[1] == 1) + analog_reading1(); + if (sensors_reading_map[2] == 1) + analog_reading2(); #endif #ifdef dallas_enable - if (sensors_reading_map[3] == 1) dallas_reading(); + if (sensors_reading_map[3] == 1) + dallas_reading(); #endif #ifdef dht_enable - if (sensors_reading_map[4] == 1) dhtT_reading(); - if (sensors_reading_map[5] == 1) dhtH_reading(); - if (sensors_reading_map[6] == 1) dhtP_reading(); - if (sensors_reading_map[7] == 1) dhtC_reading(); - if (sensors_reading_map[8] == 1) dhtD_reading(); + if (sensors_reading_map[4] == 1) + dhtT_reading(); + if (sensors_reading_map[5] == 1) + dhtH_reading(); + if (sensors_reading_map[6] == 1) + dhtP_reading(); + if (sensors_reading_map[7] == 1) + dhtC_reading(); + if (sensors_reading_map[8] == 1) + dhtD_reading(); #endif #ifdef bmp_enable - if (sensors_reading_map[9] == 1) bmp280T_rading(); - if (sensors_reading_map[10] == 1) bmp280P_reading(); + if (sensors_reading_map[9] == 1) + bmp280T_reading(); + if (sensors_reading_map[10] == 1) + bmp280P_reading(); #endif #ifdef bme_enable - if (sensors_reading_map[11] == 1) bme280T_reading(); - if (sensors_reading_map[12] == 1) bme280P_reading(); - if (sensors_reading_map[13] == 1) bme280H_reading(); - if (sensors_reading_map[14] == 1) bme280A_reading(); + if (sensors_reading_map[11] == 1) + bme280T_reading(); + if (sensors_reading_map[12] == 1) + bme280P_reading(); + if (sensors_reading_map[13] == 1) + bme280H_reading(); + if (sensors_reading_map[14] == 1) + bme280A_reading(); #endif } }, @@ -50,7 +71,8 @@ void sensors_init() { //=========================================Модуль измерения уровня в баке================================================================== #ifdef level_enable //level L 14 12 Вода#в#баке,#% Датчики fill-gauge 125 20 1 -void level() { +void level() +{ String value_name = sCmd.next(); String trig = sCmd.next(); String echo = sCmd.next(); @@ -71,7 +93,8 @@ void level() { sensors_reading_map[0] = 1; } -void level_reading() { +void level_reading() +{ long duration_; int distance_cm; int level; @@ -83,11 +106,12 @@ void level_reading() { digitalWrite(trig, HIGH); delayMicroseconds(10); digitalWrite(trig, LOW); - duration_ = pulseIn(echo, HIGH, 30000); // 3000 µs = 50cm // 30000 µs = 5 m + duration_ = pulseIn(echo, HIGH, 30000); // 3000 µs = 50cm // 30000 µs = 5 m distance_cm = duration_ / 29 / 2; - distance_cm = medianFilter.filtered(distance_cm); //отсечение промахов медианным фильтром + distance_cm = medianFilter.filtered(distance_cm); //отсечение промахов медианным фильтром counter++; - if (counter > tank_level_times_to_send) { + if (counter > tank_level_times_to_send) + { counter = 0; level = map(distance_cm, jsonReadInt(optionJson, "e_lev"), @@ -103,7 +127,8 @@ void level_reading() { //=========================================Модуль аналогового сенсора====================================================================== #ifdef analog_enable //analog adc 0 Аналоговый#вход,#% Датчики any-data 1 1023 1 100 1 -void analog() { +void analog() +{ String value_name = sCmd.next(); String pin = sCmd.next(); String widget_name = sCmd.next(); @@ -121,15 +146,18 @@ void analog() { jsonWriteStr(optionJson, value_name + "_st_out", analog_start_out); jsonWriteStr(optionJson, value_name + "_end_out", analog_end_out); choose_widget_and_create(widget_name, page_name, page_number, type, value_name); - if (enter_to_analog_counter == 1) { + if (enter_to_analog_counter == 1) + { sensors_reading_map[1] = 1; } - if (enter_to_analog_counter == 2) { + if (enter_to_analog_counter == 2) + { sensors_reading_map[2] = 1; } } -void analog_reading1() { +void analog_reading1() +{ String value_name = selectFromMarkerToMarker(analog_value_names_list, ",", 0); #ifdef ESP32 int analog_in = analogRead(34); @@ -148,7 +176,8 @@ void analog_reading1() { Serial.println("[i] sensor '" + value_name + "' data: " + String(analog)); } -void analog_reading2() { +void analog_reading2() +{ String value_name = selectFromMarkerToMarker(analog_value_names_list, ",", 1); #ifdef ESP32 int analog_in = analogRead(35); @@ -170,7 +199,8 @@ void analog_reading2() { //========================================================================================================================================= //=========================================Модуль температурного сенсора ds18b20=========================================================== #ifdef dallas_enable -void dallas() { +void dallas() +{ String value_name = sCmd.next(); String pin = sCmd.next(); String address = sCmd.next(); @@ -186,7 +216,8 @@ void dallas() { sensors_reading_map[3] = 1; } -void dallas_reading() { +void dallas_reading() +{ float temp = 0; sensors.requestTemperatures(); temp = sensors.getTempCByIndex(0); @@ -200,7 +231,8 @@ void dallas_reading() { //=========================================Модуль сенсоров DHT============================================================================= #ifdef dht_enable //dhtT t 2 dht11 Температура#DHT,#t°C Датчики any-data 1 -void dhtT() { +void dhtT() +{ String value_name = sCmd.next(); String pin = sCmd.next(); String sensor_type = sCmd.next(); @@ -209,26 +241,33 @@ void dhtT() { String type = sCmd.next(); String page_number = sCmd.next(); dhtT_value_name = value_name; - if (sensor_type == "dht11") { + if (sensor_type == "dht11") + { dht.setup(pin.toInt(), DHTesp::DHT11); } - if (sensor_type == "dht22") { + if (sensor_type == "dht22") + { dht.setup(pin.toInt(), DHTesp::DHT22); } choose_widget_and_create(widget_name, page_name, page_number, type, value_name); sensors_reading_map[4] = 1; } -void dhtT_reading() { +void dhtT_reading() +{ float value = 0; static int counter; - if (dht.getStatus() != 0 && counter < 5) { + if (dht.getStatus() != 0 && counter < 5) + { sendSTATUS(dhtT_value_name, String(dht.getStatusString())); counter++; - } else { + } + else + { counter = 0; value = dht.getTemperature(); - if (String(value) != "nan") { + if (String(value) != "nan") + { eventGen(dhtT_value_name, ""); jsonWriteStr(configJson, dhtT_value_name, String(value)); sendSTATUS(dhtT_value_name, String(value)); @@ -238,7 +277,8 @@ void dhtT_reading() { } //dhtH h 2 dht11 Влажность#DHT,#t°C Датчики any-data 1 -void dhtH() { +void dhtH() +{ String value_name = sCmd.next(); String pin = sCmd.next(); String sensor_type = sCmd.next(); @@ -247,26 +287,33 @@ void dhtH() { String type = sCmd.next(); String page_number = sCmd.next(); dhtH_value_name = value_name; - if (sensor_type == "dht11") { + if (sensor_type == "dht11") + { dht.setup(pin.toInt(), DHTesp::DHT11); } - if (sensor_type == "dht22") { + if (sensor_type == "dht22") + { dht.setup(pin.toInt(), DHTesp::DHT22); } choose_widget_and_create(widget_name, page_name, page_number, type, value_name); sensors_reading_map[5] = 1; } -void dhtH_reading() { +void dhtH_reading() +{ float value = 0; static int counter; - if (dht.getStatus() != 0 && counter < 5) { + if (dht.getStatus() != 0 && counter < 5) + { sendSTATUS(dhtH_value_name, String(dht.getStatusString())); counter++; - } else { + } + else + { counter = 0; value = dht.getHumidity(); - if (String(value) != "nan") { + if (String(value) != "nan") + { eventGen(dhtH_value_name, ""); jsonWriteStr(configJson, dhtH_value_name, String(value)); sendSTATUS(dhtH_value_name, String(value)); @@ -276,7 +323,8 @@ void dhtH_reading() { } //dhtPerception Восприятие: Датчики 4 -void dhtP() { +void dhtP() +{ String widget_name = sCmd.next(); String page_name = sCmd.next(); String page_number = sCmd.next(); @@ -284,35 +332,65 @@ void dhtP() { sensors_reading_map[6] = 1; } -void dhtP_reading() { +void dhtP_reading() +{ byte value; - if (dht.getStatus() != 0) { + if (dht.getStatus() != 0) + { sendSTATUS("dhtPerception", String(dht.getStatusString())); - } else { + } + else + { value = dht.computePerception(jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); String final_line = perception(value); jsonWriteStr(configJson, "dhtPerception", final_line); eventGen("dhtPerception", ""); sendSTATUS("dhtPerception", final_line); - if (client_mqtt.connected()) { + if (client_mqtt.connected()) + { Serial.println("[i] sensor 'dhtPerception' data: " + final_line); } } } -String perception(byte value) { - if (value == 0) return "Сухой воздух"; - if (value == 1) return "Комфортно"; - if (value == 2) return "Уютно"; - if (value == 3) return "Хорошо"; - if (value == 4) return "Неудобно"; - if (value == 5) return "Довольно неудобно"; - if (value == 6) return "Очень неудобно"; - if (value == 7) return "Сильно неудобно, полный звиздец"; +String perception(byte value) +{ + String res; + switch (value) + { + case 0: + res = F("Сухой воздух"); + break; + case 1: + res = F("Комфортно"); + break; + case 2: + res = F("Уютно"); + break; + case 3: + res = F("Хорошо"); + break; + case 4: + res = F("Неудобно"); + break; + case 5: + res = F("Довольно неудобно"); + break; + case 6: + res = F("Очень неудобно"); + break; + case 7: + res = F("Сильно неудобно, полный звиздец"); + default: + res = F("Unknown"); + break; + } + return res; } //dhtComfort Степень#комфорта: Датчики 3 -void dhtC() { +void dhtC() +{ String widget_name = sCmd.next(); String page_name = sCmd.next(); String page_number = sCmd.next(); @@ -320,12 +398,15 @@ void dhtC() { sensors_reading_map[7] = 1; } -void dhtC_reading() { - float value; +void dhtC_reading() +{ ComfortState cf; - if (dht.getStatus() != 0) { + if (dht.getStatus() != 0) + { sendSTATUS("dhtComfort", String(dht.getStatusString())); - } else { + } + else + { value = dht.getComfortRatio(cf, jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); String final_line = get_comfort_status(cf); jsonWriteStr(configJson, "dhtComfort", final_line); @@ -335,45 +416,48 @@ void dhtC_reading() { } } -String get_comfort_status(ComfortState cf) { +String get_comfort_status(ComfortState cf) +{ String comfortStatus; - switch (cf) { - case Comfort_OK: - comfortStatus = "Отлично"; - break; - case Comfort_TooHot: - comfortStatus = "Очень жарко"; - break; - case Comfort_TooCold: - comfortStatus = "Очень холодно"; - break; - case Comfort_TooDry: - comfortStatus = "Очень сухо"; - break; - case Comfort_TooHumid: - comfortStatus = "Очень влажно"; - break; - case Comfort_HotAndHumid: - comfortStatus = "Жарко и влажно"; - break; - case Comfort_HotAndDry: - comfortStatus = "Жарко и сухо"; - break; - case Comfort_ColdAndHumid: - comfortStatus = "Холодно и влажно"; - break; - case Comfort_ColdAndDry: - comfortStatus = "Холодно и сухо"; - break; - default: - comfortStatus = "Неизвестно"; - break; + switch (cf) + { + case Comfort_OK: + comfortStatus = "Отлично"; + break; + case Comfort_TooHot: + comfortStatus = "Очень жарко"; + break; + case Comfort_TooCold: + comfortStatus = "Очень холодно"; + break; + case Comfort_TooDry: + comfortStatus = "Очень сухо"; + break; + case Comfort_TooHumid: + comfortStatus = "Очень влажно"; + break; + case Comfort_HotAndHumid: + comfortStatus = "Жарко и влажно"; + break; + case Comfort_HotAndDry: + comfortStatus = "Жарко и сухо"; + break; + case Comfort_ColdAndHumid: + comfortStatus = "Холодно и влажно"; + break; + case Comfort_ColdAndDry: + comfortStatus = "Холодно и сухо"; + break; + default: + comfortStatus = "Неизвестно"; + break; }; return comfortStatus; } //dhtDewpoint Точка#росы: Датчики 5 -void dhtD() { +void dhtD() +{ String widget_name = sCmd.next(); String page_name = sCmd.next(); String page_number = sCmd.next(); @@ -381,11 +465,15 @@ void dhtD() { sensors_reading_map[8] = 1; } -void dhtD_reading() { +void dhtD_reading() +{ float value; - if (dht.getStatus() != 0) { + if (dht.getStatus() != 0) + { sendSTATUS("dhtDewpoint", String(dht.getStatusString())); - } else { + } + else + { value = dht.computeDewPoint(jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); jsonWriteInt(configJson, "dhtDewpoint", value); eventGen("dhtDewpoint", ""); @@ -397,9 +485,10 @@ void dhtD_reading() { //=========================================i2c bus esp8266 scl-4 sda-5 ==================================================================== //========================================================================================================================================= //=========================================Модуль сенсоров bmp280========================================================================== -#ifdef bmp_enable + //bmp280T temp1 0x76 Температура#bmp280 Датчики any-data 1 -void bmp280T() { +void bmp280T() +{ String value_name = sCmd.next(); String address = sCmd.next(); String widget_name = sCmd.next(); @@ -418,7 +507,8 @@ void bmp280T() { sensors_reading_map[9] = 1; } -void bmp280T_rading() { +void bmp280T_reading() +{ float value = 0; sensors_event_t temp_event, pressure_event; bmp_temp->getEvent(&temp_event); @@ -430,7 +520,8 @@ void bmp280T_rading() { } //bmp280P press1 0x76 Давление#bmp280 Датчики any-data 2 -void bmp280P() { +void bmp280P() +{ String value_name = sCmd.next(); String address = sCmd.next(); String widget_name = sCmd.next(); @@ -449,7 +540,8 @@ void bmp280P() { sensors_reading_map[10] = 1; } -void bmp280P_reading() { +void bmp280P_reading() +{ float value = 0; sensors_event_t temp_event, pressure_event; bmp_pressure->getEvent(&pressure_event); @@ -460,12 +552,12 @@ void bmp280P_reading() { sendSTATUS(bmp280P_value_name, String(value)); Serial.println("[i] sensor '" + bmp280P_value_name + "' data: " + String(value)); } -#endif + //========================================================================================================================================= //=============================================Модуль сенсоров bme280====================================================================== -#ifdef bme_enable //bme280T temp1 0x76 Температура#bmp280 Датчики any-data 1 -void bme280T() { +void bme280T() +{ String value_name = sCmd.next(); String address = sCmd.next(); String widget_name = sCmd.next(); @@ -478,7 +570,8 @@ void bme280T() { sensors_reading_map[11] = 1; } -void bme280T_reading() { +void bme280T_reading() +{ float value = 0; value = bme.readTemperature(); jsonWriteStr(configJson, bme280T_value_name, String(value)); @@ -488,7 +581,8 @@ void bme280T_reading() { } //bme280P pres1 0x76 Давление#bmp280 Датчики any-data 1 -void bme280P() { +void bme280P() +{ String value_name = sCmd.next(); String address = sCmd.next(); String widget_name = sCmd.next(); @@ -501,7 +595,8 @@ void bme280P() { sensors_reading_map[12] = 1; } -void bme280P_reading() { +void bme280P_reading() +{ float value = 0; value = bme.readPressure(); value = value / 1.333224; @@ -512,7 +607,8 @@ void bme280P_reading() { } //bme280H hum1 0x76 Влажность#bmp280 Датчики any-data 1 -void bme280H() { +void bme280H() +{ String value_name = sCmd.next(); String address = sCmd.next(); String widget_name = sCmd.next(); @@ -525,7 +621,8 @@ void bme280H() { sensors_reading_map[13] = 1; } -void bme280H_reading() { +void bme280H_reading() +{ float value = 0; value = bme.readHumidity(); jsonWriteStr(configJson, bme280H_value_name, String(value)); @@ -535,7 +632,8 @@ void bme280H_reading() { } //bme280A altit1 0x76 Высота#bmp280 Датчики any-data 1 -void bme280A() { +void bme280A() +{ String value_name = sCmd.next(); String address = sCmd.next(); String widget_name = sCmd.next(); @@ -548,7 +646,8 @@ void bme280A() { sensors_reading_map[14] = 1; } -void bme280A_reading() { +void bme280A_reading() +{ float value = 0; value = bme.readAltitude(1013.25); jsonWriteStr(configJson, bme280A_value_name, String(value)); @@ -556,4 +655,3 @@ void bme280A_reading() { sendSTATUS(bme280A_value_name, String(value)); Serial.println("[i] sensor '" + bme280A_value_name + "' data: " + String(value)); } -#endif diff --git a/src/main.cpp b/src/main.cpp index 025f81f1..8b6d24f2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,8 +39,6 @@ String jsonWriteFloat(String& json, String name, float volume) { return json; } -//============================================================================================================ -//=============================================BIT AND BYTE=================================================== uint8_t hexStringToUint8(String hex) { uint8_t tmp = strtol(hex.c_str(), NULL, 0); if (tmp >= 0x00 && tmp <= 0xFF) { From aa1ad777c9452dceaaead761e7a9b6a11101efef Mon Sep 17 00:00:00 2001 From: Yuri Trikoz Date: Fri, 19 Jun 2020 03:49:56 +0300 Subject: [PATCH 04/17] 105.5% --- include/Global.h | 21 ++-- src/Global.cpp | 22 +++- src/Sensors.cpp | 287 +++++++++++++++++++---------------------------- 3 files changed, 144 insertions(+), 186 deletions(-) diff --git a/include/Global.h b/include/Global.h index e992709a..e1f3d898 100644 --- a/include/Global.h +++ b/include/Global.h @@ -114,8 +114,7 @@ extern AsyncEventSource events; extern int sensors_reading_map[15]; -enum -{ +enum { ROUTER_SEARCHING, WIFI_MQTT_CONNECTION_CHECK, SENSORS, @@ -154,7 +153,7 @@ extern int udp_period; #ifdef level_enable #include "GyverFilters.h" -GMedian<10, int> medianFilter; +extern GMedian<10, int> medianFilter; #endif #include @@ -163,23 +162,23 @@ extern OneWire *oneWire; extern DallasTemperature sensors; #include -DHTesp dht; +extern DHTesp dht; #include #ifdef bmp_enable #include -Adafruit_BMP280 bmp; // use I2C interface -Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor(); -Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor(); +extern Adafruit_BMP280 bmp; +extern Adafruit_Sensor *bmp_temp; +extern Adafruit_Sensor *bmp_pressure; #endif #ifdef bme_enable #include -Adafruit_BME280 bme; // use I2C interface -Adafruit_Sensor *bme_temp = bme.getTemperatureSensor(); -Adafruit_Sensor *bme_pressure = bme.getPressureSensor(); -Adafruit_Sensor *bme_humidity = bme.getHumiditySensor(); +extern Adafruit_BME280 bme; +extern Adafruit_Sensor *bme_temp; +extern Adafruit_Sensor *bme_pressure; +extern Adafruit_Sensor *bme_humidity; #endif //#include diff --git a/src/Global.cpp b/src/Global.cpp index 4df4e3e7..49f9f05d 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -99,6 +99,24 @@ int udp_period; // i2c String i2c_list; -extern OneWire *oneWire; -extern DallasTemperature sensors; +OneWire *oneWire; +DallasTemperature sensors; +DHTesp dht; + +#ifdef level_enable +GMedian<10, int> medianFilter; +#endif + +#ifdef bmp_enable +Adafruit_BMP280 bmp; +Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor(); +Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor(); +#endif + +#ifdef bme_enable +Adafruit_BME280 bme; +Adafruit_Sensor *bme_temp = bme.getTemperatureSensor(); +Adafruit_Sensor *bme_pressure = bme.getPressureSensor(); +Adafruit_Sensor *bme_humidity = bme.getHumiditySensor(); +#endif diff --git a/src/Sensors.cpp b/src/Sensors.cpp index a5a228bb..d9703a65 100644 --- a/src/Sensors.cpp +++ b/src/Sensors.cpp @@ -4,8 +4,7 @@ String perception(byte value); void bmp280T_reading(); String get_comfort_status(ComfortState cf); -void sensors_init() -{ +void sensors_init() { ts.add( SENSORS, 1000, [&](void *) { static int counter; @@ -16,8 +15,7 @@ void sensors_init() level_reading(); #endif - if (counter > 10) - { + if (counter > 10) { counter = 0; #ifdef analog_enable @@ -71,8 +69,7 @@ void sensors_init() //=========================================Модуль измерения уровня в баке================================================================== #ifdef level_enable //level L 14 12 Вода#в#баке,#% Датчики fill-gauge 125 20 1 -void level() -{ +void level() { String value_name = sCmd.next(); String trig = sCmd.next(); String echo = sCmd.next(); @@ -93,8 +90,7 @@ void level() sensors_reading_map[0] = 1; } -void level_reading() -{ +void level_reading() { long duration_; int distance_cm; int level; @@ -106,12 +102,11 @@ void level_reading() digitalWrite(trig, HIGH); delayMicroseconds(10); digitalWrite(trig, LOW); - duration_ = pulseIn(echo, HIGH, 30000); // 3000 µs = 50cm // 30000 µs = 5 m + duration_ = pulseIn(echo, HIGH, 30000); // 3000 µs = 50cm // 30000 µs = 5 m distance_cm = duration_ / 29 / 2; - distance_cm = medianFilter.filtered(distance_cm); //отсечение промахов медианным фильтром + distance_cm = medianFilter.filtered(distance_cm); //отсечение промахов медианным фильтром counter++; - if (counter > tank_level_times_to_send) - { + if (counter > tank_level_times_to_send) { counter = 0; level = map(distance_cm, jsonReadInt(optionJson, "e_lev"), @@ -127,8 +122,7 @@ void level_reading() //=========================================Модуль аналогового сенсора====================================================================== #ifdef analog_enable //analog adc 0 Аналоговый#вход,#% Датчики any-data 1 1023 1 100 1 -void analog() -{ +void analog() { String value_name = sCmd.next(); String pin = sCmd.next(); String widget_name = sCmd.next(); @@ -146,18 +140,15 @@ void analog() jsonWriteStr(optionJson, value_name + "_st_out", analog_start_out); jsonWriteStr(optionJson, value_name + "_end_out", analog_end_out); choose_widget_and_create(widget_name, page_name, page_number, type, value_name); - if (enter_to_analog_counter == 1) - { + if (enter_to_analog_counter == 1) { sensors_reading_map[1] = 1; } - if (enter_to_analog_counter == 2) - { + if (enter_to_analog_counter == 2) { sensors_reading_map[2] = 1; } } -void analog_reading1() -{ +void analog_reading1() { String value_name = selectFromMarkerToMarker(analog_value_names_list, ",", 0); #ifdef ESP32 int analog_in = analogRead(34); @@ -176,8 +167,7 @@ void analog_reading1() Serial.println("[i] sensor '" + value_name + "' data: " + String(analog)); } -void analog_reading2() -{ +void analog_reading2() { String value_name = selectFromMarkerToMarker(analog_value_names_list, ",", 1); #ifdef ESP32 int analog_in = analogRead(35); @@ -199,8 +189,7 @@ void analog_reading2() //========================================================================================================================================= //=========================================Модуль температурного сенсора ds18b20=========================================================== #ifdef dallas_enable -void dallas() -{ +void dallas() { String value_name = sCmd.next(); String pin = sCmd.next(); String address = sCmd.next(); @@ -216,8 +205,7 @@ void dallas() sensors_reading_map[3] = 1; } -void dallas_reading() -{ +void dallas_reading() { float temp = 0; sensors.requestTemperatures(); temp = sensors.getTempCByIndex(0); @@ -231,8 +219,7 @@ void dallas_reading() //=========================================Модуль сенсоров DHT============================================================================= #ifdef dht_enable //dhtT t 2 dht11 Температура#DHT,#t°C Датчики any-data 1 -void dhtT() -{ +void dhtT() { String value_name = sCmd.next(); String pin = sCmd.next(); String sensor_type = sCmd.next(); @@ -241,33 +228,26 @@ void dhtT() String type = sCmd.next(); String page_number = sCmd.next(); dhtT_value_name = value_name; - if (sensor_type == "dht11") - { + if (sensor_type == "dht11") { dht.setup(pin.toInt(), DHTesp::DHT11); } - if (sensor_type == "dht22") - { + if (sensor_type == "dht22") { dht.setup(pin.toInt(), DHTesp::DHT22); } choose_widget_and_create(widget_name, page_name, page_number, type, value_name); sensors_reading_map[4] = 1; } -void dhtT_reading() -{ +void dhtT_reading() { float value = 0; static int counter; - if (dht.getStatus() != 0 && counter < 5) - { + if (dht.getStatus() != 0 && counter < 5) { sendSTATUS(dhtT_value_name, String(dht.getStatusString())); counter++; - } - else - { + } else { counter = 0; value = dht.getTemperature(); - if (String(value) != "nan") - { + if (String(value) != "nan") { eventGen(dhtT_value_name, ""); jsonWriteStr(configJson, dhtT_value_name, String(value)); sendSTATUS(dhtT_value_name, String(value)); @@ -277,8 +257,7 @@ void dhtT_reading() } //dhtH h 2 dht11 Влажность#DHT,#t°C Датчики any-data 1 -void dhtH() -{ +void dhtH() { String value_name = sCmd.next(); String pin = sCmd.next(); String sensor_type = sCmd.next(); @@ -287,33 +266,26 @@ void dhtH() String type = sCmd.next(); String page_number = sCmd.next(); dhtH_value_name = value_name; - if (sensor_type == "dht11") - { + if (sensor_type == "dht11") { dht.setup(pin.toInt(), DHTesp::DHT11); } - if (sensor_type == "dht22") - { + if (sensor_type == "dht22") { dht.setup(pin.toInt(), DHTesp::DHT22); } choose_widget_and_create(widget_name, page_name, page_number, type, value_name); sensors_reading_map[5] = 1; } -void dhtH_reading() -{ +void dhtH_reading() { float value = 0; static int counter; - if (dht.getStatus() != 0 && counter < 5) - { + if (dht.getStatus() != 0 && counter < 5) { sendSTATUS(dhtH_value_name, String(dht.getStatusString())); counter++; - } - else - { + } else { counter = 0; value = dht.getHumidity(); - if (String(value) != "nan") - { + if (String(value) != "nan") { eventGen(dhtH_value_name, ""); jsonWriteStr(configJson, dhtH_value_name, String(value)); sendSTATUS(dhtH_value_name, String(value)); @@ -323,8 +295,7 @@ void dhtH_reading() } //dhtPerception Восприятие: Датчики 4 -void dhtP() -{ +void dhtP() { String widget_name = sCmd.next(); String page_name = sCmd.next(); String page_number = sCmd.next(); @@ -332,65 +303,57 @@ void dhtP() sensors_reading_map[6] = 1; } -void dhtP_reading() -{ +void dhtP_reading() { byte value; - if (dht.getStatus() != 0) - { + if (dht.getStatus() != 0) { sendSTATUS("dhtPerception", String(dht.getStatusString())); - } - else - { + } else { value = dht.computePerception(jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); String final_line = perception(value); jsonWriteStr(configJson, "dhtPerception", final_line); eventGen("dhtPerception", ""); sendSTATUS("dhtPerception", final_line); - if (client_mqtt.connected()) - { + if (client_mqtt.connected()) { Serial.println("[i] sensor 'dhtPerception' data: " + final_line); } } } -String perception(byte value) -{ +String perception(byte value) { String res; - switch (value) - { - case 0: - res = F("Сухой воздух"); - break; - case 1: - res = F("Комфортно"); - break; - case 2: - res = F("Уютно"); - break; - case 3: - res = F("Хорошо"); - break; - case 4: - res = F("Неудобно"); - break; - case 5: - res = F("Довольно неудобно"); - break; - case 6: - res = F("Очень неудобно"); - break; - case 7: - res = F("Сильно неудобно, полный звиздец"); - default: - res = F("Unknown"); - break; + switch (value) { + case 0: + res = F("Сухой воздух"); + break; + case 1: + res = F("Комфортно"); + break; + case 2: + res = F("Уютно"); + break; + case 3: + res = F("Хорошо"); + break; + case 4: + res = F("Неудобно"); + break; + case 5: + res = F("Довольно неудобно"); + break; + case 6: + res = F("Очень неудобно"); + break; + case 7: + res = F("Сильно неудобно, полный звиздец"); + default: + res = F("Unknown"); + break; } return res; } //dhtComfort Степень#комфорта: Датчики 3 -void dhtC() -{ +void dhtC() { String widget_name = sCmd.next(); String page_name = sCmd.next(); String page_number = sCmd.next(); @@ -398,15 +361,12 @@ void dhtC() sensors_reading_map[7] = 1; } -void dhtC_reading() -{ +void dhtC_reading() { + float value; ComfortState cf; - if (dht.getStatus() != 0) - { + if (dht.getStatus() != 0) { sendSTATUS("dhtComfort", String(dht.getStatusString())); - } - else - { + } else { value = dht.getComfortRatio(cf, jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); String final_line = get_comfort_status(cf); jsonWriteStr(configJson, "dhtComfort", final_line); @@ -416,48 +376,45 @@ void dhtC_reading() } } -String get_comfort_status(ComfortState cf) -{ +String get_comfort_status(ComfortState cf) { String comfortStatus; - switch (cf) - { - case Comfort_OK: - comfortStatus = "Отлично"; - break; - case Comfort_TooHot: - comfortStatus = "Очень жарко"; - break; - case Comfort_TooCold: - comfortStatus = "Очень холодно"; - break; - case Comfort_TooDry: - comfortStatus = "Очень сухо"; - break; - case Comfort_TooHumid: - comfortStatus = "Очень влажно"; - break; - case Comfort_HotAndHumid: - comfortStatus = "Жарко и влажно"; - break; - case Comfort_HotAndDry: - comfortStatus = "Жарко и сухо"; - break; - case Comfort_ColdAndHumid: - comfortStatus = "Холодно и влажно"; - break; - case Comfort_ColdAndDry: - comfortStatus = "Холодно и сухо"; - break; - default: - comfortStatus = "Неизвестно"; - break; + switch (cf) { + case Comfort_OK: + comfortStatus = "Отлично"; + break; + case Comfort_TooHot: + comfortStatus = "Очень жарко"; + break; + case Comfort_TooCold: + comfortStatus = "Очень холодно"; + break; + case Comfort_TooDry: + comfortStatus = "Очень сухо"; + break; + case Comfort_TooHumid: + comfortStatus = "Очень влажно"; + break; + case Comfort_HotAndHumid: + comfortStatus = "Жарко и влажно"; + break; + case Comfort_HotAndDry: + comfortStatus = "Жарко и сухо"; + break; + case Comfort_ColdAndHumid: + comfortStatus = "Холодно и влажно"; + break; + case Comfort_ColdAndDry: + comfortStatus = "Холодно и сухо"; + break; + default: + comfortStatus = "Неизвестно"; + break; }; return comfortStatus; } //dhtDewpoint Точка#росы: Датчики 5 -void dhtD() -{ +void dhtD() { String widget_name = sCmd.next(); String page_name = sCmd.next(); String page_number = sCmd.next(); @@ -465,15 +422,11 @@ void dhtD() sensors_reading_map[8] = 1; } -void dhtD_reading() -{ +void dhtD_reading() { float value; - if (dht.getStatus() != 0) - { + if (dht.getStatus() != 0) { sendSTATUS("dhtDewpoint", String(dht.getStatusString())); - } - else - { + } else { value = dht.computeDewPoint(jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); jsonWriteInt(configJson, "dhtDewpoint", value); eventGen("dhtDewpoint", ""); @@ -487,8 +440,7 @@ void dhtD_reading() //=========================================Модуль сенсоров bmp280========================================================================== //bmp280T temp1 0x76 Температура#bmp280 Датчики any-data 1 -void bmp280T() -{ +void bmp280T() { String value_name = sCmd.next(); String address = sCmd.next(); String widget_name = sCmd.next(); @@ -507,8 +459,7 @@ void bmp280T() sensors_reading_map[9] = 1; } -void bmp280T_reading() -{ +void bmp280T_reading() { float value = 0; sensors_event_t temp_event, pressure_event; bmp_temp->getEvent(&temp_event); @@ -520,8 +471,7 @@ void bmp280T_reading() } //bmp280P press1 0x76 Давление#bmp280 Датчики any-data 2 -void bmp280P() -{ +void bmp280P() { String value_name = sCmd.next(); String address = sCmd.next(); String widget_name = sCmd.next(); @@ -540,8 +490,7 @@ void bmp280P() sensors_reading_map[10] = 1; } -void bmp280P_reading() -{ +void bmp280P_reading() { float value = 0; sensors_event_t temp_event, pressure_event; bmp_pressure->getEvent(&pressure_event); @@ -556,8 +505,7 @@ void bmp280P_reading() //========================================================================================================================================= //=============================================Модуль сенсоров bme280====================================================================== //bme280T temp1 0x76 Температура#bmp280 Датчики any-data 1 -void bme280T() -{ +void bme280T() { String value_name = sCmd.next(); String address = sCmd.next(); String widget_name = sCmd.next(); @@ -570,8 +518,7 @@ void bme280T() sensors_reading_map[11] = 1; } -void bme280T_reading() -{ +void bme280T_reading() { float value = 0; value = bme.readTemperature(); jsonWriteStr(configJson, bme280T_value_name, String(value)); @@ -581,8 +528,7 @@ void bme280T_reading() } //bme280P pres1 0x76 Давление#bmp280 Датчики any-data 1 -void bme280P() -{ +void bme280P() { String value_name = sCmd.next(); String address = sCmd.next(); String widget_name = sCmd.next(); @@ -595,8 +541,7 @@ void bme280P() sensors_reading_map[12] = 1; } -void bme280P_reading() -{ +void bme280P_reading() { float value = 0; value = bme.readPressure(); value = value / 1.333224; @@ -607,8 +552,7 @@ void bme280P_reading() } //bme280H hum1 0x76 Влажность#bmp280 Датчики any-data 1 -void bme280H() -{ +void bme280H() { String value_name = sCmd.next(); String address = sCmd.next(); String widget_name = sCmd.next(); @@ -621,8 +565,7 @@ void bme280H() sensors_reading_map[13] = 1; } -void bme280H_reading() -{ +void bme280H_reading() { float value = 0; value = bme.readHumidity(); jsonWriteStr(configJson, bme280H_value_name, String(value)); @@ -632,8 +575,7 @@ void bme280H_reading() } //bme280A altit1 0x76 Высота#bmp280 Датчики any-data 1 -void bme280A() -{ +void bme280A() { String value_name = sCmd.next(); String address = sCmd.next(); String widget_name = sCmd.next(); @@ -646,8 +588,7 @@ void bme280A() sensors_reading_map[14] = 1; } -void bme280A_reading() -{ +void bme280A_reading() { float value = 0; value = bme.readAltitude(1013.25); jsonWriteStr(configJson, bme280A_value_name, String(value)); From 15aa8c8539b6bb5f6025273e876030ff629056dd Mon Sep 17 00:00:00 2001 From: Yuri Trikoz Date: Fri, 19 Jun 2020 07:27:06 +0300 Subject: [PATCH 05/17] Utils --- include/JsonUtils.h | 43 +++++++++++++ include/StringUtils.h | 64 ++++++++++++++++++++ src/Global.cpp | 2 + src/Sensors.cpp | 1 + src/main.cpp | 138 ++++-------------------------------------- 5 files changed, 122 insertions(+), 126 deletions(-) create mode 100644 include/JsonUtils.h create mode 100644 include/StringUtils.h diff --git a/include/JsonUtils.h b/include/JsonUtils.h new file mode 100644 index 00000000..41f0cd0a --- /dev/null +++ b/include/JsonUtils.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include + +String jsonReadStr(String& json, String name) { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(json); + return root[name].as(); +} + +int jsonReadInt(String& json, String name) { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(json); + return root[name]; +} + +String jsonWriteStr(String& json, String name, String volume) { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(json); + root[name] = volume; + json = ""; + root.printTo(json); + return json; +} + +String jsonWriteInt(String& json, String name, int volume) { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(json); + root[name] = volume; + json = ""; + root.printTo(json); + return json; +} + +String jsonWriteFloat(String& json, String name, float volume) { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.parseObject(json); + root[name] = volume; + json = ""; + root.printTo(json); + return json; +} \ No newline at end of file diff --git a/include/StringUtils.h b/include/StringUtils.h new file mode 100644 index 00000000..5693520e --- /dev/null +++ b/include/StringUtils.h @@ -0,0 +1,64 @@ +#pragma once + +#include "Arduino.h" + +String selectToMarkerLast(String str, String found) { + int p = str.lastIndexOf(found); + return str.substring(p + found.length()); +} + +String selectToMarker(String str, String found) { + int p = str.indexOf(found); + return str.substring(0, p); +} + +String deleteAfterDelimiter(String str, String found) { + int p = str.indexOf(found); + return str.substring(0, p); +} + +String deleteBeforeDelimiter(String str, String found) { + int p = str.indexOf(found) + found.length(); + return str.substring(p); +} + +String deleteBeforeDelimiterTo(String str, String found) { + int p = str.indexOf(found); + return str.substring(p); +} + +String deleteToMarkerLast(String str, String found) { + int p = str.lastIndexOf(found); + return str.substring(0, p); +} + +String selectToMarkerPlus(String str, String found, int plus) { + int p = str.indexOf(found); + 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; // Индекс перебора + do { + if (i == number) return selectToMarker(str, found); // если индекс совпал с позицией законцим вернем резултат + str = deleteBeforeDelimiter(str, found); // отбросим проверенный блок до разделителя + i++; // увеличим индекс + } while (str.length() != 0); // повторим пока строка не пустая + return "not found"; // Достигли пустой строки и ничего не нашли +} + +inline uint8_t hexStringToUint8(String hex) { + uint8_t tmp = strtol(hex.c_str(), NULL, 0); + if (tmp >= 0x00 && tmp <= 0xFF) { + return tmp; + } +} + +inline uint16_t hexStringToUint16(String hex) { + uint16_t tmp = strtol(hex.c_str(), NULL, 0); + if (tmp >= 0x0000 && tmp <= 0xFFFF) { + return tmp; + } +} diff --git a/src/Global.cpp b/src/Global.cpp index 49f9f05d..ff0f1245 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -1,5 +1,7 @@ #include "Global.h" +#include "JsonUtils.h" + TickerScheduler ts(TEST + 1); WiFiClient espClient; diff --git a/src/Sensors.cpp b/src/Sensors.cpp index d9703a65..256c956d 100644 --- a/src/Sensors.cpp +++ b/src/Sensors.cpp @@ -1,4 +1,5 @@ #include "Global.h" +#include "StringUtils.h" String perception(byte value); void bmp280T_reading(); diff --git a/src/main.cpp b/src/main.cpp index 8b6d24f2..369a670a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,113 +1,9 @@ #include "Global.h" -String jsonReadStr(String& json, String name) { - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(json); - return root[name].as(); -} - -int jsonReadInt(String& json, String name) { - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(json); - return root[name]; -} - -String jsonWriteStr(String& json, String name, String volume) { - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(json); - root[name] = volume; - json = ""; - root.printTo(json); - return json; -} - -String jsonWriteInt(String& json, String name, int volume) { - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(json); - root[name] = volume; - json = ""; - root.printTo(json); - return json; -} - -String jsonWriteFloat(String& json, String name, float volume) { - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.parseObject(json); - root[name] = volume; - json = ""; - root.printTo(json); - return json; -} - -uint8_t hexStringToUint8(String hex) { - uint8_t tmp = strtol(hex.c_str(), NULL, 0); - if (tmp >= 0x00 && tmp <= 0xFF) { - return tmp; - } -} - -uint16_t hexStringToUint16(String hex) { - uint16_t tmp = strtol(hex.c_str(), NULL, 0); - if (tmp >= 0x0000 && tmp <= 0xFFFF) { - return tmp; - } -} - void saveConfig() { writeFile("config.json", configSetup); } -//============================================================================================================ -//=============================================STRING=================================================== - -// --------Выделяем строку от конца строки до маркера----------------------------------------------------------- -String selectToMarkerLast(String str, String found) { - int p = str.lastIndexOf(found); - return str.substring(p + found.length()); -} - -String selectToMarker(String str, String found) { - int p = str.indexOf(found); - return str.substring(0, p); -} - -String deleteAfterDelimiter(String str, String found) { - int p = str.indexOf(found); - return str.substring(0, p); -} - -String deleteBeforeDelimiter(String str, String found) { - int p = str.indexOf(found) + found.length(); - return str.substring(p); -} - -String deleteBeforeDelimiterTo(String str, String found) { - int p = str.indexOf(found); - return str.substring(p); -} - -// -------------------Выделяем строку от конца строки до маркера ------------------------------------------------ -String deleteToMarkerLast(String str, String found) { - int p = str.lastIndexOf(found); - return str.substring(0, p); -} -// -------------------Выделяем строку от конца строки до маркера + ---------------------------------------------- -String selectToMarkerPlus(String str, String found, int plus) { - int p = str.indexOf(found); - 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; // Индекс перебора - do { - if (i == number) return selectToMarker(str, found); // если индекс совпал с позицией законцим вернем резултат - str = deleteBeforeDelimiter(str, found); // отбросим проверенный блок до разделителя - i++; // увеличим индекс - } while (str.length() != 0); // повторим пока строка не пустая - return "not found"; // Достигли пустой строки и ничего не нашли -} //--------------------Посчитать ----------------------------------------------------------------------------------- int count(String str, String found) { if (str.indexOf(found) == -1) return 0; // если строки поиск нет сразу выход @@ -120,40 +16,29 @@ int count(String str, String found) { return i; // Достигли пустой строки и ничего не нашли } - boolean isDigitStr(String str) { - for (int i = 0; i < str.length(); i++) { - if (!isDigit(str.charAt(i))) { + for (int i = 0; i < str.length(); i++) { + if (!isDigit(str.charAt(i))) { return false; } } return str.length(); } -// boolean digit(String str) { -// if (str == "0" || str == "1" || str == "2" || str == "3" || str == "4" || str == "5" || str == "6" || str == "7" || str == "8" || str == "9") { -// return true; -// } else { -// return false; -// } -// } - String getURL(String urls) { - String answer = ""; + String res = ""; HTTPClient http; - http.begin(urls); //HTTP + http.begin(urls); int httpCode = http.GET(); if (httpCode == HTTP_CODE_OK) { - answer = http.getString(); + res = http.getString(); } else { - answer = "error"; + res = "error"; } http.end(); - return answer; + return res; } -//=================================================================================================================== -//===========================================FILES=================================================================== -// ------------- Добавление файла ----------------------------------------------------------------------------------- + void safeDataToFile(String data, String Folder) { //String fileName = GetDate(); String fileName; @@ -259,8 +144,7 @@ void led_blink(String satus) { #endif #endif } -//========================================================================================================================= -//=========================================ОСТАВШАЯСЯ ОПЕРАТИВНАЯ ПАМЯТЬ=================================================== + void getMemoryLoad(String text) { #ifdef ESP8266 int all_memory = 52864; @@ -271,7 +155,9 @@ void getMemoryLoad(String text) { int memory_remain = ESP.getFreeHeap(); int memory_used = all_memory - memory_remain; int memory_load = (memory_used * 100) / all_memory; - if (memory_load > 65) Serial.print("Attention!!! too match memory used!!!"); + if (memory_load > 65) { + Serial.println("Memory low!"); + } Serial.print(text + " memory used:"); Serial.print(String(memory_load) + "%; "); Serial.print("memory remain: "); From 02855b5ab91de955112590c4729c4acd96c6564a Mon Sep 17 00:00:00 2001 From: Yuri Trikoz Date: Fri, 19 Jun 2020 07:48:31 +0300 Subject: [PATCH 06/17] remove dupe strings --- include/Global.h | 39 +++++++++++++++++------------------- src/Upgrade.cpp | 52 +++++++++++++++++++----------------------------- src/main.cpp | 2 +- 3 files changed, 40 insertions(+), 53 deletions(-) diff --git a/include/Global.h b/include/Global.h index e1f3d898..31084b2c 100644 --- a/include/Global.h +++ b/include/Global.h @@ -184,6 +184,23 @@ extern Adafruit_Sensor *bme_humidity; //#include //SoftwareSerial mySerial(14, 12); +// StringUtils +extern uint8_t hexStringToUint8(String hex); +extern uint16_t hexStringToUint16(String hex); +extern String selectToMarkerLast(String str, String found); +extern String selectToMarker(String str, String found); +extern String deleteAfterDelimiter(String str, String found); +extern String deleteBeforeDelimiter(String str, String found); +extern String deleteBeforeDelimiterTo(String str, String found); +extern String selectFromMarkerToMarker(String str, String found, int number); + +// JsonUtils +extern String jsonReadStr(String &json, String name); +extern int jsonReadInt(String &json, String name); +extern String jsonWriteInt(String &json, String name, int volume); +extern String jsonWriteStr(String &json, String name, String volume); +extern String jsonWriteFloat(String &json, String name, float volume); + // Cmd extern void CMD_init(); extern void button(); @@ -240,33 +257,13 @@ extern void choose_log_date_and_send(); // Main void getMemoryLoad(String text); - -extern String jsonReadStr(String &json, String name); -extern int jsonReadInt(String &json, String name); -extern String jsonWriteInt(String &json, String name, int volume); -extern String jsonWriteStr(String &json, String name, String volume); extern void saveConfig(); -extern String jsonWriteFloat(String &json, String name, float volume); - -extern String getURL(String urls); +extern String getURL(const String &urls); extern String writeFile(String fileName, String strings); extern String readFile(String fileName, size_t len); extern String addFile(String fileName, String strings); -// Main Utils - явно -extern uint8_t hexStringToUint8(String hex); -extern uint16_t hexStringToUint16(String hex); - -//STRING -extern String selectToMarkerLast(String str, String found); -extern String selectToMarker(String str, String found); -extern String deleteAfterDelimiter(String str, String found); -extern String deleteBeforeDelimiter(String str, String found); -extern String deleteBeforeDelimiterTo(String str, String found); - -extern String selectFromMarkerToMarker(String str, String found, int number); - extern void servo_(); extern boolean isDigitStr(String str); extern String jsonWriteStr(String &json, String name, String volume); diff --git a/src/Upgrade.cpp b/src/Upgrade.cpp index 8d83c739..726a8414 100644 --- a/src/Upgrade.cpp +++ b/src/Upgrade.cpp @@ -1,20 +1,29 @@ #include "Global.h" -static const char* UPGRADE_URL PROGMEM = "http://91.204.228.124:1100/update/"; - -const String getUpgradeUrl() { - String url = FPSTR(UPGRADE_URL); +static const char* UPDATE_URL PROGMEM = "http://91.204.228.124:1100/update/%s/%s"; +static const char* FIRMWARE_FILE = "esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"; #ifdef ESP32 - url += "esp32"; +static const char* MCU = "esp32"; #else - url += "esp8266"; +static const char* MCU = "esp8266"; #endif - url += "/version.txt"; - return url; + +const String createUrl(const char* qry) { + char buf[128]; + sprintf_P(buf, UPDATE_URL, MCU, qry); + return String(buf); +} + +const String getVersionUrl() { + return createUrl("version.txt"); +} + +const String getFirmwareUrl() { + return createUrl(FIRMWARE_FILE); } void initUpgrade() { - String last_version = WiFi.status() == WL_CONNECTED ? getURL(getUpgradeUrl()) : ""; + String last_version = WiFi.status() == WL_CONNECTED ? getURL(getVersionUrl()) : ""; jsonWriteStr(configSetup, "last_version", last_version); Serial.printf("[i] Last firmware version: %s\n", last_version.c_str()); @@ -63,14 +72,8 @@ void initUpgrade() { void do_upgrade_url() { if (upgrade_url) { upgrade_url = false; -#ifdef ESP32 - last_version = getURL("http://91.204.228.124:1100/update/esp32/version.txt"); + last_version = getURL(getVersionUrl()); jsonWriteStr(configSetup, "last_version", last_version); -#endif -#ifdef ESP8266 - last_version = getURL("http://91.204.228.124:1100/update/esp8266/version.txt"); - jsonWriteStr(configSetup, "last_version", last_version); -#endif } } @@ -86,14 +89,8 @@ void upgrade_firmware() { WiFiClient client_for_upgrade; -#ifdef ESP32 httpUpdate.rebootOnUpdate(false); - t_httpUpdate_return ret = httpUpdate.updateSpiffs(client_for_upgrade, "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"); -#endif -#ifdef ESP8266 - ESPhttpUpdate.rebootOnUpdate(false); - t_httpUpdate_return ret = ESPhttpUpdate.updateSpiffs(client_for_upgrade, "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"); -#endif + t_httpUpdate_return ret = httpUpdate.updateSpiffs(client_for_upgrade, getFirmwareUrl()); if (ret == HTTP_UPDATE_OK) { writeFile("firmware.s.txt", scenario_for_update); @@ -104,14 +101,7 @@ void upgrade_firmware() { Serial.println("SPIFFS upgrade done!"); Serial.println("Start upgrade BUILD, please wait..."); -#ifdef ESP32 - //httpUpdate.rebootOnUpdate(true); - t_httpUpdate_return ret = httpUpdate.update(client_for_upgrade, "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.ino.bin"); -#endif -#ifdef ESP8266 - //ESPhttpUpdate.rebootOnUpdate(true); - t_httpUpdate_return ret = ESPhttpUpdate.update(client_for_upgrade, "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.ino.bin"); -#endif + t_httpUpdate_return ret = httpUpdate.update(client_for_upgrade, getFirmwareUrl()); if (ret == HTTP_UPDATE_OK) { Serial.println("BUILD upgrade done!"); diff --git a/src/main.cpp b/src/main.cpp index 369a670a..60f78de6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,7 +25,7 @@ boolean isDigitStr(String str) { return str.length(); } -String getURL(String urls) { +String getURL(const String& urls) { String res = ""; HTTPClient http; http.begin(urls); From 2edba7baba55a67a9826290139b75ed39d233e34 Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Fri, 19 Jun 2020 12:59:35 +0200 Subject: [PATCH 07/17] Partitions for ESP32 --- partitions_custom.csv | 6 ++++++ platformio.ini | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 partitions_custom.csv diff --git a/partitions_custom.csv b/partitions_custom.csv new file mode 100644 index 00000000..86202b53 --- /dev/null +++ b/partitions_custom.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +ota_0, app, ota_0, 0x10000, 0x1A0000 +ota_1, app, ota_1, , 0x1A0000 +otadata, data, ota, 0x350000, 0x2000 +nvs, data, nvs, , 0x6000 +data, data, spiffs, , 0xA8000 \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 16f15936..83d84cae 100644 --- a/platformio.ini +++ b/platformio.ini @@ -23,7 +23,7 @@ lib_deps= Adafruit BMP280 Library Adafruit BME280 Library -#board_build.partitions = partitions_custom.csv +board_build.partitions = partitions_custom.csv [env:esp32dev] platform = espressif32 From 2a45769cafe27e1dd22e8018cc1ce90baf144de9 Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Fri, 19 Jun 2020 13:30:44 +0200 Subject: [PATCH 08/17] Com port speed settings added --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index 83d84cae..df62c63c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,4 +29,5 @@ board_build.partitions = partitions_custom.csv platform = espressif32 board = esp32dev framework = arduino +monitor_speed = 115200 From e6637dcd698b09292fc04e3b879bb1a351f7e064 Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Fri, 19 Jun 2020 13:48:25 +0200 Subject: [PATCH 09/17] deleted some files, will be changed to new ones soon --- data/configs/analog.c.txt | 8 -------- data/configs/analog.s.txt | 1 - data/configs/dallas.c.txt | 5 ----- data/configs/dallas.s.txt | 1 - data/configs/dht11.c.txt | 7 ------- data/configs/dht11.s.txt | 1 - data/configs/dht22.c.txt | 7 ------- data/configs/dht22.s.txt | 1 - data/configs/firmware.c.txt | 12 ------------ data/configs/firmware.s.txt | 13 ------------- data/configs/level.c.txt | 11 ----------- data/configs/level.s.txt | 6 ------ data/configs/moution_r.c.txt | 11 ----------- data/configs/moution_r.s.txt | 7 ------- data/configs/moution_s.c.txt | 12 ------------ data/configs/moution_s.s.txt | 10 ---------- data/configs/pwm.c.txt | 6 ------ data/configs/pwm.s.txt | 1 - data/configs/relay.c.txt | 3 --- data/configs/relay.s.txt | 1 - data/configs/relay_br.c.txt | 6 ------ data/configs/relay_br.s.txt | 8 -------- data/configs/relay_c.c.txt | 4 ---- data/configs/relay_c.s.txt | 6 ------ data/configs/relay_rm.c.txt | 3 --- data/configs/relay_rm.s.txt | 3 --- data/configs/relay_s.c.txt | 3 --- data/configs/relay_s.s.txt | 8 -------- data/configs/relay_sr.c.txt | 6 ------ data/configs/relay_sr.s.txt | 4 ---- data/configs/relay_sw.c.txt | 4 ---- data/configs/relay_sw.s.txt | 3 --- data/configs/relay_t.c.txt | 6 ------ data/configs/relay_t.s.txt | 6 ------ data/configs/servo.c.txt | 17 ----------------- data/configs/servo.s.txt | 12 ------------ data/configs/stepper.c.txt | 17 ----------------- data/configs/stepper.s.txt | 12 ------------ data/configs/termostat.c.txt | 12 ------------ data/configs/termostat.s.txt | 6 ------ data/widgets/outstanding/widget.select.json | 7 ------- 41 files changed, 277 deletions(-) delete mode 100644 data/configs/analog.c.txt delete mode 100644 data/configs/analog.s.txt delete mode 100644 data/configs/dallas.c.txt delete mode 100644 data/configs/dallas.s.txt delete mode 100644 data/configs/dht11.c.txt delete mode 100644 data/configs/dht11.s.txt delete mode 100644 data/configs/dht22.c.txt delete mode 100644 data/configs/dht22.s.txt delete mode 100644 data/configs/firmware.c.txt delete mode 100644 data/configs/firmware.s.txt delete mode 100644 data/configs/level.c.txt delete mode 100644 data/configs/level.s.txt delete mode 100644 data/configs/moution_r.c.txt delete mode 100644 data/configs/moution_r.s.txt delete mode 100644 data/configs/moution_s.c.txt delete mode 100644 data/configs/moution_s.s.txt delete mode 100644 data/configs/pwm.c.txt delete mode 100644 data/configs/pwm.s.txt delete mode 100644 data/configs/relay.c.txt delete mode 100644 data/configs/relay.s.txt delete mode 100644 data/configs/relay_br.c.txt delete mode 100644 data/configs/relay_br.s.txt delete mode 100644 data/configs/relay_c.c.txt delete mode 100644 data/configs/relay_c.s.txt delete mode 100644 data/configs/relay_rm.c.txt delete mode 100644 data/configs/relay_rm.s.txt delete mode 100644 data/configs/relay_s.c.txt delete mode 100644 data/configs/relay_s.s.txt delete mode 100644 data/configs/relay_sr.c.txt delete mode 100644 data/configs/relay_sr.s.txt delete mode 100644 data/configs/relay_sw.c.txt delete mode 100644 data/configs/relay_sw.s.txt delete mode 100644 data/configs/relay_t.c.txt delete mode 100644 data/configs/relay_t.s.txt delete mode 100644 data/configs/servo.c.txt delete mode 100644 data/configs/servo.s.txt delete mode 100644 data/configs/stepper.c.txt delete mode 100644 data/configs/stepper.s.txt delete mode 100644 data/configs/termostat.c.txt delete mode 100644 data/configs/termostat.s.txt delete mode 100644 data/widgets/outstanding/widget.select.json diff --git a/data/configs/analog.c.txt b/data/configs/analog.c.txt deleted file mode 100644 index 429ccada..00000000 --- a/data/configs/analog.c.txt +++ /dev/null @@ -1,8 +0,0 @@ -analog adc 0 Аналоговый#вход,#% Датчики progress-round 310 620 1 100 1 -logging adc 5 100 Аналоговый#вход Датчики 2 - -//если датчик углекислого газа выдает напряжение от 1 вольта до 2 вольт, то значит -//значение чтения аналогового входа будут примерно равным -//при 1 вольте - 310, а при 2 вольтах - 620 (считаем по пропорции) -//данная строка переведет диапазон 310-620 в диапазон 1-100 и отобразит в приложении -//варианты отображения: any-data, progress-round, progress-line, fill-gauge diff --git a/data/configs/analog.s.txt b/data/configs/analog.s.txt deleted file mode 100644 index 8b137891..00000000 --- a/data/configs/analog.s.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/data/configs/dallas.c.txt b/data/configs/dallas.c.txt deleted file mode 100644 index e6686b14..00000000 --- a/data/configs/dallas.c.txt +++ /dev/null @@ -1,5 +0,0 @@ -dallas 2 Водонагреватель,#t°C Датчики any-data 1 -logging dallas 1 100 Температура Датчики 2 - -//2 - номер пина датчика -//варианты отображения: any-data, progress-round, progress-line, fill-gauge \ No newline at end of file diff --git a/data/configs/dallas.s.txt b/data/configs/dallas.s.txt deleted file mode 100644 index 8b137891..00000000 --- a/data/configs/dallas.s.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/data/configs/dht11.c.txt b/data/configs/dht11.c.txt deleted file mode 100644 index ce8ec1a8..00000000 --- a/data/configs/dht11.c.txt +++ /dev/null @@ -1,7 +0,0 @@ -dhtT t 2 dht11 Температура#DHT,#t°C Датчики any-data 1 -dhtH h 2 dht11 Влажность#DHT,#t°C Датчики any-data 2 -dhtComfort Степень#комфорта: Датчики 3 -dhtPerception Восприятие: Датчики 4 -dhtDewpoint Точка#росы: Датчики 5 -logging t 1 50 Температура Датчики 6 -logging h 1 50 Влажность Датчики 7 \ No newline at end of file diff --git a/data/configs/dht11.s.txt b/data/configs/dht11.s.txt deleted file mode 100644 index 8b137891..00000000 --- a/data/configs/dht11.s.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/data/configs/dht22.c.txt b/data/configs/dht22.c.txt deleted file mode 100644 index a0124e41..00000000 --- a/data/configs/dht22.c.txt +++ /dev/null @@ -1,7 +0,0 @@ -dhtT t 2 dht22 Температура#DHT,#t°C Датчики any-data 1 -dhtH h 2 dht22 Влажность#DHT,#t°C Датчики any-data 2 -dhtComfort Степень#комфорта: Датчики 3 -dhtPerception Восприятие: Датчики 4 -dhtDewpoint Точка#росы: Датчики 5 -logging t 1 50 Температура Датчики 6 -logging h 1 50 Влажность Датчики 7 \ No newline at end of file diff --git a/data/configs/dht22.s.txt b/data/configs/dht22.s.txt deleted file mode 100644 index 8b137891..00000000 --- a/data/configs/dht22.s.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/data/configs/firmware.c.txt b/data/configs/firmware.c.txt deleted file mode 100644 index 99beb0be..00000000 --- a/data/configs/firmware.c.txt +++ /dev/null @@ -1,12 +0,0 @@ -button 1 na Включить#все Реле 0 1 -button 2 13 Прихожая Реле 0 2 -button 3 14 Кухня Реле 0 3 -pwm 1 3 Яркость#коредор: Реле 1023 4 -pwm 2 4 Яркость#ванная: Реле 510 5 -analog adc 0 Аналоговый#вход Датчики fill-gauge 1 1023 1 1023 6 -logging adc 1 100 Аналоговый#вход Датчики 7 - -//Это демо конфигурация. В ней показано как связать кнопки c помощью сценариев -//Кнопка номер 1 связана с кнопкой 2, 3 и с pwm 2 -//Так же продемонстрированна система логгирования данных строкой logging -//1 - это интервал между точками в минутах, 100 это количество точек \ No newline at end of file diff --git a/data/configs/firmware.s.txt b/data/configs/firmware.s.txt deleted file mode 100644 index 4927ac1e..00000000 --- a/data/configs/firmware.s.txt +++ /dev/null @@ -1,13 +0,0 @@ -button1 = 1 -buttonSet 2 1 -buttonSet 3 1 -pwmSet 2 1024 -end -button1 = 0 -buttonSet 2 0 -buttonSet 3 0 -pwmSet 2 0 -end -adc > 50 -buttonSet 2 1 -end \ No newline at end of file diff --git a/data/configs/level.c.txt b/data/configs/level.c.txt deleted file mode 100644 index 619af218..00000000 --- a/data/configs/level.c.txt +++ /dev/null @@ -1,11 +0,0 @@ -level lev 14 12 Вода#в#баке,#% Датчики fill-gauge 125 20 1 -inputDigit digit1 При#скольки#выключить? Датчики 95 2 -inputDigit digit2 При#скольки#включить? Датчики 10 3 -button 1 5 Насос Датчики 0 4 -button 2 line1,line2, Автоматический#режим Датчики 1 5 -logging lev 1 100 Вода#в#баке Датчики 6 - -//125 - это расстояние от датчика до дна бака в сантиметрах -//20 - это расстояние от датчика до поверхности воды когда бак полный в сантиметрах -//вывод данных будет в процентах заполнения бака -//варианты отображения: any-data, progress-round, progress-line, fill-gauge \ No newline at end of file diff --git a/data/configs/level.s.txt b/data/configs/level.s.txt deleted file mode 100644 index 12f881be..00000000 --- a/data/configs/level.s.txt +++ /dev/null @@ -1,6 +0,0 @@ -lev > digit1 -buttonSet 1 0 -end -lev < digit2 -buttonSet 1 1 -end \ No newline at end of file diff --git a/data/configs/moution_r.c.txt b/data/configs/moution_r.c.txt deleted file mode 100644 index fa0b78ac..00000000 --- a/data/configs/moution_r.c.txt +++ /dev/null @@ -1,11 +0,0 @@ -button 1 5 Прихожая Освещение 0 1 -inputDigit digit1 Задержка#выключения Освещение 30 2 -switch 1 0 10 - -//0 - номер пина датчика движения -//5 - номер пина реле -//при срабатывании датчика движения включится реле и обратный таймер на 30 сек -//если движение не будет обнаружено повтороно в течении 30 секунд - свет выключится -//если движение повторится в течении 30 секунд то таймер продлится опять на 30 сек -//свет выключится только в том случае если в комнате все замрет на 30 сек -//задержку выключения можно будет настраивать в приложении \ No newline at end of file diff --git a/data/configs/moution_r.s.txt b/data/configs/moution_r.s.txt deleted file mode 100644 index 899b7035..00000000 --- a/data/configs/moution_r.s.txt +++ /dev/null @@ -1,7 +0,0 @@ -switch1 = 1 -timerStart 1 digit1 sec -buttonSet 1 1 -end -timer1 = 0 -buttonSet 1 0 -end \ No newline at end of file diff --git a/data/configs/moution_s.c.txt b/data/configs/moution_s.c.txt deleted file mode 100644 index bc7d8192..00000000 --- a/data/configs/moution_s.c.txt +++ /dev/null @@ -1,12 +0,0 @@ -switch 1 0 20 -text 1 Вход: Охрана 1 -textSet 1 не#обнаружено-time -button 1 na Сбросить Охрана 0 2 -button 2 line3, Включить#push Охрана 1 3 - -//0 - номер пина датчика -//при срабатывании датчика движения устройство пошлет пуш и в приложении будет -//написано в текстовом поле, что движение было обнаружено -//так же будет зафиксирован момент времени срабатывания датчика -//в приложении можно отключать отправку пуш сообщений на тот случай если дома хозяин -//перевести датчик снова в режим ожидания движения можно нажав кнопку сброса в приложении \ No newline at end of file diff --git a/data/configs/moution_s.s.txt b/data/configs/moution_s.s.txt deleted file mode 100644 index f764dc9d..00000000 --- a/data/configs/moution_s.s.txt +++ /dev/null @@ -1,10 +0,0 @@ -switch1 = 1 -textSet 1 обнаружено#движение-time -end -button1 = 1 -textSet 1 не#обнаружено-time -buttonSet 1 0 -end -switch1 = 1 -push Внимание обнаружено#движение! -end \ No newline at end of file diff --git a/data/configs/pwm.c.txt b/data/configs/pwm.c.txt deleted file mode 100644 index 09eef72c..00000000 --- a/data/configs/pwm.c.txt +++ /dev/null @@ -1,6 +0,0 @@ -pwm 1 3 Яркость#коредор: Реле 1023 1 -pwm 2 4 Яркость#ванная: Реле 510 2 - -//в приложении появятся ползунки, соответствующее значение pwm -//будет установленно на пинах 3 и 4 -//1023 и 510 это начальные значения после загрузки модуля \ No newline at end of file diff --git a/data/configs/pwm.s.txt b/data/configs/pwm.s.txt deleted file mode 100644 index 8b137891..00000000 --- a/data/configs/pwm.s.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/data/configs/relay.c.txt b/data/configs/relay.c.txt deleted file mode 100644 index 733f4c95..00000000 --- a/data/configs/relay.c.txt +++ /dev/null @@ -1,3 +0,0 @@ -button 1 5 Включить#реле Реле 0 1 - -//это простая кнопка номер 1 управляющая пином 5 имеющая начальное состояние 0 \ No newline at end of file diff --git a/data/configs/relay.s.txt b/data/configs/relay.s.txt deleted file mode 100644 index 8b137891..00000000 --- a/data/configs/relay.s.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/data/configs/relay_br.c.txt b/data/configs/relay_br.c.txt deleted file mode 100644 index db812455..00000000 --- a/data/configs/relay_br.c.txt +++ /dev/null @@ -1,6 +0,0 @@ -button 1 5 Включить#все Реле 0 1 - - -//что бы использовать эту конфигурацию на другой esp необходимо активировать пресет -//"Вкл. выкл. локального реле", затем в сценарии данного модуля подставить Device ID -//того esp, кнопка на этом девайсе будет выключать другие устройства по воздуху \ No newline at end of file diff --git a/data/configs/relay_br.s.txt b/data/configs/relay_br.s.txt deleted file mode 100644 index 9eb30933..00000000 --- a/data/configs/relay_br.s.txt +++ /dev/null @@ -1,8 +0,0 @@ -button1 = 1 -mqtt 3233662-1589485 buttonSet_1_1 -mqtt 2233662-1589486 buttonSet_1_1 -end -button1 = 0 -mqtt 3233662-1589485 buttonSet_1_0 -mqtt 2233662-1589486 buttonSet_1_0 -end \ No newline at end of file diff --git a/data/configs/relay_c.c.txt b/data/configs/relay_c.c.txt deleted file mode 100644 index 9f0c5c45..00000000 --- a/data/configs/relay_c.c.txt +++ /dev/null @@ -1,4 +0,0 @@ -button 1 5 Вкл#на#время Таймеры 0 1 -inputDigit digit1 Через#сколько#секунд#выключить? Таймеры 5 2 - -//в сценариях можно поменять на sec, min или hours если нужны другие размерности времени \ No newline at end of file diff --git a/data/configs/relay_c.s.txt b/data/configs/relay_c.s.txt deleted file mode 100644 index f8ced990..00000000 --- a/data/configs/relay_c.s.txt +++ /dev/null @@ -1,6 +0,0 @@ -button1 = 1 -timerStart 1 digit1 sec -end -timer1 = 0 -buttonSet 1 0 -end \ No newline at end of file diff --git a/data/configs/relay_rm.c.txt b/data/configs/relay_rm.c.txt deleted file mode 100644 index 92abc26d..00000000 --- a/data/configs/relay_rm.c.txt +++ /dev/null @@ -1,3 +0,0 @@ -switch 1 0 10 - -//физическая кнопка номер 1 подключенная к пину 0, задержка от дребезга 10 мс \ No newline at end of file diff --git a/data/configs/relay_rm.s.txt b/data/configs/relay_rm.s.txt deleted file mode 100644 index 827e1495..00000000 --- a/data/configs/relay_rm.s.txt +++ /dev/null @@ -1,3 +0,0 @@ -switch1 = 1 -mqtt 3233662-1589489 buttonChange_1 -end \ No newline at end of file diff --git a/data/configs/relay_s.c.txt b/data/configs/relay_s.c.txt deleted file mode 100644 index b0978b0d..00000000 --- a/data/configs/relay_s.c.txt +++ /dev/null @@ -1,3 +0,0 @@ -button 1 na Включить#все Освещение 0 1 - -//при нажатии на эту кнопку пины номер 5 и 13 поведут себя как установленно в сценариях \ No newline at end of file diff --git a/data/configs/relay_s.s.txt b/data/configs/relay_s.s.txt deleted file mode 100644 index 276282c3..00000000 --- a/data/configs/relay_s.s.txt +++ /dev/null @@ -1,8 +0,0 @@ -button1 = 1 -pinSet 5 1 -pinSet 13 0 -end -button1 = 0 -pinSet 5 0 -pinSet 13 1 -end \ No newline at end of file diff --git a/data/configs/relay_sr.c.txt b/data/configs/relay_sr.c.txt deleted file mode 100644 index 739a1424..00000000 --- a/data/configs/relay_sr.c.txt +++ /dev/null @@ -1,6 +0,0 @@ -switch 1 0 10 - -//что бы использовать эту конфигурацию на другой esp необходимо активировать пресет -//"Вкл. выкл. локального реле", затем в сценарии данного модуля подставить Device ID -//того esp, к данному модулю нужно подключить кнопку к пину 0 и тогда -//один девайс будет управлять другим по воздуху \ No newline at end of file diff --git a/data/configs/relay_sr.s.txt b/data/configs/relay_sr.s.txt deleted file mode 100644 index 0c48cbdf..00000000 --- a/data/configs/relay_sr.s.txt +++ /dev/null @@ -1,4 +0,0 @@ -switch1 = 1 -mqtt 3233662-1589485 buttonChange_1 -mqtt 2233662-1589486 buttonChange_1 -end \ No newline at end of file diff --git a/data/configs/relay_sw.c.txt b/data/configs/relay_sw.c.txt deleted file mode 100644 index 5ef7e5f5..00000000 --- a/data/configs/relay_sw.c.txt +++ /dev/null @@ -1,4 +0,0 @@ -button 1 13 Включить#реле Реле 0 1 -switch 1 0 10 - -//можно управлять реле на пине 13 кнопкой на пине 0 или кнопкой в приложении \ No newline at end of file diff --git a/data/configs/relay_sw.s.txt b/data/configs/relay_sw.s.txt deleted file mode 100644 index 093de1fe..00000000 --- a/data/configs/relay_sw.s.txt +++ /dev/null @@ -1,3 +0,0 @@ -switch1 = 1 -buttonChange 1 -end \ No newline at end of file diff --git a/data/configs/relay_t.c.txt b/data/configs/relay_t.c.txt deleted file mode 100644 index 1e54f5dd..00000000 --- a/data/configs/relay_t.c.txt +++ /dev/null @@ -1,6 +0,0 @@ -inputTime time1 Во#сколько#включить? Таймеры 20-30-00 1 -inputTime time2 Во#сколько#выключить? Таймеры 20-35-00 2 -button 1 5 Кнопка#(по#таймеру) Таймеры 0 3 - -//время в приложение необходимо вводить в строгом формате: ЧЧ-ММ-СС -//можно создавать любое количество таймеров, копируя строку inputTime... \ No newline at end of file diff --git a/data/configs/relay_t.s.txt b/data/configs/relay_t.s.txt deleted file mode 100644 index 5deba589..00000000 --- a/data/configs/relay_t.s.txt +++ /dev/null @@ -1,6 +0,0 @@ -timenow = time1 -buttonSet 1 1 -end -timenow = time2 -buttonSet 1 0 -end diff --git a/data/configs/servo.c.txt b/data/configs/servo.c.txt deleted file mode 100644 index 5d45aea0..00000000 --- a/data/configs/servo.c.txt +++ /dev/null @@ -1,17 +0,0 @@ -servo 1 12 50 Мой#сервопривод Сервоприводы 0 100 0 180 1 -servo 2 13 50 Мой#сервопривод Сервоприводы 0 100 0 180 2 -button 1 na Открыть1 Сервоприводы 0 3 -button 2 na Открыть2 Сервоприводы 0 4 - -//Можно создавать не более двух сервоприводов на одном устройстве. -//1 - номер привода -//12 - номер пина -//50 - начальное значение в процентах - -//0 - 100 диапазон ползунка -//0 - 180 диапазон угла - -//Представим ситуацию когда есть некая заслонка и при угле в 30 градусов она закрыта, -//а при угле в 90 градусов открыта. В этом случае необходимо написать -//0 100 30 90 и тогда поставив ползунок в 0 % серва встанет в положение 30 градусов, -//а если поставить ползунок в 100 % серва встанет в положение 90 градусов. \ No newline at end of file diff --git a/data/configs/servo.s.txt b/data/configs/servo.s.txt deleted file mode 100644 index b4340463..00000000 --- a/data/configs/servo.s.txt +++ /dev/null @@ -1,12 +0,0 @@ -button1 = 1 -servoSet 1 100 -end -button1 = 0 -servoSet 1 0 -end -button2 = 1 -servoSet 2 100 -end -button2 = 0 -servoSet 2 0 -end \ No newline at end of file diff --git a/data/configs/stepper.c.txt b/data/configs/stepper.c.txt deleted file mode 100644 index 82b41ae2..00000000 --- a/data/configs/stepper.c.txt +++ /dev/null @@ -1,17 +0,0 @@ -stepper 1 12 4 -stepper 2 13 5 -button 1 na Открыть#штору#1 Шторы 0 1 -button 2 na Открыть#штору#2 Шторы 0 2 - -//для подключения необходим драйвер шагового двигателя A4988 - -//stepper 1 12 4 шаговый двигатель с параметрами: 1 - номер шагового двигателя, -//12 - номер пина количества шагов, 4 - номер пина направления - -//stepper 2 13 5 шаговый двигатель с параметрами: 2 - номер шагового двигателя, -//13 - номер пина количества шагов, 5 - номер пина направления - -//stepperSet 1 200 5 - прокрутить шаговик номер 1 на 200 шагов по часовой стрелке -//с задержкой между шагами 5 милисекунд (чем меньше задержка тем больше скорость) -//если поставить -200 то будет вращаться против часовой стрелки -//можно подключить не более двух шаговиков \ No newline at end of file diff --git a/data/configs/stepper.s.txt b/data/configs/stepper.s.txt deleted file mode 100644 index 16e7cfa6..00000000 --- a/data/configs/stepper.s.txt +++ /dev/null @@ -1,12 +0,0 @@ -button1 = 1 -stepperSet 1 200 1 -end -button1 = 0 -stepperSet 1 -200 1 -end -button2 = 1 -stepperSet 2 200 1 -end -button2 = 0 -stepperSet 2 -200 1 -end \ No newline at end of file diff --git a/data/configs/termostat.c.txt b/data/configs/termostat.c.txt deleted file mode 100644 index af75deeb..00000000 --- a/data/configs/termostat.c.txt +++ /dev/null @@ -1,12 +0,0 @@ -dallas 2 Водонагреватель,#t°C Термостат any-data 1 -logging dallas 5 100 Температура Термостат 2 -inputDigit digit1 При#скольки#выключить? Термостат 40 3 -inputDigit digit2 При#скольки#включить? Термостат 20 4 -button 1 5 Нагреватель Термостат 0 5 -button 2 line1,line2, Автоматический#режим Термостат 1 6 - -//2 - номер пина датчика -//5 - номер пина реле -//это термостат который будет держать температуру между двумя -//установленными в приложении значениями, так же можно выключить -//автоматический режим, и тогда нагреватель будет управляться в ручную \ No newline at end of file diff --git a/data/configs/termostat.s.txt b/data/configs/termostat.s.txt deleted file mode 100644 index 60782623..00000000 --- a/data/configs/termostat.s.txt +++ /dev/null @@ -1,6 +0,0 @@ -dallas > digit1 -buttonSet 1 0 -end -dallas < digit2 -buttonSet 1 1 -end \ No newline at end of file diff --git a/data/widgets/outstanding/widget.select.json b/data/widgets/outstanding/widget.select.json deleted file mode 100644 index c6531b70..00000000 --- a/data/widgets/outstanding/widget.select.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "widget" : "select", - "size" : "small", - "fill" : "outline", - "options" : "["Zero item", "First item", "Second item"]", - "status" : 2 -} \ No newline at end of file From 48ba3c99dde9f24d4be66a39527c454362b53635 Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Fri, 19 Jun 2020 14:50:34 +0200 Subject: [PATCH 10/17] changed json var names to more visible --- include/Global.h | 17 ++- include/push_pushingbox.h | 4 +- src/Cmd.cpp | 302 +++++++++++++++++++++++--------------- src/FileSystem.cpp | 20 +-- src/Global.cpp | 6 +- src/Init.cpp | 16 +- src/Logging.cpp | 12 +- src/Mqtt.cpp | 42 +++--- src/Scenario.cpp | 32 ++-- src/Sensors.cpp | 175 ++++++++++++---------- src/TimeUtils.cpp | 12 +- src/Timers.cpp | 18 +-- src/Upgrade.cpp | 16 +- src/Web_server.cpp | 18 +-- src/WiFiUtils.cpp | 30 ++-- src/i2c_bus.cpp | 4 +- src/main.cpp | 6 +- src/udp.cpp | 38 ++--- 18 files changed, 428 insertions(+), 340 deletions(-) diff --git a/include/Global.h b/include/Global.h index 31084b2c..19c43cfa 100644 --- a/include/Global.h +++ b/include/Global.h @@ -61,9 +61,9 @@ extern AsyncWebServer server; extern boolean just_load; extern const char *hostName; -extern String configSetup; -extern String configJson; -extern String optionJson; +extern String configSetupJson; //все настройки +extern String configLiveJson; //все данные с датчиков (связан с mqtt) +extern String configOptionJson; //для трансфера extern String chipID; extern String prex; @@ -74,7 +74,8 @@ extern String order_loop; extern String analog_value_names_list; extern int enter_to_analog_counter; -extern String level_value_name; +extern String levelPr_value_name; +extern String ultrasonicCm_value_name; extern String dhtT_value_name; extern String dhtH_value_name; @@ -228,8 +229,8 @@ extern void text(); extern void textSet(); extern void mqttOrderSend(); extern void httpOrderSend(); -extern void firmware(); -extern void update_firmware(); +extern void firmwareVersion(); +extern void firmwareUpdate(); extern void Scenario_init(); extern void txtExecution(String file); extern void stringExecution(String str); @@ -295,9 +296,11 @@ extern String add_set(String param_name); // И как раз тут хорошо просто в Sensors.h это пихать - а не в один здоровенный ФАЙЛ extern void sensors_init(); -extern void level(); +extern void levelPr(); +extern void ultrasonicCm(); extern void level_reading(); + extern void analog(); extern void analog_reading1(); extern void analog_reading2(); diff --git a/include/push_pushingbox.h b/include/push_pushingbox.h index a96626ef..e7b92c34 100644 --- a/include/push_pushingbox.h +++ b/include/push_pushingbox.h @@ -5,7 +5,7 @@ void Push_init() { server.on("/pushingboxDate", HTTP_GET, [](AsyncWebServerRequest* request) { if (request->hasArg("pushingbox_id")) { - jsonWriteStr(configSetup, "pushingbox_id", request->getParam("pushingbox_id")->value()); + jsonWriteStr(configSetupJson, "pushingbox_id", request->getParam("pushingbox_id")->value()); } saveConfig(); @@ -23,7 +23,7 @@ inline void pushControl() { static String body_old; const char* logServer = "api.pushingbox.com"; - String deviceId = jsonReadStr(configSetup, "pushingbox_id"); + String deviceId = jsonReadStr(configSetupJson, "pushingbox_id"); Serial.println("- starting client"); diff --git a/src/Cmd.cpp b/src/Cmd.cpp index c9a0c566..2390ccb7 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -2,7 +2,8 @@ #include "push_pushingbox.h" -void CMD_init() { +void CMD_init() +{ sCmd.addCommand("button", button); sCmd.addCommand("buttonSet", buttonSet); sCmd.addCommand("buttonChange", buttonChange); @@ -19,7 +20,8 @@ void CMD_init() { sCmd.addCommand("analog", analog); #endif #ifdef level_enable - sCmd.addCommand("level", level); + sCmd.addCommand("levelPr", levelPr); + sCmd.addCommand("ultrasonicCm", ultrasonicCm); #endif #ifdef dallas_enable sCmd.addCommand("dallas", dallas); @@ -82,13 +84,14 @@ void CMD_init() { sCmd.addCommand("push", pushControl); #endif - sCmd.addCommand("update", update_firmware); - sCmd.addCommand("firmware", firmware); + sCmd.addCommand("firmwareUpdate", firmwareUpdate); + sCmd.addCommand("firmwareVersion", firmwareVersion); handle_time_init(); } -void button() { +void button() +{ String button_number = sCmd.next(); String button_param = sCmd.next(); String widget_name = sCmd.next(); @@ -96,26 +99,31 @@ void button() { String start_state = sCmd.next(); String page_number = sCmd.next(); - jsonWriteStr(optionJson, "button_param" + button_number, button_param); - jsonWriteStr(configJson, "button" + button_number, start_state); + jsonWriteStr(configOptionJson, "button_param" + button_number, button_param); + jsonWriteStr(configLiveJson, "button" + button_number, start_state); - if (isDigitStr(button_param)) { + if (isDigitStr(button_param)) + { pinMode(button_param.toInt(), OUTPUT); digitalWrite(button_param.toInt(), start_state.toInt()); } - if (button_param == "scenario") { - jsonWriteStr(configSetup, "scenario", start_state); + if (button_param == "scenario") + { + jsonWriteStr(configSetupJson, "scenario", start_state); Scenario_init(); saveConfig(); } - if (button_param.indexOf("line") != -1) { + if (button_param.indexOf("line") != -1) + { String str = button_param; - while (str.length() != 0) { - if (str == "") return; - String tmp = selectToMarker(str, ","); //line1, - String number = deleteBeforeDelimiter(tmp, "e"); //1, + while (str.length() != 0) + { + if (str == "") + return; + String tmp = selectToMarker(str, ","); //line1, + String number = deleteBeforeDelimiter(tmp, "e"); //1, number.replace(",", ""); Serial.println(number); int number_int = number.toInt(); @@ -126,27 +134,33 @@ void button() { createWidget(widget_name, page_name, page_number, "widgets/widget.toggle.json", "button" + button_number); } -void buttonSet() { +void buttonSet() +{ String button_number = sCmd.next(); String button_state = sCmd.next(); - String button_param = jsonReadStr(optionJson, "button_param" + button_number); + String button_param = jsonReadStr(configOptionJson, "button_param" + button_number); - if (button_param != "na" || button_param != "scenario" || button_param.indexOf("line") != -1) { + if (button_param != "na" || button_param != "scenario" || button_param.indexOf("line") != -1) + { digitalWrite(button_param.toInt(), button_state.toInt()); } - if (button_param == "scenario") { - jsonWriteStr(configSetup, "scenario", button_state); + if (button_param == "scenario") + { + jsonWriteStr(configSetupJson, "scenario", button_state); Scenario_init(); saveConfig(); } - if (button_param.indexOf("line") != -1) { + if (button_param.indexOf("line") != -1) + { String str = button_param; - while (str.length() != 0) { - if (str == "") return; - String tmp = selectToMarker(str, ","); //line1, - String number = deleteBeforeDelimiter(tmp, "e"); //1, + while (str.length() != 0) + { + if (str == "") + return; + String tmp = selectToMarker(str, ","); //line1, + String number = deleteBeforeDelimiter(tmp, "e"); //1, number.replace(",", ""); Serial.println(number); int number_int = number.toInt(); @@ -157,37 +171,44 @@ void buttonSet() { eventGen("button", button_number); - jsonWriteStr(configJson, "button" + button_number, button_state); + jsonWriteStr(configLiveJson, "button" + button_number, button_state); sendSTATUS("button" + button_number, button_state); } -void buttonChange() { +void buttonChange() +{ String button_number = sCmd.next(); - String current_state = jsonReadStr(configJson, "button" + button_number); - if (current_state == "1") { + String current_state = jsonReadStr(configLiveJson, "button" + button_number); + if (current_state == "1") + { current_state = "0"; - } else if (current_state == "0") { + } + else if (current_state == "0") + { current_state = "1"; } order_loop += "buttonSet " + button_number + " " + current_state + ","; - jsonWriteStr(configJson, "button" + button_number, current_state); + jsonWriteStr(configLiveJson, "button" + button_number, current_state); sendSTATUS("button" + button_number, current_state); } -void pinSet() { +void pinSet() +{ String pin_number = sCmd.next(); String pin_state = sCmd.next(); pinMode(pin_number.toInt(), OUTPUT); digitalWrite(pin_number.toInt(), pin_state.toInt()); } -void pinChange() { +void pinChange() +{ String pin_number = sCmd.next(); pinMode(pin_number.toInt(), OUTPUT); digitalWrite(pin_number.toInt(), !digitalRead(pin_number.toInt())); } -void pwm() { +void pwm() +{ // TODO Unused // static boolean flag = true; String pwm_number = sCmd.next(); @@ -199,29 +220,31 @@ void pwm() { String page_number = sCmd.next(); uint8_t pwm_pin_int = pwm_pin.toInt(); - jsonWriteStr(optionJson, "pwm_pin" + pwm_number, pwm_pin); + jsonWriteStr(configOptionJson, "pwm_pin" + pwm_number, pwm_pin); pinMode(pwm_pin_int, INPUT); analogWrite(pwm_pin_int, start_state.toInt()); - jsonWriteStr(configJson, "pwm" + pwm_number, start_state); + jsonWriteStr(configLiveJson, "pwm" + pwm_number, start_state); createWidget(widget_name, page_name, page_number, "widgets/widget.range.json", "pwm" + pwm_number); } -void pwmSet() { +void pwmSet() +{ String pwm_number = sCmd.next(); String pwm_state = sCmd.next(); int pwm_state_int = pwm_state.toInt(); - int pin = jsonReadInt(optionJson, "pwm_pin" + pwm_number); + int pin = jsonReadInt(configOptionJson, "pwm_pin" + pwm_number); analogWrite(pin, pwm_state_int); eventGen("pwm", pwm_number); - jsonWriteStr(configJson, "pwm" + pwm_number, pwm_state); + jsonWriteStr(configLiveJson, "pwm" + pwm_number, pwm_state); sendSTATUS("pwm" + pwm_number, pwm_state); } //================================================================================================================== //==========================================Модуль физической кнопки================================================ -void switch_() { +void switch_() +{ String switch_number = sCmd.next(); String switch_pin = sCmd.next(); String switch_delay = sCmd.next(); @@ -231,27 +254,33 @@ void switch_() { but[switch_number.toInt()] = true; } -void handleButton() { +void handleButton() +{ static uint8_t switch_number = 1; - if (but[switch_number]) { + if (but[switch_number]) + { buttons[switch_number].update(); - if (buttons[switch_number].fell()) { + if (buttons[switch_number].fell()) + { eventGen("switch", String(switch_number)); - jsonWriteStr(configJson, "switch" + String(switch_number), "1"); + jsonWriteStr(configLiveJson, "switch" + String(switch_number), "1"); } - if (buttons[switch_number].rose()) { + if (buttons[switch_number].rose()) + { eventGen("switch", String(switch_number)); - jsonWriteStr(configJson, "switch" + String(switch_number), "0"); + jsonWriteStr(configLiveJson, "switch" + String(switch_number), "0"); } } switch_number++; - if (switch_number == NUM_BUTTONS) switch_number = 0; + if (switch_number == NUM_BUTTONS) + switch_number = 0; } -void inputDigit() { +void inputDigit() +{ String value_name = sCmd.next(); String number = value_name.substring(5); String widget_name = sCmd.next(); @@ -260,18 +289,20 @@ void inputDigit() { page_name.replace("#", " "); String start_state = sCmd.next(); String page_number = sCmd.next(); - jsonWriteStr(configJson, "digit" + number, start_state); + jsonWriteStr(configLiveJson, "digit" + number, start_state); createWidget(widget_name, page_name, page_number, "widgets/widget.inputNum.json", "digit" + number); } -void digitSet() { +void digitSet() +{ String number = sCmd.next(); String value = sCmd.next(); - jsonWriteStr(configJson, "digit" + number, value); + jsonWriteStr(configLiveJson, "digit" + number, value); sendSTATUS("digit" + number, value); } -void inputTime() { +void inputTime() +{ String value_name = sCmd.next(); String number = value_name.substring(4); String widget_name = sCmd.next(); @@ -280,30 +311,33 @@ void inputTime() { page_name.replace("#", " "); String start_state = sCmd.next(); String page_number = sCmd.next(); - jsonWriteStr(configJson, "time" + number, start_state); + jsonWriteStr(configLiveJson, "time" + number, start_state); createWidget(widget_name, page_name, page_number, "widgets/widget.inputTime.json", "time" + number); } -void timeSet() { +void timeSet() +{ String number = sCmd.next(); String value = sCmd.next(); - jsonWriteStr(configJson, "time" + number, value); + jsonWriteStr(configLiveJson, "time" + number, value); sendSTATUS("time" + number, value); } -void handle_time_init() { +void handle_time_init() +{ ts.add( - TIME, 1000, [&](void*) { + TIME, 1000, [&](void *) { String tmp = GetTime(); - jsonWriteStr(configJson, "time", tmp); + jsonWriteStr(configLiveJson, "time", tmp); tmp.replace(":", "-"); - jsonWriteStr(configJson, "timenow", tmp); + jsonWriteStr(configLiveJson, "timenow", tmp); eventGen("timenow", ""); }, nullptr, true); } -void text() { +void text() +{ String number = sCmd.next(); String widget_name = sCmd.next(); String page_name = sCmd.next(); @@ -312,12 +346,14 @@ void text() { createWidget(widget_name, page_name, page_number, "widgets/widget.anyData.json", "text" + number); } -void textSet() { +void textSet() +{ String number = sCmd.next(); String text = sCmd.next(); text.replace("_", " "); - if (text.indexOf("-time") >= 0) { + if (text.indexOf("-time") >= 0) + { text.replace("-time", ""); text.replace("#", " "); String time = GetTime(); @@ -325,44 +361,50 @@ void textSet() { text = text + " " + GetDataDigital() + " " + time; } - jsonWriteStr(configJson, "text" + number, text); + jsonWriteStr(configLiveJson, "text" + number, text); sendSTATUS("text" + number, text); } #ifdef stepper_enable //stepper 1 12 13 -void stepper() { +void stepper() +{ String stepper_number = sCmd.next(); String pin_step = sCmd.next(); String pin_dir = sCmd.next(); - jsonWriteStr(optionJson, "stepper" + stepper_number, pin_step + " " + pin_dir); + jsonWriteStr(configOptionJson, "stepper" + stepper_number, pin_step + " " + pin_dir); pinMode(pin_step.toInt(), OUTPUT); pinMode(pin_dir.toInt(), OUTPUT); } //stepperSet 1 100 5 -void stepperSet() { +void stepperSet() +{ String stepper_number = sCmd.next(); String steps = sCmd.next(); - jsonWriteStr(optionJson, "steps" + stepper_number, steps); + jsonWriteStr(configOptionJson, "steps" + stepper_number, steps); String stepper_speed = sCmd.next(); - String pin_step = selectToMarker(jsonReadStr(optionJson, "stepper" + stepper_number), " "); - String pin_dir = deleteBeforeDelimiter(jsonReadStr(optionJson, "stepper" + stepper_number), " "); + String pin_step = selectToMarker(jsonReadStr(configOptionJson, "stepper" + stepper_number), " "); + String pin_dir = deleteBeforeDelimiter(jsonReadStr(configOptionJson, "stepper" + stepper_number), " "); Serial.println(pin_step); Serial.println(pin_dir); - if (steps.toInt() > 0) digitalWrite(pin_dir.toInt(), HIGH); - if (steps.toInt() < 0) digitalWrite(pin_dir.toInt(), LOW); - if (stepper_number == "1") { + if (steps.toInt() > 0) + digitalWrite(pin_dir.toInt(), HIGH); + if (steps.toInt() < 0) + digitalWrite(pin_dir.toInt(), LOW); + if (stepper_number == "1") + { ts.add( - STEPPER1, stepper_speed.toInt(), [&](void*) { - int steps_int = abs(jsonReadInt(optionJson, "steps1") * 2); + STEPPER1, stepper_speed.toInt(), [&](void *) { + int steps_int = abs(jsonReadInt(configOptionJson, "steps1") * 2); static int count; count++; - String pin_step = selectToMarker(jsonReadStr(optionJson, "stepper1"), " "); + String pin_step = selectToMarker(jsonReadStr(configOptionJson, "stepper1"), " "); digitalWrite(pin_step.toInt(), !digitalRead(pin_step.toInt())); yield(); - if (count > steps_int) { + if (count > steps_int) + { digitalWrite(pin_step.toInt(), LOW); ts.remove(STEPPER1); count = 0; @@ -370,16 +412,18 @@ void stepperSet() { }, nullptr, true); } - if (stepper_number == "2") { + if (stepper_number == "2") + { ts.add( - STEPPER2, stepper_speed.toInt(), [&](void*) { - int steps_int = abs(jsonReadInt(optionJson, "steps2") * 2); + STEPPER2, stepper_speed.toInt(), [&](void *) { + int steps_int = abs(jsonReadInt(configOptionJson, "steps2") * 2); static int count; count++; - String pin_step = selectToMarker(jsonReadStr(optionJson, "stepper2"), " "); + String pin_step = selectToMarker(jsonReadStr(configOptionJson, "stepper2"), " "); digitalWrite(pin_step.toInt(), !digitalRead(pin_step.toInt())); yield(); - if (count > steps_int) { + if (count > steps_int) + { digitalWrite(pin_step.toInt(), LOW); ts.remove(STEPPER2); count = 0; @@ -393,7 +437,8 @@ void stepperSet() { //=================================================================Сервоприводы======================================================================= #ifdef servo_enable //servo 1 13 50 Мой#сервопривод Сервоприводы 0 100 0 180 2 -void servo_() { +void servo_() +{ String servo_number = sCmd.next(); String servo_pin = sCmd.next(); String start_state = sCmd.next(); @@ -409,10 +454,11 @@ void servo_() { String page_number = sCmd.next(); - jsonWriteStr(optionJson, "servo_pin" + servo_number, servo_pin); + jsonWriteStr(configOptionJson, "servo_pin" + servo_number, servo_pin); start_state_int = map(start_state_int, min_value.toInt(), max_value.toInt(), min_deg.toInt(), max_deg.toInt()); - if (servo_number == "1") { + if (servo_number == "1") + { #ifdef ESP8266 myServo1.attach(servo_pin.toInt()); myServo1.write(start_state_int); @@ -423,7 +469,8 @@ void servo_() { #endif } - if (servo_number == "2") { + if (servo_number == "2") + { #ifdef ESP8266 myServo2.attach(servo_pin.toInt()); myServo2.write(start_state_int); @@ -434,31 +481,33 @@ void servo_() { #endif } - jsonWriteStr(optionJson, "s_min_val" + servo_number, min_value); - jsonWriteStr(optionJson, "s_max_val" + servo_number, max_value); - jsonWriteStr(optionJson, "s_min_deg" + servo_number, min_deg); - jsonWriteStr(optionJson, "s_max_deg" + servo_number, max_deg); + jsonWriteStr(configOptionJson, "s_min_val" + servo_number, min_value); + jsonWriteStr(configOptionJson, "s_max_val" + servo_number, max_value); + jsonWriteStr(configOptionJson, "s_min_deg" + servo_number, min_deg); + jsonWriteStr(configOptionJson, "s_max_deg" + servo_number, max_deg); - jsonWriteStr(configJson, "servo" + servo_number, start_state); + jsonWriteStr(configLiveJson, "servo" + servo_number, start_state); createWidgetParam(widget_name, page_name, page_number, "widgets/widget.range.json", "servo" + servo_number, "min", min_value, "max", max_value, "k", "1"); } -void servoSet() { +void servoSet() +{ String servo_number = sCmd.next(); String servo_state = sCmd.next(); int servo_state_int = servo_state.toInt(); // TODO Unused - //int pin = jsonReadInt(optionJson, "servo_pin" + servo_number); + //int pin = jsonReadInt(configOptionJson, "servo_pin" + servo_number); servo_state_int = map(servo_state_int, - jsonReadInt(optionJson, "s_min_val" + servo_number), - jsonReadInt(optionJson, "s_max_val" + servo_number), - jsonReadInt(optionJson, "s_min_deg" + servo_number), - jsonReadInt(optionJson, "s_max_deg" + servo_number)); + jsonReadInt(configOptionJson, "s_min_val" + servo_number), + jsonReadInt(configOptionJson, "s_max_val" + servo_number), + jsonReadInt(configOptionJson, "s_min_deg" + servo_number), + jsonReadInt(configOptionJson, "s_max_deg" + servo_number)); - if (servo_number == "1") { + if (servo_number == "1") + { #ifdef ESP8266 myServo1.write(servo_state_int); #endif @@ -467,7 +516,8 @@ void servoSet() { #endif } - if (servo_number == "2") { + if (servo_number == "2") + { #ifdef ESP8266 myServo2.write(servo_state_int); #endif @@ -478,14 +528,15 @@ void servoSet() { eventGen("servo", servo_number); - jsonWriteStr(configJson, "servo" + servo_number, servo_state); + jsonWriteStr(configLiveJson, "servo" + servo_number, servo_state); sendSTATUS("servo" + servo_number, servo_state); } #endif //==================================================================================================================================================== //===================================================================================serial=========================================================== #ifdef serial_enable -void serialBegin() { +void serialBegin() +{ //String s_speed = sCmd.next(); //String rxPin = sCmd.next(); //String txPin = sCmd.next(); @@ -493,7 +544,8 @@ void serialBegin() { //mySerial.begin(s_speed.toInt()); } -void serialWrite() { +void serialWrite() +{ //String text = sCmd.next(); //mySerial.println(text); } @@ -501,15 +553,17 @@ void serialWrite() { //==================================================================================================================================================== //=================================================Глобальные команды удаленного управления=========================================================== -void mqttOrderSend() { +void mqttOrderSend() +{ String id = sCmd.next(); String order = sCmd.next(); - String all_line = jsonReadStr(configSetup, "mqttPrefix") + "/" + id + "/order"; + String all_line = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + id + "/order"; client_mqtt.publish(all_line.c_str(), order.c_str(), false); } -void httpOrderSend() { +void httpOrderSend() +{ String ip = sCmd.next(); String order = sCmd.next(); order.replace("_", "%20"); @@ -517,36 +571,40 @@ void httpOrderSend() { getURL(url); } -void update_firmware() { - upgrade = true; +void firmwareUpdate() { + upgrade = true; } -void firmware() { - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String page_number = sCmd.next(); - jsonWriteStr(configJson, "firm1", firmware_version); - choose_widget_and_create(widget_name, page_name, page_number, "any-data", "firm1"); +void firmwareVersion() { + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String page_number = sCmd.next(); + jsonWriteStr(configLiveJson, "firmver", firmware_version); + choose_widget_and_create(widget_name, page_name, page_number, "any-data", "firmver"); } //============================================================================================================================== //============================выполнение команд (в лупе) по очереди из строки order============================================= -void handleCMD_loop() { - if (order_loop != "") { - String tmp = selectToMarker(order_loop, ","); //выделяем из страки order первую команду rel 5 1, - sCmd.readStr(tmp); //выполняем первую команду +void handleCMD_loop() +{ + if (order_loop != "") + { + String tmp = selectToMarker(order_loop, ","); //выделяем из страки order первую команду rel 5 1, + sCmd.readStr(tmp); //выполняем первую команду Serial.println("[ORDER] => " + order_loop); - order_loop = deleteBeforeDelimiter(order_loop, ","); //осекаем выполненную команду + order_loop = deleteBeforeDelimiter(order_loop, ","); //осекаем выполненную команду } } -void txtExecution(String file) { +void txtExecution(String file) +{ String command_all = readFile(file, 2048) + "\r\n"; command_all.replace("\r\n", "\n"); command_all.replace("\r", "\n"); - while (command_all.length() != 0) { + while (command_all.length() != 0) + { String tmp = selectToMarker(command_all, "\n"); sCmd.readStr(tmp); command_all = deleteBeforeDelimiter(command_all, "\n"); @@ -554,13 +612,15 @@ void txtExecution(String file) { command_all = ""; } -void stringExecution(String str) { +void stringExecution(String str) +{ str = str + "\r\n"; str.replace("\r\n", "\n"); str.replace("\r", "\n"); - while (str.length()) { + while (str.length()) + { String tmp = selectToMarker(str, "\n"); sCmd.readStr(tmp); diff --git a/src/FileSystem.cpp b/src/FileSystem.cpp index 92eb6f31..82c2ca7a 100644 --- a/src/FileSystem.cpp +++ b/src/FileSystem.cpp @@ -6,28 +6,28 @@ void File_system_init() { Serial.println("--------------started----------------"); //-------------------------------------------------------------- SPIFFS.begin(); - configSetup = readFile("config.json", 4096); - configSetup.replace(" ", ""); - configSetup.replace("\r\n", ""); - Serial.println(configSetup); - jsonWriteStr(configJson, "name", jsonReadStr(configSetup, "name")); - jsonWriteStr(configJson, "lang", jsonReadStr(configSetup, "lang")); + configSetupJson = readFile("config.json", 4096); + configSetupJson.replace(" ", ""); + configSetupJson.replace("\r\n", ""); + Serial.println(configSetupJson); + jsonWriteStr(configLiveJson, "name", jsonReadStr(configSetupJson, "name")); + jsonWriteStr(configLiveJson, "lang", jsonReadStr(configSetupJson, "lang")); #ifdef ESP32 uint32_t chipID_u = ESP.getEfuseMac(); chipID = String(chipID_u); - jsonWriteStr(configSetup, "chipID", chipID); + jsonWriteStr(configSetupJson, "chipID", chipID); #endif #ifdef ESP8266 chipID = String(ESP.getChipId()) + "-" + String(ESP.getFlashChipId()); - jsonWriteStr(configSetup, "chipID", chipID); + jsonWriteStr(configSetupJson, "chipID", chipID); Serial.setDebugOutput(0); #endif - jsonWriteStr(configSetup, "firmware_version", firmware_version); + jsonWriteStr(configSetupJson, "firmware_version", firmware_version); - prex = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID; + prex = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipID; Serial.println(chipID); } diff --git a/src/Global.cpp b/src/Global.cpp index ff0f1245..a190e014 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -22,9 +22,9 @@ boolean just_load = true; const char *hostName = "IoT Manager"; // Json -String configSetup = "{}"; -String configJson = "{}"; -String optionJson = "{}"; +String configSetupJson = "{}"; +String configLiveJson = "{}"; +String configOptionJson = "{}"; // Mqtt String chipID = ""; diff --git a/src/Init.cpp b/src/Init.cpp index 2cac31c4..d0a45e8d 100644 --- a/src/Init.cpp +++ b/src/Init.cpp @@ -7,13 +7,13 @@ void All_init() { value = request->getParam("arg")->value(); } if (value == "0") { //выкл сценариев - jsonWriteStr(configSetup, "scenario", value); + jsonWriteStr(configSetupJson, "scenario", value); saveConfig(); Scenario_init(); request->send(200, "text/text", "OK"); } if (value == "1") { //вкл сценариев - jsonWriteStr(configSetup, "scenario", value); + jsonWriteStr(configSetupJson, "scenario", value); saveConfig(); Scenario_init(); request->send(200, "text/text", "OK"); @@ -51,7 +51,7 @@ void Device_init() { analog_value_names_list = ""; enter_to_analog_counter = 0; - level_value_name = ""; + levelPr_value_name = ""; dhtT_value_name = ""; dhtH_value_name = ""; @@ -85,7 +85,7 @@ void Device_init() { } void Scenario_init() { - if (jsonReadStr(configSetup, "scenario") == "1") { + if (jsonReadStr(configSetupJson, "scenario") == "1") { scenario = readFile("firmware.s.txt", 2048); } } @@ -188,19 +188,19 @@ void up_time() { if (ss != 0) { out = "[i] uptime = " + String(ss) + " sec"; - jsonWriteStr(configJson, "uptime", String(ss) + " sec"); + jsonWriteStr(configLiveJson, "uptime", String(ss) + " sec"); } if (mm != 0) { out = "[i] uptime = " + String(mm) + " min"; - jsonWriteStr(configJson, "uptime", String(mm) + " min"); + jsonWriteStr(configLiveJson, "uptime", String(mm) + " min"); } if (hh != 0) { out = "[i] uptime = " + String(hh) + " hours"; - jsonWriteStr(configJson, "uptime", String(hh) + " hours"); + jsonWriteStr(configLiveJson, "uptime", String(hh) + " hours"); } if (dd != 0) { out = "[i] uptime = " + String(dd) + " days"; - jsonWriteStr(configJson, "uptime", String(dd) + " days"); + jsonWriteStr(configLiveJson, "uptime", String(dd) + " days"); } Serial.println(out + ", mqtt_lost_error: " + String(mqtt_lost_error) + ", wifi_lost_error: " + String(wifi_lost_error)); } diff --git a/src/Logging.cpp b/src/Logging.cpp index 996786ce..ac8c9d83 100644 --- a/src/Logging.cpp +++ b/src/Logging.cpp @@ -17,7 +17,7 @@ void logging() { // считаем количество входов в эту функцию enter_to_logging_counter++; //создаем в файловой системе переменную количества точек на графике с отметкой _c что значит count - jsonWriteStr(optionJson, value_name + "_c", maxCount); + jsonWriteStr(configOptionJson, value_name + "_c", maxCount); //создаем график в приложении с топиком _ch /prefix/3234045-1589487/value_name_ch createChart(widget_name, page_name, page_number, "widgets/widget.chart.json", value_name + "_ch", maxCount); @@ -25,7 +25,7 @@ void logging() { ts.add( LOG1, period_min.toInt() * 1000 * 60, [&](void*) { String tmp_buf_1 = selectFromMarkerToMarker(logging_value_names_list, ",", 0); - deleteOldDate("log." + tmp_buf_1 + ".txt", jsonReadInt(optionJson, tmp_buf_1 + "_c"), jsonReadStr(configJson, tmp_buf_1)); + deleteOldDate("log." + tmp_buf_1 + ".txt", jsonReadInt(configOptionJson, tmp_buf_1 + "_c"), jsonReadStr(configLiveJson, tmp_buf_1)); Serial.println("[i] LOGGING for sensor '" + tmp_buf_1 + "' done"); }, nullptr, false); @@ -34,7 +34,7 @@ void logging() { ts.add( LOG2, period_min.toInt() * 1000 * 60, [&](void*) { String tmp_buf_2 = selectFromMarkerToMarker(logging_value_names_list, ",", 1); - deleteOldDate("log." + tmp_buf_2 + ".txt", jsonReadInt(optionJson, tmp_buf_2 + "_c"), jsonReadStr(configJson, tmp_buf_2)); + deleteOldDate("log." + tmp_buf_2 + ".txt", jsonReadInt(configOptionJson, tmp_buf_2 + "_c"), jsonReadStr(configLiveJson, tmp_buf_2)); Serial.println("[i] LOGGING for sensor '" + tmp_buf_2 + "' done"); }, nullptr, false); @@ -43,7 +43,7 @@ void logging() { ts.add( LOG3, period_min.toInt() * 1000 * 60, [&](void*) { String tmp_buf_3 = selectFromMarkerToMarker(logging_value_names_list, ",", 2); - deleteOldDate("log." + tmp_buf_3 + ".txt", jsonReadInt(optionJson, tmp_buf_3 + "_c"), jsonReadStr(configJson, tmp_buf_3)); + deleteOldDate("log." + tmp_buf_3 + ".txt", jsonReadInt(configOptionJson, tmp_buf_3 + "_c"), jsonReadStr(configLiveJson, tmp_buf_3)); Serial.println("[i] LOGGING for sensor '" + tmp_buf_3 + "' done"); }, nullptr, false); @@ -52,7 +52,7 @@ void logging() { ts.add( LOG4, period_min.toInt() * 1000 * 60, [&](void*) { String tmp_buf_4 = selectFromMarkerToMarker(logging_value_names_list, ",", 3); - deleteOldDate("log." + tmp_buf_4 + ".txt", jsonReadInt(optionJson, tmp_buf_4 + "_c"), jsonReadStr(configJson, tmp_buf_4)); + deleteOldDate("log." + tmp_buf_4 + ".txt", jsonReadInt(configOptionJson, tmp_buf_4 + "_c"), jsonReadStr(configLiveJson, tmp_buf_4)); Serial.println("[i] LOGGING for sensor '" + tmp_buf_4 + "' done"); }, nullptr, false); @@ -61,7 +61,7 @@ void logging() { ts.add( LOG5, period_min.toInt() * 1000 * 60, [&](void*) { String tmp_buf_5 = selectFromMarkerToMarker(logging_value_names_list, ",", 4); - deleteOldDate("log." + tmp_buf_5 + ".txt", jsonReadInt(optionJson, tmp_buf_5 + "_c"), jsonReadStr(configJson, tmp_buf_5)); + deleteOldDate("log." + tmp_buf_5 + ".txt", jsonReadInt(configOptionJson, tmp_buf_5 + "_c"), jsonReadStr(configLiveJson, tmp_buf_5)); Serial.println("[i] LOGGING for sensor '" + tmp_buf_5 + "' done"); }, nullptr, false); diff --git a/src/Mqtt.cpp b/src/Mqtt.cpp index feb78d41..7acbcf16 100644 --- a/src/Mqtt.cpp +++ b/src/Mqtt.cpp @@ -32,20 +32,20 @@ void MQTT_init() { server.on("/mqttSave", HTTP_GET, [](AsyncWebServerRequest* request) { if (request->hasArg("mqttServer")) { - jsonWriteStr(configSetup, "mqttServer", request->getParam("mqttServer")->value()); + jsonWriteStr(configSetupJson, "mqttServer", request->getParam("mqttServer")->value()); } if (request->hasArg("mqttPort")) { int port = (request->getParam("mqttPort")->value()).toInt(); - jsonWriteInt(configSetup, "mqttPort", port); + jsonWriteInt(configSetupJson, "mqttPort", port); } if (request->hasArg("mqttPrefix")) { - jsonWriteStr(configSetup, "mqttPrefix", request->getParam("mqttPrefix")->value()); + jsonWriteStr(configSetupJson, "mqttPrefix", request->getParam("mqttPrefix")->value()); } if (request->hasArg("mqttUser")) { - jsonWriteStr(configSetup, "mqttUser", request->getParam("mqttUser")->value()); + jsonWriteStr(configSetupJson, "mqttUser", request->getParam("mqttUser")->value()); } if (request->hasArg("mqttPass")) { - jsonWriteStr(configSetup, "mqttPass", request->getParam("mqttPass")->value()); + jsonWriteStr(configSetupJson, "mqttPass", request->getParam("mqttPass")->value()); } saveConfig(); mqtt_connection = true; @@ -79,21 +79,21 @@ void handleMQTT() { boolean MQTT_Connecting() { bool res = false; - String mqtt_server = jsonReadStr(configSetup, "mqttServer"); + String mqtt_server = jsonReadStr(configSetupJson, "mqttServer"); if ((mqtt_server != "")) { Serial.println("[E] Lost MQTT connection, start reconnecting"); led_blink("fast"); - client_mqtt.setServer(mqtt_server.c_str(), jsonReadInt(configSetup, "mqttPort")); + 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(configSetup, "mqttUser").c_str(), jsonReadStr(configSetup, "mqttPass").c_str())) { + if (client_mqtt.connect(chipID.c_str(), jsonReadStr(configSetupJson, "mqttUser").c_str(), jsonReadStr(configSetupJson, "mqttPass").c_str())) { Serial.println("[VV] MQTT connected"); led_blink("off"); client_mqtt.setCallback(callback); - client_mqtt.subscribe(jsonReadStr(configSetup, "mqttPrefix").c_str()); // Для приема получения HELLOW и подтверждения связи - client_mqtt.subscribe((jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/+/control").c_str()); // Подписываемся на топики control - client_mqtt.subscribe((jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/order").c_str()); // Подписываемся на топики order + 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 Serial.println("[V] Callback set, subscribe done"); res = true; } else { @@ -157,7 +157,7 @@ void outcoming_date() { } boolean sendMQTT(String end_of_topik, String data) { - String topik = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/" + end_of_topik; + 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(); @@ -165,7 +165,7 @@ boolean sendMQTT(String end_of_topik, String data) { } boolean sendCHART(String topik, String data) { - topik = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/" + topik + "/" + "status"; + 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(); @@ -173,14 +173,14 @@ boolean sendCHART(String topik, String data) { } void sendSTATUS(String topik, String state) { - topik = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/" + topik + "/" + "status"; + topik = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipID + "/" + topik + "/" + "status"; String json_ = "{}"; jsonWriteStr(json_, "status", state); client_mqtt.publish(topik.c_str(), json_.c_str(), false); } void sendCONTROL(String id, String topik, String state) { - String all_line = jsonReadStr(configSetup, "mqttPrefix") + "/" + id + "/" + topik + "/control"; + String all_line = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + id + "/" + topik + "/control"; client_mqtt.publish(all_line.c_str(), state.c_str(), false); } @@ -227,7 +227,7 @@ void sendAllWigets() { //=====================================================ОТПРАВЛЯЕМ ДАННЫЕ В ВИДЖЕТЫ ПРИ ОБНОВЛЕНИИ СТРАНИЦЫ======================================================== void sendAllData() { //берет строку json и ключи превращает в топики а значения колючей в них посылает - String current_config = configJson; //{"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"} + String current_config = configLiveJson; //{"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"} getMemoryLoad("[i] after send all date"); current_config.replace("{", ""); current_config.replace("}", ""); //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1" @@ -289,7 +289,7 @@ String stateMQTT() { /*void scenario_devices_topiks_subscribe() { //SCENARIO ANALOG > 5 800324-1458415 rel1 0 - if (jsonReadStr(configSetup, "scenario") == "1") { + if (jsonReadStr(configSetupJson, "scenario") == "1") { //String all_text = readFile("firmware.s.txt", 1024) + "\r\n"; String all_text = scenario + "\r\n"; all_text.replace("\r\n", "\n"); @@ -298,7 +298,7 @@ String stateMQTT() { String line_ = selectToMarker (all_text, "\n"); String id = selectFromMarkerToMarker(line_, " ", 4); if (id != "not found") { - client_mqtt.subscribe((jsonReadStr(configSetup, "mqttPrefix") + "/" + id + "/+/status").c_str(), 0); + client_mqtt.subscribe((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + id + "/+/status").c_str(), 0); Serial.println("subscribed to device, id: " + id); } all_text = deleteBeforeDelimiter(all_text, "\n"); @@ -308,7 +308,7 @@ String stateMQTT() { */ /*void scenario_devices_test_msg_send() { - if (jsonReadStr(configSetup, "scenario") == "1") { + if (jsonReadStr(configSetupJson, "scenario") == "1") { String all_text = scenario + "\r\n"; all_text.replace("\r\n", "\n"); @@ -318,7 +318,7 @@ String stateMQTT() { String id = selectFromMarkerToMarker(line_, " ", 4); if (id != "not found") { //Serial.println(); - Serial.println(client_mqtt.publish ((jsonReadStr(configSetup, "mqttPrefix") + "/" + id).c_str(), "CHECK", true)); + Serial.println(client_mqtt.publish ((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + id).c_str(), "CHECK", true)); } all_text = deleteBeforeDelimiter(all_text, "\n"); @@ -330,7 +330,7 @@ String stateMQTT() { //----------------------------------------------------------------------------------------------------------------------------------------------- //jsonWriteStr(tmp, "status", "1"); - String current_config = configJson; //{"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"} + String current_config = configLiveJson; //{"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"} current_config.replace("{", ""); current_config.replace("}", ""); //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1" current_config += ","; //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1", diff --git a/src/Scenario.cpp b/src/Scenario.cpp index 12294285..a653dd2b 100644 --- a/src/Scenario.cpp +++ b/src/Scenario.cpp @@ -1,8 +1,8 @@ #include "Global.h" void handleScenario() { - if (jsonReadStr(configSetup, "scenario") == "1") { - if ((jsonReadStr(optionJson, "scenario_status") != "")) { + if (jsonReadStr(configSetupJson, "scenario") == "1") { + if ((jsonReadStr(configOptionJson, "scenario_status") != "")) { int i = 0; String str = scenario; //читаем переменную с сценариями (то что из файла на странице) str += "\n"; @@ -18,7 +18,7 @@ void handleScenario() { //Serial.println(i); String condition = selectToMarker(tmp, "\n"); //выделяем первую строку самого сценария button1 = 1 (условие) String param_name = selectFromMarkerToMarker(condition, " ", 0); - String order = jsonReadStr(optionJson, "scenario_status"); //читаем весь файл событий + String order = jsonReadStr(configOptionJson, "scenario_status"); //читаем весь файл событий String param = selectToMarker(order, ","); //читаем первое событие из файла событий if (param_name == param) { //если поступившее событие равно событию заданному buttonSet1 в файле начинаем его обработку @@ -26,30 +26,30 @@ void handleScenario() { String value = selectFromMarkerToMarker(condition, " ", 2); //читаем значение (1) if (value.indexOf("digit") != -1) { // value = add_set(value); - value = jsonReadStr(configJson, value); + value = jsonReadStr(configLiveJson, value); } if (value.indexOf("time") != -1) { // value = add_set(value); - value = jsonReadStr(configJson, value); + value = jsonReadStr(configLiveJson, value); } boolean flag = false; //если одно из значений совпало то только тогда начинаем выполнять комнады if (sign == "=") { - if (jsonReadStr(configJson, param_name) == value) flag = true; + if (jsonReadStr(configLiveJson, param_name) == value) flag = true; } if (sign == "!=") { - if (jsonReadStr(configJson, param_name) != value) flag = true; + if (jsonReadStr(configLiveJson, param_name) != value) flag = true; } if (sign == "<") { - if (jsonReadStr(configJson, param_name).toInt() < value.toInt()) flag = true; + if (jsonReadStr(configLiveJson, param_name).toInt() < value.toInt()) flag = true; } if (sign == ">") { - if (jsonReadStr(configJson, param_name).toInt() > value.toInt()) flag = true; + if (jsonReadStr(configLiveJson, param_name).toInt() > value.toInt()) flag = true; } if (sign == ">=") { - if (jsonReadStr(configJson, param_name).toInt() >= value.toInt()) flag = true; + if (jsonReadStr(configLiveJson, param_name).toInt() >= value.toInt()) flag = true; } if (sign == "<=") { - if (jsonReadStr(configJson, param_name).toInt() <= value.toInt()) flag = true; + if (jsonReadStr(configLiveJson, param_name).toInt() <= value.toInt()) flag = true; } if (flag) { @@ -64,9 +64,9 @@ void handleScenario() { str = deleteBeforeDelimiter(str, "end\n"); //удаляем первый сценарий //----------------------------------------------------------------------------------------------------------------------- } - String tmp2 = jsonReadStr(optionJson, "scenario_status"); //читаем файл событий + String tmp2 = jsonReadStr(configOptionJson, "scenario_status"); //читаем файл событий tmp2 = deleteBeforeDelimiter(tmp2, ","); //удаляем выполненное событие - jsonWriteStr(optionJson, "scenario_status", tmp2); //записываем обновленный файл событий + jsonWriteStr(configOptionJson, "scenario_status", tmp2); //записываем обновленный файл событий i = 0; } } @@ -74,10 +74,10 @@ void handleScenario() { //событие выглядит как имя плюс set плюс номер: button+Set+1 void eventGen(String event_name, String number) { - if (jsonReadStr(configSetup, "scenario") == "1") { - String tmp = jsonReadStr(optionJson, "scenario_status"); //генерирование события + if (jsonReadStr(configSetupJson, "scenario") == "1") { + String tmp = jsonReadStr(configOptionJson, "scenario_status"); //генерирование события //Serial.println(event_name); - jsonWriteStr(optionJson, "scenario_status", tmp + event_name + number + ","); + jsonWriteStr(configOptionJson, "scenario_status", tmp + event_name + number + ","); } } diff --git a/src/Sensors.cpp b/src/Sensors.cpp index 256c956d..3a27aad4 100644 --- a/src/Sensors.cpp +++ b/src/Sensors.cpp @@ -69,54 +69,79 @@ void sensors_init() { //========================================================================================================================================= //=========================================Модуль измерения уровня в баке================================================================== #ifdef level_enable -//level L 14 12 Вода#в#баке,#% Датчики fill-gauge 125 20 1 -void level() { - String value_name = sCmd.next(); - String trig = sCmd.next(); - String echo = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String type = sCmd.next(); - String empty_level = sCmd.next(); - String full_level = sCmd.next(); - String page_number = sCmd.next(); - level_value_name = value_name; - jsonWriteStr(optionJson, "e_lev", empty_level); - jsonWriteStr(optionJson, "f_lev", full_level); - jsonWriteStr(optionJson, "trig", trig); - jsonWriteStr(optionJson, "echo", echo); - pinMode(trig.toInt(), OUTPUT); - pinMode(echo.toInt(), INPUT); - choose_widget_and_create(widget_name, page_name, page_number, type, value_name); - sensors_reading_map[0] = 1; +//levelPr p 14 12 Вода#в#баке,#% Датчики fill-gauge 125 20 1 +void levelPr() { + String value_name = sCmd.next(); + String trig = sCmd.next(); + String echo = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String type = sCmd.next(); + String empty_level = sCmd.next(); + String full_level = sCmd.next(); + String page_number = sCmd.next(); + levelPr_value_name = value_name; + jsonWriteStr(configOptionJson, "e_lev", empty_level); + jsonWriteStr(configOptionJson, "f_lev", full_level); + jsonWriteStr(configOptionJson, "trig", trig); + jsonWriteStr(configOptionJson, "echo", echo); + pinMode(trig.toInt(), OUTPUT); + pinMode(echo.toInt(), INPUT); + choose_widget_and_create(widget_name, page_name, page_number, type, value_name); + sensors_reading_map[0] = 1; +} +//ultrasonicCm cm 14 12 Дистанция,#см Датчики fill-gauge 1 +void ultrasonicCm() { + String value_name = sCmd.next(); + String trig = sCmd.next(); + String echo = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String type = sCmd.next(); + String empty_level = sCmd.next(); + String full_level = sCmd.next(); + String page_number = sCmd.next(); + ultrasonicCm_value_name = value_name; + jsonWriteStr(configOptionJson, "trig", trig); + jsonWriteStr(configOptionJson, "echo", echo); + pinMode(trig.toInt(), OUTPUT); + pinMode(echo.toInt(), INPUT); + choose_widget_and_create(widget_name, page_name, page_number, type, value_name); + sensors_reading_map[0] = 1; } -void level_reading() { - long duration_; - int distance_cm; - int level; - static int counter; - int trig = jsonReadInt(optionJson, "trig"); - int echo = jsonReadInt(optionJson, "echo"); - digitalWrite(trig, LOW); - delayMicroseconds(2); - digitalWrite(trig, HIGH); - delayMicroseconds(10); - digitalWrite(trig, LOW); - duration_ = pulseIn(echo, HIGH, 30000); // 3000 µs = 50cm // 30000 µs = 5 m - distance_cm = duration_ / 29 / 2; - distance_cm = medianFilter.filtered(distance_cm); //отсечение промахов медианным фильтром - counter++; - if (counter > tank_level_times_to_send) { - counter = 0; - level = map(distance_cm, - jsonReadInt(optionJson, "e_lev"), - jsonReadInt(optionJson, "f_lev"), 0, 100); - jsonWriteInt(configJson, level_value_name, level); - eventGen(level_value_name, ""); - sendSTATUS(level_value_name, String(level)); - Serial.println("[i] sensor '" + level_value_name + "' data: " + String(level)); - } +void ultrasonic_reading() { + long duration_; + int distance_cm; + int level; + static int counter; + int trig = jsonReadInt(configOptionJson, "trig"); + int echo = jsonReadInt(configOptionJson, "echo"); + digitalWrite(trig, LOW); + delayMicroseconds(2); + digitalWrite(trig, HIGH); + delayMicroseconds(10); + digitalWrite(trig, LOW); + duration_ = pulseIn(echo, HIGH, 30000); // 3000 µs = 50cm // 30000 µs = 5 m + distance_cm = duration_ / 29 / 2; + distance_cm = medianFilter.filtered(distance_cm);//отсечение промахов медианным фильтром + counter++; + if (counter > tank_level_times_to_send) { + counter = 0; + level = map(distance_cm, + jsonReadInt(configOptionJson, "e_lev"), + jsonReadInt(configOptionJson, "f_lev"), 0, 100); + + jsonWriteInt(configLiveJson, levelPr_value_name, level); + eventGen (levelPr_value_name, ""); + sendSTATUS(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, ""); + sendSTATUS(ultrasonicCm_value_name, String(distance_cm)); + Serial.println("[i] sensor '" + ultrasonicCm_value_name + "' data: " + String(distance_cm)); + } } #endif //========================================================================================================================================= @@ -136,10 +161,10 @@ void analog() { String page_number = sCmd.next(); analog_value_names_list += value_name + ","; enter_to_analog_counter++; - jsonWriteStr(optionJson, value_name + "_st", analog_start); - jsonWriteStr(optionJson, value_name + "_end", analog_end); - jsonWriteStr(optionJson, value_name + "_st_out", analog_start_out); - jsonWriteStr(optionJson, value_name + "_end_out", analog_end_out); + jsonWriteStr(configOptionJson, value_name + "_st", analog_start); + jsonWriteStr(configOptionJson, value_name + "_end", analog_end); + jsonWriteStr(configOptionJson, value_name + "_st_out", analog_start_out); + jsonWriteStr(configOptionJson, value_name + "_end_out", analog_end_out); choose_widget_and_create(widget_name, page_name, page_number, type, value_name); if (enter_to_analog_counter == 1) { sensors_reading_map[1] = 1; @@ -158,11 +183,11 @@ void analog_reading1() { int analog_in = analogRead(A0); #endif int analog = map(analog_in, - jsonReadInt(optionJson, value_name + "_st"), - jsonReadInt(optionJson, value_name + "_end"), - jsonReadInt(optionJson, value_name + "_st_out"), - jsonReadInt(optionJson, value_name + "_end_out")); - jsonWriteInt(configJson, value_name, analog); + jsonReadInt(configOptionJson, value_name + "_st"), + jsonReadInt(configOptionJson, value_name + "_end"), + jsonReadInt(configOptionJson, value_name + "_st_out"), + jsonReadInt(configOptionJson, value_name + "_end_out")); + jsonWriteInt(configLiveJson, value_name, analog); eventGen(value_name, ""); sendSTATUS(value_name, String(analog)); Serial.println("[i] sensor '" + value_name + "' data: " + String(analog)); @@ -177,11 +202,11 @@ void analog_reading2() { int analog_in = analogRead(A0); #endif int analog = map(analog_in, - jsonReadInt(optionJson, value_name + "_st"), - jsonReadInt(optionJson, value_name + "_end"), - jsonReadInt(optionJson, value_name + "_st_out"), - jsonReadInt(optionJson, value_name + "_end_out")); - jsonWriteInt(configJson, value_name, analog); + jsonReadInt(configOptionJson, value_name + "_st"), + jsonReadInt(configOptionJson, value_name + "_end"), + jsonReadInt(configOptionJson, value_name + "_st_out"), + jsonReadInt(configOptionJson, value_name + "_end_out")); + jsonWriteInt(configLiveJson, value_name, analog); eventGen(value_name, ""); sendSTATUS(value_name, String(analog)); Serial.println("[i] sensor '" + value_name + "' data: " + String(analog)); @@ -210,7 +235,7 @@ void dallas_reading() { float temp = 0; sensors.requestTemperatures(); temp = sensors.getTempCByIndex(0); - jsonWriteStr(configJson, "dallas", String(temp)); + jsonWriteStr(configLiveJson, "dallas", String(temp)); eventGen("dallas", ""); sendSTATUS("dallas", String(temp)); Serial.println("[i] sensor 'dallas' send date " + String(temp)); @@ -250,7 +275,7 @@ void dhtT_reading() { value = dht.getTemperature(); if (String(value) != "nan") { eventGen(dhtT_value_name, ""); - jsonWriteStr(configJson, dhtT_value_name, String(value)); + jsonWriteStr(configLiveJson, dhtT_value_name, String(value)); sendSTATUS(dhtT_value_name, String(value)); Serial.println("[i] sensor '" + dhtT_value_name + "' data: " + String(value)); } @@ -288,7 +313,7 @@ void dhtH_reading() { value = dht.getHumidity(); if (String(value) != "nan") { eventGen(dhtH_value_name, ""); - jsonWriteStr(configJson, dhtH_value_name, String(value)); + jsonWriteStr(configLiveJson, dhtH_value_name, String(value)); sendSTATUS(dhtH_value_name, String(value)); Serial.println("[i] sensor '" + dhtH_value_name + "' data: " + String(value)); } @@ -309,9 +334,9 @@ void dhtP_reading() { if (dht.getStatus() != 0) { sendSTATUS("dhtPerception", String(dht.getStatusString())); } else { - value = dht.computePerception(jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); + value = dht.computePerception(jsonReadStr(configLiveJson, dhtT_value_name).toFloat(), jsonReadStr(configLiveJson, dhtH_value_name).toFloat(), false); String final_line = perception(value); - jsonWriteStr(configJson, "dhtPerception", final_line); + jsonWriteStr(configLiveJson, "dhtPerception", final_line); eventGen("dhtPerception", ""); sendSTATUS("dhtPerception", final_line); if (client_mqtt.connected()) { @@ -368,9 +393,9 @@ void dhtC_reading() { if (dht.getStatus() != 0) { sendSTATUS("dhtComfort", String(dht.getStatusString())); } else { - value = dht.getComfortRatio(cf, jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); + value = dht.getComfortRatio(cf, jsonReadStr(configLiveJson, dhtT_value_name).toFloat(), jsonReadStr(configLiveJson, dhtH_value_name).toFloat(), false); String final_line = get_comfort_status(cf); - jsonWriteStr(configJson, "dhtComfort", final_line); + jsonWriteStr(configLiveJson, "dhtComfort", final_line); eventGen("dhtComfort", ""); sendSTATUS("dhtComfort", final_line); Serial.println("[i] sensor 'dhtComfort' send date " + final_line); @@ -428,8 +453,8 @@ void dhtD_reading() { if (dht.getStatus() != 0) { sendSTATUS("dhtDewpoint", String(dht.getStatusString())); } else { - value = dht.computeDewPoint(jsonReadStr(configJson, dhtT_value_name).toFloat(), jsonReadStr(configJson, dhtH_value_name).toFloat(), false); - jsonWriteInt(configJson, "dhtDewpoint", value); + value = dht.computeDewPoint(jsonReadStr(configLiveJson, dhtT_value_name).toFloat(), jsonReadStr(configLiveJson, dhtH_value_name).toFloat(), false); + jsonWriteInt(configLiveJson, "dhtDewpoint", value); eventGen("dhtDewpoint", ""); sendSTATUS("dhtDewpoint", String(value)); Serial.println("[i] sensor 'dhtDewpoint' data: " + String(value)); @@ -465,7 +490,7 @@ void bmp280T_reading() { sensors_event_t temp_event, pressure_event; bmp_temp->getEvent(&temp_event); value = temp_event.temperature; - jsonWriteStr(configJson, bmp280T_value_name, String(value)); + jsonWriteStr(configLiveJson, bmp280T_value_name, String(value)); eventGen(bmp280T_value_name, ""); sendSTATUS(bmp280T_value_name, String(value)); Serial.println("[i] sensor '" + bmp280T_value_name + "' data: " + String(value)); @@ -497,7 +522,7 @@ void bmp280P_reading() { bmp_pressure->getEvent(&pressure_event); value = pressure_event.pressure; value = value / 1.333224; - jsonWriteStr(configJson, bmp280P_value_name, String(value)); + jsonWriteStr(configLiveJson, bmp280P_value_name, String(value)); eventGen(bmp280P_value_name, ""); sendSTATUS(bmp280P_value_name, String(value)); Serial.println("[i] sensor '" + bmp280P_value_name + "' data: " + String(value)); @@ -522,7 +547,7 @@ void bme280T() { void bme280T_reading() { float value = 0; value = bme.readTemperature(); - jsonWriteStr(configJson, bme280T_value_name, String(value)); + jsonWriteStr(configLiveJson, bme280T_value_name, String(value)); eventGen(bme280T_value_name, ""); sendSTATUS(bme280T_value_name, String(value)); Serial.println("[i] sensor '" + bme280T_value_name + "' data: " + String(value)); @@ -546,7 +571,7 @@ void bme280P_reading() { float value = 0; value = bme.readPressure(); value = value / 1.333224; - jsonWriteStr(configJson, bme280P_value_name, String(value)); + jsonWriteStr(configLiveJson, bme280P_value_name, String(value)); eventGen(bme280P_value_name, ""); sendSTATUS(bme280P_value_name, String(value)); Serial.println("[i] sensor '" + bme280P_value_name + "' data: " + String(value)); @@ -569,7 +594,7 @@ void bme280H() { void bme280H_reading() { float value = 0; value = bme.readHumidity(); - jsonWriteStr(configJson, bme280H_value_name, String(value)); + jsonWriteStr(configLiveJson, bme280H_value_name, String(value)); eventGen(bme280H_value_name, ""); sendSTATUS(bme280H_value_name, String(value)); Serial.println("[i] sensor '" + bme280H_value_name + "' data: " + String(value)); @@ -592,7 +617,7 @@ void bme280A() { void bme280A_reading() { float value = 0; value = bme.readAltitude(1013.25); - jsonWriteStr(configJson, bme280A_value_name, String(value)); + jsonWriteStr(configLiveJson, bme280A_value_name, String(value)); eventGen(bme280A_value_name, ""); sendSTATUS(bme280A_value_name, String(value)); Serial.println("[i] sensor '" + bme280A_value_name + "' data: " + String(value)); diff --git a/src/TimeUtils.cpp b/src/TimeUtils.cpp index 4f7036d0..b7cda1cc 100644 --- a/src/TimeUtils.cpp +++ b/src/TimeUtils.cpp @@ -3,10 +3,10 @@ void Time_Init() { server.on("/time", HTTP_GET, [](AsyncWebServerRequest* request) { if (request->hasArg("timezone")) { - jsonWriteStr(configSetup, "timezone", request->getParam("timezone")->value()); + jsonWriteStr(configSetupJson, "timezone", request->getParam("timezone")->value()); } if (request->hasArg("ntp")) { - jsonWriteStr(configSetup, "ntp", request->getParam("ntp")->value()); + jsonWriteStr(configSetupJson, "ntp", request->getParam("ntp")->value()); } saveConfig(); reconfigTime(); @@ -29,7 +29,7 @@ void time_check() { void reconfigTime() { if (WiFi.status() == WL_CONNECTED) { - String ntp = jsonReadStr(configSetup, "ntp"); + String ntp = jsonReadStr(configSetupJson, "ntp"); configTime(0, 0, ntp.c_str()); int i = 0; Serial.println("[i] Awaiting for time "); @@ -74,7 +74,7 @@ String GetTimeUnix() { // Получение текущего времени String GetTime() { time_t now = time(nullptr); // получаем время с помощью библиотеки time.h - int zone = 3600 * jsonReadStr(configSetup, "timezone").toInt(); + int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); now = now + zone; String Time = ""; // Строка для результатов времени Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 @@ -85,7 +85,7 @@ String GetTime() { String GetTimeWOsec() { time_t now = time(nullptr); // получаем время с помощью библиотеки time.h - int zone = 3600 * jsonReadStr(configSetup, "timezone").toInt(); + int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); now = now + zone; String Time = ""; // Строка для результатов времени Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 @@ -97,7 +97,7 @@ String GetTimeWOsec() { // Получение даты String GetDate() { time_t now = time(nullptr); // получаем время с помощью библиотеки time.h - int zone = 3600 * jsonReadStr(configSetup, "timezone").toInt(); + int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); now = now + zone; String Data = ""; // Строка для результатов времени Data += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 diff --git a/src/Timers.cpp b/src/Timers.cpp index 6c249891..73dfe5e9 100644 --- a/src/Timers.cpp +++ b/src/Timers.cpp @@ -3,7 +3,7 @@ void Timer_countdown_init() { ts.add( TIMER_COUNTDOWN, 1000, [&](void*) { - String old_line = jsonReadStr(optionJson, "timers"); + String old_line = jsonReadStr(configOptionJson, "timers"); if (old_line != "") { //Serial.println(old_line); int i = 0; @@ -16,7 +16,7 @@ void Timer_countdown_init() { int time = readTimer(number); if (time == 0) { delTimer(String(number)); - jsonWriteStr(configJson, "timer" + String(number), "0"); + jsonWriteStr(configLiveJson, "timer" + String(number), "0"); eventGen("timer", String(number)); } else { time--; @@ -34,17 +34,17 @@ void timerStart_() { String period_of_time = sCmd.next(); String type = sCmd.next(); if (period_of_time.indexOf("digit") != -1) { - period_of_time = jsonReadStr(configJson, period_of_time); + period_of_time = jsonReadStr(configLiveJson, period_of_time); } if (type == "sec") period_of_time = period_of_time; if (type == "min") period_of_time = String(period_of_time.toInt() * 60); if (type == "hours") period_of_time = String(period_of_time.toInt() * 60 * 60); addTimer(number, period_of_time); - jsonWriteStr(configJson, "timer" + number, "1"); + jsonWriteStr(configLiveJson, "timer" + number, "1"); } void addTimer(String number, String time) { - String tmp = jsonReadStr(optionJson, "timers"); //1:60,2:120, + String tmp = jsonReadStr(configOptionJson, "timers"); //1:60,2:120, String new_timer = number + ":" + time; int psn1 = tmp.indexOf(number + ":"); //0 ищем позицию таймера который надо заменить if (psn1 != -1) { //если он есть @@ -56,7 +56,7 @@ void addTimer(String number, String time) { } else { //если его нет tmp += new_timer + ","; } - jsonWriteStr(optionJson, "timers", tmp); + jsonWriteStr(configOptionJson, "timers", tmp); //Serial.println("ura"); } @@ -66,18 +66,18 @@ void timerStop_() { } void delTimer(String number) { - String tmp = jsonReadStr(optionJson, "timers"); //1:60,2:120, + String tmp = jsonReadStr(configOptionJson, "timers"); //1:60,2:120, int psn1 = tmp.indexOf(number + ":"); //0 ищем позицию таймера который надо удалить if (psn1 != -1) { //если он есть int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой String timer = tmp.substring(psn1, psn2) + ","; //1:60, выделяем таймер который надо удалить tmp.replace(timer, ""); //удаляем таймер - jsonWriteStr(optionJson, "timers", tmp); + jsonWriteStr(configOptionJson, "timers", tmp); } } int readTimer(int number) { - String tmp = jsonReadStr(optionJson, "timers"); //1:60,2:120, + String tmp = jsonReadStr(configOptionJson, "timers"); //1:60,2:120, int psn1 = tmp.indexOf(String(number) + ":"); //0 ищем позицию таймера который надо прочитать String timer; if (psn1 != -1) { //если он есть diff --git a/src/Upgrade.cpp b/src/Upgrade.cpp index 726a8414..e8982117 100644 --- a/src/Upgrade.cpp +++ b/src/Upgrade.cpp @@ -24,7 +24,7 @@ const String getFirmwareUrl() { void initUpgrade() { String last_version = WiFi.status() == WL_CONNECTED ? getURL(getVersionUrl()) : ""; - jsonWriteStr(configSetup, "last_version", last_version); + jsonWriteStr(configSetupJson, "last_version", last_version); Serial.printf("[i] Last firmware version: %s\n", last_version.c_str()); @@ -73,17 +73,17 @@ void do_upgrade_url() { if (upgrade_url) { upgrade_url = false; last_version = getURL(getVersionUrl()); - jsonWriteStr(configSetup, "last_version", last_version); + jsonWriteStr(configSetupJson, "last_version", last_version); } } void upgrade_firmware() { String scenario_for_update; String config_for_update; - String configSetup_for_update; + String configSetupJson_for_update; scenario_for_update = readFile("firmware.s.txt", 4000); config_for_update = readFile("firmware.c.txt", 4000); - configSetup_for_update = configSetup; + configSetupJson_for_update = configSetupJson; Serial.println("Start upgrade SPIFFS, please wait..."); @@ -95,7 +95,7 @@ void upgrade_firmware() { if (ret == HTTP_UPDATE_OK) { writeFile("firmware.s.txt", scenario_for_update); writeFile("firmware.c.txt", config_for_update); - writeFile("config.json", configSetup_for_update); + writeFile("config.json", configSetupJson_for_update); saveConfig(); Serial.println("SPIFFS upgrade done!"); @@ -157,16 +157,16 @@ void do_upgrade() { if (spiffsData != "") { // Если нужно прошить FS String scenario_for_update; String config_for_update; - String configSetup_for_update; + String configSetupJson_for_update; Serial.println(spiffsData); scenario_for_update = readFile("firmware.s.txt", 2048); config_for_update = readFile("config.all.txt", 2048); - configSetup_for_update = configSetup; + configSetupJson_for_update = configSetupJson; ESPhttpUpdate.rebootOnUpdate(false); // Отключим перезагрузку после обновления updateHTTP(spiffsData, true); writeFile("firmware.s.txt", scenario_for_update); writeFile("config.all.txt", config_for_update); - writeFile("config.json", configSetup_for_update); + writeFile("config.json", configSetupJson_for_update); saveConfig(); } diff --git a/src/Web_server.cpp b/src/Web_server.cpp index 3bb2070e..a2f8f602 100644 --- a/src/Web_server.cpp +++ b/src/Web_server.cpp @@ -50,9 +50,9 @@ void Web_server_init() { #endif #ifdef ESP32 - server.addHandler(new SPIFFSEditor(SPIFFS, jsonReadStr(configSetup, "web_login").c_str(), jsonReadStr(configSetup, "web_pass").c_str())); + server.addHandler(new SPIFFSEditor(SPIFFS, jsonReadStr(configSetupJson, "web_login").c_str(), jsonReadStr(configSetupJson, "web_pass").c_str())); #elif defined(ESP8266) - server.addHandler(new SPIFFSEditor(jsonReadStr(configSetup, "web_login").c_str(), jsonReadStr(configSetup, "web_pass").c_str())); + server.addHandler(new SPIFFSEditor(jsonReadStr(configSetupJson, "web_login").c_str(), jsonReadStr(configSetupJson, "web_pass").c_str())); #endif /* server.on("/heap", HTTP_GET, [](AsyncWebServerRequest * request) { @@ -63,7 +63,7 @@ void Web_server_init() { server.serveStatic("/js/", SPIFFS, "/js/").setCacheControl("max-age=31536000"); server.serveStatic("/favicon.ico", SPIFFS, "/favicon.ico").setCacheControl("max-age=31536000"); - server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm").setAuthentication(jsonReadStr(configSetup, "web_login").c_str(), jsonReadStr(configSetup, "web_pass").c_str()); + server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm").setAuthentication(jsonReadStr(configSetupJson, "web_login").c_str(), jsonReadStr(configSetupJson, "web_pass").c_str()); server.onNotFound([](AsyncWebServerRequest *request) { Serial.printf("NOT_FOUND: "); @@ -130,17 +130,17 @@ void Web_server_init() { server.begin(); - // --------------------Выдаем данные configJson //config.live.json - динамические данные + // --------------------Выдаем данные configLiveJson //config.live.json - динамические данные server.on("/config.live.json", HTTP_GET, [](AsyncWebServerRequest *request) { - request->send(200, "application/json", configJson); + request->send(200, "application/json", configLiveJson); }); - // --------------------Выдаем данные optionJson //config.option.json - данные не являющиеся событиями + // --------------------Выдаем данные configOptionJson //config.option.json - данные не являющиеся событиями server.on("/config.option.json", HTTP_GET, [](AsyncWebServerRequest *request) { - request->send(200, "application/json", optionJson); + request->send(200, "application/json", configOptionJson); }); - // -------------------Выдаем данные configSetup //config.setup.json - для хранения постоянных данных + // -------------------Выдаем данные configSetupJson //config.setup.json - для хранения постоянных данных server.on("/config.setup.json", HTTP_GET, [](AsyncWebServerRequest *request) { - request->send(200, "application/json", configSetup); + request->send(200, "application/json", configSetupJson); }); // ------------------Выполнение команды из запроса diff --git a/src/WiFiUtils.cpp b/src/WiFiUtils.cpp index ffb7b783..18b55510 100644 --- a/src/WiFiUtils.cpp +++ b/src/WiFiUtils.cpp @@ -8,11 +8,11 @@ void WIFI_init() server.on("/ssid", HTTP_GET, [](AsyncWebServerRequest *request) { if (request->hasArg("ssid")) { - jsonWriteStr(configSetup, "ssid", request->getParam("ssid")->value()); + jsonWriteStr(configSetupJson, "ssid", request->getParam("ssid")->value()); } if (request->hasArg("password")) { - jsonWriteStr(configSetup, "password", request->getParam("password")->value()); + jsonWriteStr(configSetupJson, "password", request->getParam("password")->value()); } saveConfig(); // Функция сохранения данных во Flash request->send(200, "text/text", "OK"); // отправляем ответ о выполнении @@ -21,11 +21,11 @@ void WIFI_init() server.on("/ssidap", HTTP_GET, [](AsyncWebServerRequest *request) { if (request->hasArg("ssidAP")) { - jsonWriteStr(configSetup, "ssidAP", request->getParam("ssidAP")->value()); + jsonWriteStr(configSetupJson, "ssidAP", request->getParam("ssidAP")->value()); } if (request->hasArg("passwordAP")) { - jsonWriteStr(configSetup, "passwordAP", request->getParam("passwordAP")->value()); + jsonWriteStr(configSetupJson, "passwordAP", request->getParam("passwordAP")->value()); } saveConfig(); // Функция сохранения данных во Flash request->send(200, "text/text", "OK"); // отправляем ответ о выполнении @@ -35,11 +35,11 @@ void WIFI_init() server.on("/web", HTTP_GET, [](AsyncWebServerRequest *request) { if (request->hasArg("web_login")) { - jsonWriteStr(configSetup, "web_login", request->getParam("web_login")->value()); + jsonWriteStr(configSetupJson, "web_login", request->getParam("web_login")->value()); } if (request->hasArg("web_pass")) { - jsonWriteStr(configSetup, "web_pass", request->getParam("web_pass")->value()); + jsonWriteStr(configSetupJson, "web_pass", request->getParam("web_pass")->value()); } saveConfig(); // Функция сохранения данных во Flash //Web_server_init(); @@ -64,8 +64,8 @@ void ROUTER_Connecting() WiFi.mode(WIFI_STA); byte tries = 20; - String _ssid = jsonReadStr(configSetup, "ssid"); - String _password = jsonReadStr(configSetup, "password"); + String _ssid = jsonReadStr(configSetupJson, "ssid"); + String _password = jsonReadStr(configSetupJson, "password"); //WiFi.persistent(false); if (_ssid == "" && _password == "") @@ -86,7 +86,7 @@ void ROUTER_Connecting() { Serial.println("[E] password is not correct"); tries = 1; - jsonWriteInt(optionJson, "pass_status", 1); + jsonWriteInt(configOptionJson, "pass_status", 1); } Serial.print("."); delay(1000); @@ -104,7 +104,7 @@ void ROUTER_Connecting() Serial.print(WiFi.localIP()); Serial.println(); - jsonWriteStr(configJson, "ip", WiFi.localIP().toString()); + jsonWriteStr(configLiveJson, "ip", WiFi.localIP().toString()); led_blink("off"); } } @@ -116,21 +116,21 @@ bool StartAPMode() WiFi.mode(WIFI_AP); - String _ssidAP = jsonReadStr(configSetup, "ssidAP"); - String _passwordAP = jsonReadStr(configSetup, "passwordAP"); + String _ssidAP = jsonReadStr(configSetupJson, "ssidAP"); + String _passwordAP = jsonReadStr(configSetupJson, "passwordAP"); WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str()); IPAddress myIP = WiFi.softAPIP(); led_blink("on"); Serial.print("AP IP address: "); Serial.println(myIP); - jsonWriteStr(configJson, "ip", myIP.toString()); + jsonWriteStr(configLiveJson, "ip", myIP.toString()); - if (jsonReadInt(optionJson, "pass_status") != 1) + if (jsonReadInt(configOptionJson, "pass_status") != 1) { ts.add( ROUTER_SEARCHING, 10 * 1000, [&](void *) { Serial.println("->try find router"); - if (RouterFind(jsonReadStr(configSetup, "ssid"))) + if (RouterFind(jsonReadStr(configSetupJson, "ssid"))) { ts.remove(ROUTER_SEARCHING); WiFi.scanDelete(); diff --git a/src/i2c_bus.cpp b/src/i2c_bus.cpp index b48335c6..abf28a9a 100644 --- a/src/i2c_bus.cpp +++ b/src/i2c_bus.cpp @@ -7,10 +7,10 @@ void do_i2c_scanning() { if (tmp == "error") { tmp = i2c_scan(); Serial.println(tmp); - jsonWriteStr(configJson, "i2c", tmp); + jsonWriteStr(configLiveJson, "i2c", tmp); } else { Serial.println(tmp); - jsonWriteStr(configJson, "i2c", tmp); + jsonWriteStr(configLiveJson, "i2c", tmp); } } } diff --git a/src/main.cpp b/src/main.cpp index 60f78de6..a66ac527 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ #include "Global.h" void saveConfig() { - writeFile("config.json", configSetup); + writeFile("config.json", configSetupJson); } //--------------------Посчитать ----------------------------------------------------------------------------------- @@ -49,7 +49,7 @@ void safeDataToFile(String data, String Folder) { fileName = Folder + "/" + fileName + ".txt"; // addFile(fileName, GetTime() + "/" + data); Serial.println(fileName); - jsonWriteStr(configJson, "test", fileName); + jsonWriteStr(configLiveJson, "test", fileName); } // ------------- Чтение файла в строку ------------------------------------------------------------------------------- @@ -113,7 +113,7 @@ String readFileString(const String& filename, const String& str_to_found) { void sendCONFIG(String topik, String widgetConfig, String key, String date) { yield(); - topik = jsonReadStr(configSetup, "mqttPrefix") + "/" + chipID + "/" + topik + "/status"; + topik = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipID + "/" + topik + "/status"; String outer = "{\"widgetConfig\":"; String inner = "{\""; inner = inner + key; diff --git a/src/udp.cpp b/src/udp.cpp index 0ede7729..5832fe22 100644 --- a/src/udp.cpp +++ b/src/udp.cpp @@ -11,11 +11,11 @@ void UDP_init() { value = request->getParam("arg")->value(); } if (value == "0") { - jsonWriteStr(configSetup, "udponoff", value); + jsonWriteStr(configSetupJson, "udponoff", value); request->send(200, "text/text", "ok"); } if (value == "1") { - jsonWriteStr(configSetup, "udponoff", value); + jsonWriteStr(configSetupJson, "udponoff", value); request->send(200, "text/text", "ok"); } if (value == "2") { @@ -33,8 +33,8 @@ void UDP_init() { }); server.on("/name", HTTP_GET, [](AsyncWebServerRequest * request) { if (request->hasArg("arg")) { - jsonWriteStr(configSetup, "name", request->getParam("arg")->value()); - jsonWriteStr(configJson, "name", request->getParam("arg")->value()); + jsonWriteStr(configSetupJson, "name", request->getParam("arg")->value()); + jsonWriteStr(configLiveJson, "name", request->getParam("arg")->value()); saveConfig(); } request->send(200, "text/text", "OK"); @@ -53,10 +53,10 @@ void UDP_init() { udp_period = random(50000, 60000); ts.add(UDP, udp_period, [&](void*) { - if (jsonReadStr(configSetup, "udponoff") == "1") { + if (jsonReadStr(configSetupJson, "udponoff") == "1") { if (WiFi.status() == WL_CONNECTED) { if (!udp_busy) { - String line_to_send = "iotm;" + chipID + ";" + jsonReadStr(configSetup, "name"); + String line_to_send = "iotm;" + chipID + ";" + jsonReadStr(configSetupJson, "name"); #ifdef ESP8266 Udp.beginPacketMulticast(udp_multicastIP, udp_port, WiFi.localIP()); Udp.write(line_to_send.c_str()); @@ -74,7 +74,7 @@ void UDP_init() { void handleUdp() { #ifdef ESP8266 - if (jsonReadStr(configSetup, "udponoff") == "1") { + if (jsonReadStr(configSetupJson, "udponoff") == "1") { if (WiFi.status() == WL_CONNECTED) { int packetSize = Udp.parsePacket(); if (packetSize) { @@ -105,7 +105,7 @@ void handleUdp_esp32() { udp.onPacket([](AsyncUDPPacket packet) { received_udp_line = (char*)packet.data(); received_ip = packet.remoteIP().toString(); - if (jsonReadStr(configSetup, "udponoff") == "1") { + if (jsonReadStr(configSetupJson, "udponoff") == "1") { if (received_udp_line.indexOf("iotm;") >= 0) { udp_data_parse = true; @@ -127,11 +127,11 @@ void do_udp_data_parse() { Serial.print(" "); Serial.println(received_udp_line); if (received_udp_line.indexOf("mqttServer") >= 0) { - jsonWriteStr(configSetup, "mqttServer", jsonReadStr(received_udp_line, "mqttServer")); - jsonWriteInt(configSetup, "mqttPort", jsonReadInt(received_udp_line, "mqttPort")); - jsonWriteStr(configSetup, "mqttPrefix", jsonReadStr(received_udp_line, "mqttPrefix")); - jsonWriteStr(configSetup, "mqttUser", jsonReadStr(received_udp_line, "mqttUser")); - jsonWriteStr(configSetup, "mqttPass", jsonReadStr(received_udp_line, "mqttPass")); + jsonWriteStr(configSetupJson, "mqttServer", jsonReadStr(received_udp_line, "mqttServer")); + jsonWriteInt(configSetupJson, "mqttPort", jsonReadInt(received_udp_line, "mqttPort")); + jsonWriteStr(configSetupJson, "mqttPrefix", jsonReadStr(received_udp_line, "mqttPrefix")); + jsonWriteStr(configSetupJson, "mqttUser", jsonReadStr(received_udp_line, "mqttUser")); + jsonWriteStr(configSetupJson, "mqttPass", jsonReadStr(received_udp_line, "mqttPass")); saveConfig(); Serial.println("[V] new mqtt setting received from udp and saved"); mqtt_connection = true; @@ -150,15 +150,15 @@ void add_dev_in_list(String fileName, String id, String dev_name, String ip) { } void send_mqtt_to_udp() { - if (jsonReadStr(configSetup, "udponoff") == "1") { + if (jsonReadStr(configSetupJson, "udponoff") == "1") { if (WiFi.status() == WL_CONNECTED) { udp_busy = true; String mqtt_data = "{}"; - jsonWriteStr(mqtt_data, "mqttServer", jsonReadStr(configSetup, "mqttServer")); - jsonWriteInt(mqtt_data, "mqttPort", jsonReadInt(configSetup, "mqttPort")); - jsonWriteStr(mqtt_data, "mqttPrefix", jsonReadStr(configSetup, "mqttPrefix")); - jsonWriteStr(mqtt_data, "mqttUser", jsonReadStr(configSetup, "mqttUser")); - jsonWriteStr(mqtt_data, "mqttPass", jsonReadStr(configSetup, "mqttPass")); + jsonWriteStr(mqtt_data, "mqttServer", jsonReadStr(configSetupJson, "mqttServer")); + jsonWriteInt(mqtt_data, "mqttPort", jsonReadInt(configSetupJson, "mqttPort")); + jsonWriteStr(mqtt_data, "mqttPrefix", jsonReadStr(configSetupJson, "mqttPrefix")); + jsonWriteStr(mqtt_data, "mqttUser", jsonReadStr(configSetupJson, "mqttUser")); + jsonWriteStr(mqtt_data, "mqttPass", jsonReadStr(configSetupJson, "mqttPass")); Serial.println(mqtt_data); #ifdef ESP8266 Udp.beginPacketMulticast(udp_multicastIP, udp_port, WiFi.localIP()); From 446809355b7285abe4831f1ccd0964af3616a845 Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Fri, 19 Jun 2020 15:22:22 +0200 Subject: [PATCH 11/17] changed --- include/Global.h | 2 +- src/Global.cpp | 3 ++- src/Sensors.cpp | 7 +++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/Global.h b/include/Global.h index 19c43cfa..331d95cd 100644 --- a/include/Global.h +++ b/include/Global.h @@ -298,7 +298,7 @@ extern void sensors_init(); extern void levelPr(); extern void ultrasonicCm(); -extern void level_reading(); +extern void ultrasonic_reading(); extern void analog(); diff --git a/src/Global.cpp b/src/Global.cpp index a190e014..337258c6 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -37,7 +37,8 @@ String order_loop; String analog_value_names_list; int enter_to_analog_counter; -String level_value_name; +String levelPr_value_name; +String ultrasonicCm_value_name; String dhtT_value_name; String dhtH_value_name; diff --git a/src/Sensors.cpp b/src/Sensors.cpp index 3a27aad4..badfc9a2 100644 --- a/src/Sensors.cpp +++ b/src/Sensors.cpp @@ -13,7 +13,7 @@ void sensors_init() { #ifdef level_enable if (sensors_reading_map[0] == 1) - level_reading(); + ultrasonic_reading(); #endif if (counter > 10) { @@ -387,13 +387,12 @@ void dhtC() { sensors_reading_map[7] = 1; } -void dhtC_reading() { - float value; +void dhtC_reading() { ComfortState cf; if (dht.getStatus() != 0) { sendSTATUS("dhtComfort", String(dht.getStatusString())); } else { - value = dht.getComfortRatio(cf, jsonReadStr(configLiveJson, dhtT_value_name).toFloat(), jsonReadStr(configLiveJson, dhtH_value_name).toFloat(), false); + float value = 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", ""); From 817a3e58982e2892221476b0796dc3d6dc58440f Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Fri, 19 Jun 2020 22:14:50 +0200 Subject: [PATCH 12/17] Global change --- data/config.json | 19 +- data/configs/1-relay.c.txt | 3 + data/configs/1-relay.s.txt | 1 + data/configs/10-dht22.c.txt | 7 + data/configs/10-dht22.s.txt | 1 + data/configs/11-analog.c.txt | 8 + data/configs/11-analog.s.txt | 1 + data/configs/12-bmp280.c.txt | 6 + data/configs/12-bmp280.s.txt | 1 + data/configs/13-bme280.c.txt | 9 + data/configs/13-bme280.s.txt | 1 + data/configs/14-dallas.c.txt | 5 + data/configs/14-dallas.s.txt | 1 + data/configs/15-termostat.c.txt | 12 + data/configs/15-termostat.s.txt | 6 + data/configs/16-ultrasonic.c.txt | 12 + data/configs/16-ultrasonic.s.txt | 6 + data/configs/17-moution.c.txt | 11 + data/configs/17-moution.s.txt | 7 + data/configs/18-moution.c.txt | 12 + data/configs/18-moution.s.txt | 10 + data/configs/19-stepper.c.txt | 17 + data/configs/19-stepper.s.txt | 12 + data/configs/2-relay.c.txt | 6 + data/configs/2-relay.s.txt | 6 + data/configs/20-servo.c.txt | 17 + data/configs/20-servo.s.txt | 12 + data/configs/3-relay.c.txt | 4 + data/configs/3-relay.s.txt | 6 + data/configs/4-relay.c.txt | 3 + data/configs/4-relay.s.txt | 8 + data/configs/5-relay.c.txt | 4 + data/configs/5-relay.s.txt | 3 + data/configs/6-relay.c.txt | 6 + data/configs/6-relay.s.txt | 8 + data/configs/7-relay.c.txt | 6 + data/configs/7-relay.s.txt | 4 + data/configs/8-pwm.c.txt | 6 + data/configs/8-pwm.s.txt | 1 + data/configs/9-dht11.c.txt | 7 + data/configs/9-dht11.s.txt | 1 + data/configs/firmware.c.txt | 12 + data/configs/firmware.s.txt | 13 + data/configuration.json | 118 --- data/css/build.css.gz | Bin 15607 -> 15178 bytes data/dev.json | 92 -- data/icon.jpeg | Bin 0 -> 15396 bytes data/index.htm.gz | Bin 1976 -> 1444 bytes data/index.json | 85 +- data/js/build.chart.js.gz | Bin 12758 -> 12758 bytes data/js/function.js.gz | Bin 19860 -> 17521 bytes data/lang/lang.ru.json | 39 + data/mqtt.json | 111 --- data/pushingbox.json | 46 - data/set.device.json | 143 +++ data/set.mqtt.json | 133 +++ data/set.push.json | 51 + data/set.udp.json | 96 ++ data/{utilities.json => set.utilities.json} | 24 +- data/set.wifi.json | 185 ++++ data/setup.json | 162 ---- data/widgets/outstanding/widget.select.json | 7 + include/Consts.h | 1 + include/Global.h | 160 ++-- lib/Arduino-UpTime/Changelog | 2 + lib/Arduino-UpTime/Makefile | 15 + lib/Arduino-UpTime/README | 99 ++ lib/Arduino-UpTime/UpTime.cpp | 65 ++ lib/Arduino-UpTime/UpTime.h | 124 +++ .../examples/UpTime_synopsis/README | 4 + .../UpTime_synopsis/UpTime_synopsis.ino | 24 + .../examples/UpTime_tick/README | 11 + .../examples/UpTime_tick/UpTime_tick.ino | 52 + src/Cmd.cpp | 898 +++++++++--------- src/FileSystem.cpp | 45 +- src/Global.cpp | 69 +- src/Init.cpp | 272 ++---- src/Logging.cpp | 240 +++-- src/Mqtt.cpp | 370 +++----- src/Scenario.cpp | 161 ++-- src/TimeUtils.cpp | 203 ++-- src/Timers.cpp | 148 +-- src/Upgrade.cpp | 253 ++--- src/Web.cpp | 356 +++++++ src/Web_server.cpp | 380 ++++---- src/WiFiUtils.cpp | 206 ++-- src/Widgets.cpp | 115 ++- src/i2c_bus.cpp | 54 +- src/iot_firmware.cpp | 121 ++- src/udp.cpp | 38 +- 90 files changed, 3370 insertions(+), 2709 deletions(-) create mode 100644 data/configs/1-relay.c.txt create mode 100644 data/configs/1-relay.s.txt create mode 100644 data/configs/10-dht22.c.txt create mode 100644 data/configs/10-dht22.s.txt create mode 100644 data/configs/11-analog.c.txt create mode 100644 data/configs/11-analog.s.txt create mode 100644 data/configs/12-bmp280.c.txt create mode 100644 data/configs/12-bmp280.s.txt create mode 100644 data/configs/13-bme280.c.txt create mode 100644 data/configs/13-bme280.s.txt create mode 100644 data/configs/14-dallas.c.txt create mode 100644 data/configs/14-dallas.s.txt create mode 100644 data/configs/15-termostat.c.txt create mode 100644 data/configs/15-termostat.s.txt create mode 100644 data/configs/16-ultrasonic.c.txt create mode 100644 data/configs/16-ultrasonic.s.txt create mode 100644 data/configs/17-moution.c.txt create mode 100644 data/configs/17-moution.s.txt create mode 100644 data/configs/18-moution.c.txt create mode 100644 data/configs/18-moution.s.txt create mode 100644 data/configs/19-stepper.c.txt create mode 100644 data/configs/19-stepper.s.txt create mode 100644 data/configs/2-relay.c.txt create mode 100644 data/configs/2-relay.s.txt create mode 100644 data/configs/20-servo.c.txt create mode 100644 data/configs/20-servo.s.txt create mode 100644 data/configs/3-relay.c.txt create mode 100644 data/configs/3-relay.s.txt create mode 100644 data/configs/4-relay.c.txt create mode 100644 data/configs/4-relay.s.txt create mode 100644 data/configs/5-relay.c.txt create mode 100644 data/configs/5-relay.s.txt create mode 100644 data/configs/6-relay.c.txt create mode 100644 data/configs/6-relay.s.txt create mode 100644 data/configs/7-relay.c.txt create mode 100644 data/configs/7-relay.s.txt create mode 100644 data/configs/8-pwm.c.txt create mode 100644 data/configs/8-pwm.s.txt create mode 100644 data/configs/9-dht11.c.txt create mode 100644 data/configs/9-dht11.s.txt create mode 100644 data/configs/firmware.c.txt create mode 100644 data/configs/firmware.s.txt delete mode 100644 data/configuration.json delete mode 100644 data/dev.json create mode 100644 data/icon.jpeg create mode 100644 data/lang/lang.ru.json delete mode 100644 data/mqtt.json delete mode 100644 data/pushingbox.json create mode 100644 data/set.device.json create mode 100644 data/set.mqtt.json create mode 100644 data/set.push.json create mode 100644 data/set.udp.json rename data/{utilities.json => set.utilities.json} (70%) create mode 100644 data/set.wifi.json delete mode 100644 data/setup.json create mode 100644 data/widgets/outstanding/widget.select.json create mode 100644 lib/Arduino-UpTime/Changelog create mode 100644 lib/Arduino-UpTime/Makefile create mode 100644 lib/Arduino-UpTime/README create mode 100644 lib/Arduino-UpTime/UpTime.cpp create mode 100644 lib/Arduino-UpTime/UpTime.h create mode 100644 lib/Arduino-UpTime/examples/UpTime_synopsis/README create mode 100644 lib/Arduino-UpTime/examples/UpTime_synopsis/UpTime_synopsis.ino create mode 100644 lib/Arduino-UpTime/examples/UpTime_tick/README create mode 100644 lib/Arduino-UpTime/examples/UpTime_tick/UpTime_tick.ino create mode 100644 src/Web.cpp diff --git a/data/config.json b/data/config.json index 180bdcd3..589bab8c 100644 --- a/data/config.json +++ b/data/config.json @@ -1,10 +1,10 @@ { "name": "IoTmanager", "chipID": "", - "ssidAP": "WiFi2", - "passwordAP": "", - "ssid": "rise", - "password": "hostel3333", + "apssid": "IoTmanager", + "appass": "", + "routerssid": "rise", + "routerpass": "hostel3333", "timezone": 2, "ntp": "pool.ntp.org", "mqttServer": "91.204.228.124", @@ -12,9 +12,10 @@ "mqttPrefix": "/rise", "mqttUser": "test", "mqttPass": "test", - "scenario": "1", - "pushingbox_id": "v7C133E426B0C69E", - "web_login": "admin", - "web_pass": "admin", - "udponoff": "1" + "scen": "1", + "pushingboxid": "v7C133E426B0C69E", + "weblogin": "admin", + "webpass": "admin", + "udponoff": "1", + "blink":"1" } \ No newline at end of file diff --git a/data/configs/1-relay.c.txt b/data/configs/1-relay.c.txt new file mode 100644 index 00000000..733f4c95 --- /dev/null +++ b/data/configs/1-relay.c.txt @@ -0,0 +1,3 @@ +button 1 5 Включить#реле Реле 0 1 + +//это простая кнопка номер 1 управляющая пином 5 имеющая начальное состояние 0 \ No newline at end of file diff --git a/data/configs/1-relay.s.txt b/data/configs/1-relay.s.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/data/configs/1-relay.s.txt @@ -0,0 +1 @@ + diff --git a/data/configs/10-dht22.c.txt b/data/configs/10-dht22.c.txt new file mode 100644 index 00000000..a0124e41 --- /dev/null +++ b/data/configs/10-dht22.c.txt @@ -0,0 +1,7 @@ +dhtT t 2 dht22 Температура#DHT,#t°C Датчики any-data 1 +dhtH h 2 dht22 Влажность#DHT,#t°C Датчики any-data 2 +dhtComfort Степень#комфорта: Датчики 3 +dhtPerception Восприятие: Датчики 4 +dhtDewpoint Точка#росы: Датчики 5 +logging t 1 50 Температура Датчики 6 +logging h 1 50 Влажность Датчики 7 \ No newline at end of file diff --git a/data/configs/10-dht22.s.txt b/data/configs/10-dht22.s.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/data/configs/10-dht22.s.txt @@ -0,0 +1 @@ + diff --git a/data/configs/11-analog.c.txt b/data/configs/11-analog.c.txt new file mode 100644 index 00000000..429ccada --- /dev/null +++ b/data/configs/11-analog.c.txt @@ -0,0 +1,8 @@ +analog adc 0 Аналоговый#вход,#% Датчики progress-round 310 620 1 100 1 +logging adc 5 100 Аналоговый#вход Датчики 2 + +//если датчик углекислого газа выдает напряжение от 1 вольта до 2 вольт, то значит +//значение чтения аналогового входа будут примерно равным +//при 1 вольте - 310, а при 2 вольтах - 620 (считаем по пропорции) +//данная строка переведет диапазон 310-620 в диапазон 1-100 и отобразит в приложении +//варианты отображения: any-data, progress-round, progress-line, fill-gauge diff --git a/data/configs/11-analog.s.txt b/data/configs/11-analog.s.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/data/configs/11-analog.s.txt @@ -0,0 +1 @@ + diff --git a/data/configs/12-bmp280.c.txt b/data/configs/12-bmp280.c.txt new file mode 100644 index 00000000..16956455 --- /dev/null +++ b/data/configs/12-bmp280.c.txt @@ -0,0 +1,6 @@ +bmp280T temp1 0x76 Температура#bmp280 Датчики any-data 1 +bmp280P press1 0x76 Давление#bmp280 Датчики any-data 2 +logging temp1 1 100 Температура Датчики 3 +logging press1 1 100 Давление Датчики 4 + +//Чтение и логгирование датчика bmp280. Датчик подключается к шине i2c (esp8266 - gpio 5, 4) \ No newline at end of file diff --git a/data/configs/12-bmp280.s.txt b/data/configs/12-bmp280.s.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/data/configs/12-bmp280.s.txt @@ -0,0 +1 @@ + diff --git a/data/configs/13-bme280.c.txt b/data/configs/13-bme280.c.txt new file mode 100644 index 00000000..e8414f61 --- /dev/null +++ b/data/configs/13-bme280.c.txt @@ -0,0 +1,9 @@ +bme280T temp1 0x76 Температура#bmp280 Датчики any-data 1 +bme280P pres1 0x76 Давление#bmp280 Датчики any-data 2 +bme280H hum1 0x76 Влажность#bmp280 Датчики any-data 3 +bme280A altit1 0x76 Высота#bmp280 Датчики any-data 4 +logging temp1 1 100 Температура Датчики 5 +logging press1 1 100 Давление Датчики 6 +logging hum1 1 100 Влажность Датчики 7 + +//Чтение и логгирование датчика bme280. Датчик подключается к шине i2c (esp8266 - gpio 5, 4) \ No newline at end of file diff --git a/data/configs/13-bme280.s.txt b/data/configs/13-bme280.s.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/data/configs/13-bme280.s.txt @@ -0,0 +1 @@ + diff --git a/data/configs/14-dallas.c.txt b/data/configs/14-dallas.c.txt new file mode 100644 index 00000000..e6686b14 --- /dev/null +++ b/data/configs/14-dallas.c.txt @@ -0,0 +1,5 @@ +dallas 2 Водонагреватель,#t°C Датчики any-data 1 +logging dallas 1 100 Температура Датчики 2 + +//2 - номер пина датчика +//варианты отображения: any-data, progress-round, progress-line, fill-gauge \ No newline at end of file diff --git a/data/configs/14-dallas.s.txt b/data/configs/14-dallas.s.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/data/configs/14-dallas.s.txt @@ -0,0 +1 @@ + diff --git a/data/configs/15-termostat.c.txt b/data/configs/15-termostat.c.txt new file mode 100644 index 00000000..af75deeb --- /dev/null +++ b/data/configs/15-termostat.c.txt @@ -0,0 +1,12 @@ +dallas 2 Водонагреватель,#t°C Термостат any-data 1 +logging dallas 5 100 Температура Термостат 2 +inputDigit digit1 При#скольки#выключить? Термостат 40 3 +inputDigit digit2 При#скольки#включить? Термостат 20 4 +button 1 5 Нагреватель Термостат 0 5 +button 2 line1,line2, Автоматический#режим Термостат 1 6 + +//2 - номер пина датчика +//5 - номер пина реле +//это термостат который будет держать температуру между двумя +//установленными в приложении значениями, так же можно выключить +//автоматический режим, и тогда нагреватель будет управляться в ручную \ No newline at end of file diff --git a/data/configs/15-termostat.s.txt b/data/configs/15-termostat.s.txt new file mode 100644 index 00000000..60782623 --- /dev/null +++ b/data/configs/15-termostat.s.txt @@ -0,0 +1,6 @@ +dallas > digit1 +buttonSet 1 0 +end +dallas < digit2 +buttonSet 1 1 +end \ No newline at end of file diff --git a/data/configs/16-ultrasonic.c.txt b/data/configs/16-ultrasonic.c.txt new file mode 100644 index 00000000..4eacdf30 --- /dev/null +++ b/data/configs/16-ultrasonic.c.txt @@ -0,0 +1,12 @@ +ultrasonicPr p 14 12 Уровень#в#баке,#% Датчики fill-gauge 125 25 1 +ultrasonicCm cm 14 12 Дистанция,#см Датчики any-data 2 +inputDigit digit1 При#скольки#выключить? Датчики 95 3 +inputDigit digit2 При#скольки#включить? Датчики 10 4 +button 1 5 Насос Датчики 0 5 +logging p 1 100 Вода#в#баке Датчики 6 + +//125 - это расстояние от датчика до дна бака в сантиметрах +//25 - это расстояние от датчика до поверхности воды когда бак полный в сантиметрах +//distancePr - эта строка выводит процент заполнения бака +//distanceCm - эта строка выводит расстояние в сантиметрах +//варианты отображения: any-data, progress-round, progress-line, fill-gauge \ No newline at end of file diff --git a/data/configs/16-ultrasonic.s.txt b/data/configs/16-ultrasonic.s.txt new file mode 100644 index 00000000..babd78ab --- /dev/null +++ b/data/configs/16-ultrasonic.s.txt @@ -0,0 +1,6 @@ +p > digit1 +buttonSet 1 0 +end +p < digit2 +buttonSet 1 1 +end \ No newline at end of file diff --git a/data/configs/17-moution.c.txt b/data/configs/17-moution.c.txt new file mode 100644 index 00000000..fa0b78ac --- /dev/null +++ b/data/configs/17-moution.c.txt @@ -0,0 +1,11 @@ +button 1 5 Прихожая Освещение 0 1 +inputDigit digit1 Задержка#выключения Освещение 30 2 +switch 1 0 10 + +//0 - номер пина датчика движения +//5 - номер пина реле +//при срабатывании датчика движения включится реле и обратный таймер на 30 сек +//если движение не будет обнаружено повтороно в течении 30 секунд - свет выключится +//если движение повторится в течении 30 секунд то таймер продлится опять на 30 сек +//свет выключится только в том случае если в комнате все замрет на 30 сек +//задержку выключения можно будет настраивать в приложении \ No newline at end of file diff --git a/data/configs/17-moution.s.txt b/data/configs/17-moution.s.txt new file mode 100644 index 00000000..899b7035 --- /dev/null +++ b/data/configs/17-moution.s.txt @@ -0,0 +1,7 @@ +switch1 = 1 +timerStart 1 digit1 sec +buttonSet 1 1 +end +timer1 = 0 +buttonSet 1 0 +end \ No newline at end of file diff --git a/data/configs/18-moution.c.txt b/data/configs/18-moution.c.txt new file mode 100644 index 00000000..bc7d8192 --- /dev/null +++ b/data/configs/18-moution.c.txt @@ -0,0 +1,12 @@ +switch 1 0 20 +text 1 Вход: Охрана 1 +textSet 1 не#обнаружено-time +button 1 na Сбросить Охрана 0 2 +button 2 line3, Включить#push Охрана 1 3 + +//0 - номер пина датчика +//при срабатывании датчика движения устройство пошлет пуш и в приложении будет +//написано в текстовом поле, что движение было обнаружено +//так же будет зафиксирован момент времени срабатывания датчика +//в приложении можно отключать отправку пуш сообщений на тот случай если дома хозяин +//перевести датчик снова в режим ожидания движения можно нажав кнопку сброса в приложении \ No newline at end of file diff --git a/data/configs/18-moution.s.txt b/data/configs/18-moution.s.txt new file mode 100644 index 00000000..f764dc9d --- /dev/null +++ b/data/configs/18-moution.s.txt @@ -0,0 +1,10 @@ +switch1 = 1 +textSet 1 обнаружено#движение-time +end +button1 = 1 +textSet 1 не#обнаружено-time +buttonSet 1 0 +end +switch1 = 1 +push Внимание обнаружено#движение! +end \ No newline at end of file diff --git a/data/configs/19-stepper.c.txt b/data/configs/19-stepper.c.txt new file mode 100644 index 00000000..82b41ae2 --- /dev/null +++ b/data/configs/19-stepper.c.txt @@ -0,0 +1,17 @@ +stepper 1 12 4 +stepper 2 13 5 +button 1 na Открыть#штору#1 Шторы 0 1 +button 2 na Открыть#штору#2 Шторы 0 2 + +//для подключения необходим драйвер шагового двигателя A4988 + +//stepper 1 12 4 шаговый двигатель с параметрами: 1 - номер шагового двигателя, +//12 - номер пина количества шагов, 4 - номер пина направления + +//stepper 2 13 5 шаговый двигатель с параметрами: 2 - номер шагового двигателя, +//13 - номер пина количества шагов, 5 - номер пина направления + +//stepperSet 1 200 5 - прокрутить шаговик номер 1 на 200 шагов по часовой стрелке +//с задержкой между шагами 5 милисекунд (чем меньше задержка тем больше скорость) +//если поставить -200 то будет вращаться против часовой стрелки +//можно подключить не более двух шаговиков \ No newline at end of file diff --git a/data/configs/19-stepper.s.txt b/data/configs/19-stepper.s.txt new file mode 100644 index 00000000..16e7cfa6 --- /dev/null +++ b/data/configs/19-stepper.s.txt @@ -0,0 +1,12 @@ +button1 = 1 +stepperSet 1 200 1 +end +button1 = 0 +stepperSet 1 -200 1 +end +button2 = 1 +stepperSet 2 200 1 +end +button2 = 0 +stepperSet 2 -200 1 +end \ No newline at end of file diff --git a/data/configs/2-relay.c.txt b/data/configs/2-relay.c.txt new file mode 100644 index 00000000..1e54f5dd --- /dev/null +++ b/data/configs/2-relay.c.txt @@ -0,0 +1,6 @@ +inputTime time1 Во#сколько#включить? Таймеры 20-30-00 1 +inputTime time2 Во#сколько#выключить? Таймеры 20-35-00 2 +button 1 5 Кнопка#(по#таймеру) Таймеры 0 3 + +//время в приложение необходимо вводить в строгом формате: ЧЧ-ММ-СС +//можно создавать любое количество таймеров, копируя строку inputTime... \ No newline at end of file diff --git a/data/configs/2-relay.s.txt b/data/configs/2-relay.s.txt new file mode 100644 index 00000000..5deba589 --- /dev/null +++ b/data/configs/2-relay.s.txt @@ -0,0 +1,6 @@ +timenow = time1 +buttonSet 1 1 +end +timenow = time2 +buttonSet 1 0 +end diff --git a/data/configs/20-servo.c.txt b/data/configs/20-servo.c.txt new file mode 100644 index 00000000..5d45aea0 --- /dev/null +++ b/data/configs/20-servo.c.txt @@ -0,0 +1,17 @@ +servo 1 12 50 Мой#сервопривод Сервоприводы 0 100 0 180 1 +servo 2 13 50 Мой#сервопривод Сервоприводы 0 100 0 180 2 +button 1 na Открыть1 Сервоприводы 0 3 +button 2 na Открыть2 Сервоприводы 0 4 + +//Можно создавать не более двух сервоприводов на одном устройстве. +//1 - номер привода +//12 - номер пина +//50 - начальное значение в процентах + +//0 - 100 диапазон ползунка +//0 - 180 диапазон угла + +//Представим ситуацию когда есть некая заслонка и при угле в 30 градусов она закрыта, +//а при угле в 90 градусов открыта. В этом случае необходимо написать +//0 100 30 90 и тогда поставив ползунок в 0 % серва встанет в положение 30 градусов, +//а если поставить ползунок в 100 % серва встанет в положение 90 градусов. \ No newline at end of file diff --git a/data/configs/20-servo.s.txt b/data/configs/20-servo.s.txt new file mode 100644 index 00000000..b4340463 --- /dev/null +++ b/data/configs/20-servo.s.txt @@ -0,0 +1,12 @@ +button1 = 1 +servoSet 1 100 +end +button1 = 0 +servoSet 1 0 +end +button2 = 1 +servoSet 2 100 +end +button2 = 0 +servoSet 2 0 +end \ No newline at end of file diff --git a/data/configs/3-relay.c.txt b/data/configs/3-relay.c.txt new file mode 100644 index 00000000..9f0c5c45 --- /dev/null +++ b/data/configs/3-relay.c.txt @@ -0,0 +1,4 @@ +button 1 5 Вкл#на#время Таймеры 0 1 +inputDigit digit1 Через#сколько#секунд#выключить? Таймеры 5 2 + +//в сценариях можно поменять на sec, min или hours если нужны другие размерности времени \ No newline at end of file diff --git a/data/configs/3-relay.s.txt b/data/configs/3-relay.s.txt new file mode 100644 index 00000000..f8ced990 --- /dev/null +++ b/data/configs/3-relay.s.txt @@ -0,0 +1,6 @@ +button1 = 1 +timerStart 1 digit1 sec +end +timer1 = 0 +buttonSet 1 0 +end \ No newline at end of file diff --git a/data/configs/4-relay.c.txt b/data/configs/4-relay.c.txt new file mode 100644 index 00000000..b0978b0d --- /dev/null +++ b/data/configs/4-relay.c.txt @@ -0,0 +1,3 @@ +button 1 na Включить#все Освещение 0 1 + +//при нажатии на эту кнопку пины номер 5 и 13 поведут себя как установленно в сценариях \ No newline at end of file diff --git a/data/configs/4-relay.s.txt b/data/configs/4-relay.s.txt new file mode 100644 index 00000000..276282c3 --- /dev/null +++ b/data/configs/4-relay.s.txt @@ -0,0 +1,8 @@ +button1 = 1 +pinSet 5 1 +pinSet 13 0 +end +button1 = 0 +pinSet 5 0 +pinSet 13 1 +end \ No newline at end of file diff --git a/data/configs/5-relay.c.txt b/data/configs/5-relay.c.txt new file mode 100644 index 00000000..5ef7e5f5 --- /dev/null +++ b/data/configs/5-relay.c.txt @@ -0,0 +1,4 @@ +button 1 13 Включить#реле Реле 0 1 +switch 1 0 10 + +//можно управлять реле на пине 13 кнопкой на пине 0 или кнопкой в приложении \ No newline at end of file diff --git a/data/configs/5-relay.s.txt b/data/configs/5-relay.s.txt new file mode 100644 index 00000000..093de1fe --- /dev/null +++ b/data/configs/5-relay.s.txt @@ -0,0 +1,3 @@ +switch1 = 1 +buttonChange 1 +end \ No newline at end of file diff --git a/data/configs/6-relay.c.txt b/data/configs/6-relay.c.txt new file mode 100644 index 00000000..db812455 --- /dev/null +++ b/data/configs/6-relay.c.txt @@ -0,0 +1,6 @@ +button 1 5 Включить#все Реле 0 1 + + +//что бы использовать эту конфигурацию на другой esp необходимо активировать пресет +//"Вкл. выкл. локального реле", затем в сценарии данного модуля подставить Device ID +//того esp, кнопка на этом девайсе будет выключать другие устройства по воздуху \ No newline at end of file diff --git a/data/configs/6-relay.s.txt b/data/configs/6-relay.s.txt new file mode 100644 index 00000000..9eb30933 --- /dev/null +++ b/data/configs/6-relay.s.txt @@ -0,0 +1,8 @@ +button1 = 1 +mqtt 3233662-1589485 buttonSet_1_1 +mqtt 2233662-1589486 buttonSet_1_1 +end +button1 = 0 +mqtt 3233662-1589485 buttonSet_1_0 +mqtt 2233662-1589486 buttonSet_1_0 +end \ No newline at end of file diff --git a/data/configs/7-relay.c.txt b/data/configs/7-relay.c.txt new file mode 100644 index 00000000..739a1424 --- /dev/null +++ b/data/configs/7-relay.c.txt @@ -0,0 +1,6 @@ +switch 1 0 10 + +//что бы использовать эту конфигурацию на другой esp необходимо активировать пресет +//"Вкл. выкл. локального реле", затем в сценарии данного модуля подставить Device ID +//того esp, к данному модулю нужно подключить кнопку к пину 0 и тогда +//один девайс будет управлять другим по воздуху \ No newline at end of file diff --git a/data/configs/7-relay.s.txt b/data/configs/7-relay.s.txt new file mode 100644 index 00000000..0c48cbdf --- /dev/null +++ b/data/configs/7-relay.s.txt @@ -0,0 +1,4 @@ +switch1 = 1 +mqtt 3233662-1589485 buttonChange_1 +mqtt 2233662-1589486 buttonChange_1 +end \ No newline at end of file diff --git a/data/configs/8-pwm.c.txt b/data/configs/8-pwm.c.txt new file mode 100644 index 00000000..09eef72c --- /dev/null +++ b/data/configs/8-pwm.c.txt @@ -0,0 +1,6 @@ +pwm 1 3 Яркость#коредор: Реле 1023 1 +pwm 2 4 Яркость#ванная: Реле 510 2 + +//в приложении появятся ползунки, соответствующее значение pwm +//будет установленно на пинах 3 и 4 +//1023 и 510 это начальные значения после загрузки модуля \ No newline at end of file diff --git a/data/configs/8-pwm.s.txt b/data/configs/8-pwm.s.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/data/configs/8-pwm.s.txt @@ -0,0 +1 @@ + diff --git a/data/configs/9-dht11.c.txt b/data/configs/9-dht11.c.txt new file mode 100644 index 00000000..ce8ec1a8 --- /dev/null +++ b/data/configs/9-dht11.c.txt @@ -0,0 +1,7 @@ +dhtT t 2 dht11 Температура#DHT,#t°C Датчики any-data 1 +dhtH h 2 dht11 Влажность#DHT,#t°C Датчики any-data 2 +dhtComfort Степень#комфорта: Датчики 3 +dhtPerception Восприятие: Датчики 4 +dhtDewpoint Точка#росы: Датчики 5 +logging t 1 50 Температура Датчики 6 +logging h 1 50 Влажность Датчики 7 \ No newline at end of file diff --git a/data/configs/9-dht11.s.txt b/data/configs/9-dht11.s.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/data/configs/9-dht11.s.txt @@ -0,0 +1 @@ + diff --git a/data/configs/firmware.c.txt b/data/configs/firmware.c.txt new file mode 100644 index 00000000..99beb0be --- /dev/null +++ b/data/configs/firmware.c.txt @@ -0,0 +1,12 @@ +button 1 na Включить#все Реле 0 1 +button 2 13 Прихожая Реле 0 2 +button 3 14 Кухня Реле 0 3 +pwm 1 3 Яркость#коредор: Реле 1023 4 +pwm 2 4 Яркость#ванная: Реле 510 5 +analog adc 0 Аналоговый#вход Датчики fill-gauge 1 1023 1 1023 6 +logging adc 1 100 Аналоговый#вход Датчики 7 + +//Это демо конфигурация. В ней показано как связать кнопки c помощью сценариев +//Кнопка номер 1 связана с кнопкой 2, 3 и с pwm 2 +//Так же продемонстрированна система логгирования данных строкой logging +//1 - это интервал между точками в минутах, 100 это количество точек \ No newline at end of file diff --git a/data/configs/firmware.s.txt b/data/configs/firmware.s.txt new file mode 100644 index 00000000..4927ac1e --- /dev/null +++ b/data/configs/firmware.s.txt @@ -0,0 +1,13 @@ +button1 = 1 +buttonSet 2 1 +buttonSet 3 1 +pwmSet 2 1024 +end +button1 = 0 +buttonSet 2 0 +buttonSet 3 0 +pwmSet 2 0 +end +adc > 50 +buttonSet 2 1 +end \ No newline at end of file diff --git a/data/configuration.json b/data/configuration.json deleted file mode 100644 index fb4381dd..00000000 --- a/data/configuration.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "configs": [ - "/config.live.json", - "/config.setup.json", - "/config.option.json" - ], - "class": "col-sm-offset-1 col-sm-10", - "content": [ - { - "type": "h5", - "title": "{{name}}", - "class": "alert-warning" - }, - { - "type": "h4", - "title": "Device ID: {{chipID}}" - }, - { - "type": "h4", - "title": "IP address: {{ip}}" - }, - { - "type": "h4", - "title": "Uptime: {{uptime}}" - }, - { - "type": "h4", - "title": "Time: {{time}}" - }, - { - "type": "hr" - }, - { - "type": "dropdown", - "name": "help-url", - "class": "btn btn-warning btn-lg", - "style": "display:inline", - "title": { - "#": "Выбирите то, во что Вы хотите превратить это устройство ", - "/preset?arg=1": "1.Вкл. выкл. локального реле", - "/preset?arg=2": "2.Вкл. выкл. локального реле в определенное время", - "/preset?arg=3": "3.Вкл. выкл. локального реле на определенный период времени", - "/preset?arg=4": "4.Вкл. выкл. нескольких локальных реле кнопкой в приложении", - "/preset?arg=5": "5.Вкл. выкл. локального реле физической кнопкой и кнопкой в приложении параллельно (для выключателя света)", - "/preset?arg=6": "6.Вкл. выкл. нескольких удаленных реле кнопкой в приложении (нужно указать Device ID)", - "/preset?arg=7": "7.Вкл. выкл. нескольких удаленных реле физической кнопкой (нужно указать Device ID)", - "/preset?arg=8": "8.Широтно импульсная модуляция", - "/preset?arg=9": "9.Сенсор DHT11 и логгирование", - "/preset?arg=10": "10.Сенсор DHT22, DHT33, DHT44, AM2302, RHT03 и логгирование", - "/preset?arg=11": "11.Аналоговый сенсор и логгирование", - "/preset?arg=12": "12.Сенсор DS18B20 и логгирование", - "/preset?arg=13": "13.Термостат на DS18B20 с переключением в ручной режим и логгированием", - "/preset?arg=14": "14.Контроль уровня в баке на сенсорах: JSN-SR04T, HC-SR04, HY-SRF05 и логгирование (управление насосом)", - "/preset?arg=15": "15.Датчик движения включающий свет", - "/preset?arg=16": "16.Охранный датчик движения", - "/preset?arg=17": "17.Система управления шаговыми двигателями на основе драйвера A4988 (открытие закрытие штор)", - "/preset?arg=18": "18.Система управления сервоприводами", - "/preset?arg=19": "Настройки по умолчанию" - } - }, - { - "type": "h2", - "title": "Конфигурация устройства" - }, - { - "type": "file", - "state": "firmware.c.txt", - "style": "width:100%;height:400px", - "title": "Сохранить", - "action": "/init?arg=2", - "class": "btn btn-block btn-success" - }, - { - "type": "link", - "title": "Подробная инструкция", - "action": "https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/wiki/Instruction", - "class": "btn btn-block btn-primary" - }, - { - "type": "h2", - "title": "Сценарии" - }, - { - "type": "checkbox", - "name": "scenario", - "title": "Включить сценарии", - "action": "/init?arg=[[scenario]]", - "state": "{{scenario}}" - }, - { - "type": "h6", - "title": "" - }, - { - "type": "file", - "state": "firmware.s.txt", - "style": "width:100%;height:400px", - "title": "Сохранить", - "action": "/init?arg=4", - "class": "btn btn-block btn-success" - }, - { - "type": "hr" - }, - { - "type": "link", - "title": "Очистить логи сенсоров", - "action": "/init?arg=3", - "class": "btn btn-block btn-success" - }, - { - "type": "link", - "title": "Главная", - "action": "/", - "class": "btn btn-block btn-danger btn-sm" - } - ] -} \ No newline at end of file diff --git a/data/css/build.css.gz b/data/css/build.css.gz index fc58d776669a70f0f4a2a6f1a1615fd4d2dabff0..4bf6e06001ba59fb28f775adfad194fffa985f28 100644 GIT binary patch literal 15178 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 E0O(?Z-~a#s delta 15611 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 L*>aDB0S5XXFI1CK diff --git a/data/dev.json b/data/dev.json deleted file mode 100644 index 9b474644..00000000 --- a/data/dev.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "configs": [ - "/config.live.json", - "/config.setup.json" - ], - "title": "Главная", - "class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6", - "content": [ - { - "type": "h5", - "title": "{{name}}", - "class": "alert-warning" - }, - { - "type": "h3", - "title": "Список других устройств в сети:" - }, - { - "type": "hr" - }, - { - "type": "csv", - "title": [ - "html", - "html", - "html" - ], - "state": "dev.csv", - "style": "width:100%;", - "class": "nan" - }, - { - "type": "hr" - }, - { - "type": "link", - "title": "Переформировать список устройств", - "action": "udp?arg=3", - "class": "btn btn-block btn-success" - }, - { - "type": "link", - "title": "Обновить страницу", - "action": "udp?arg=4", - "class": "btn btn-block btn-success" - }, - { - "type": "hr" - }, - { - "type": "text", - "class": "alert alert-warning", - "title": "После нажатия на кнопку 'Переформировать список устройств' ждите примерно минуту, а затем обновите страницу и список появится вновь" - }, - { - "type": "h3", - "title": "Имя этого устройства:" - }, - { - "type": "input", - "title": "Имя устройства", - "name": "dev_name", - "state": "{{name}}", - "pattern": "[A-Za-z0-9]{6,12}" - }, - { - "type": "button", - "title": "Сохранить", - "action": "name?arg=[[dev_name]]", - "class": "btn btn-block btn-success" - }, - { - "type": "hr" - }, - { - "type": "checkbox", - "name": "udponoff", - "title": "Включить обмен данными между устройствами", - "action": "/udp?arg=[[udponoff]]", - "state": "{{udponoff}}" - }, - { - "type": "hr" - }, - { - "type": "link", - "title": "Главная", - "action": "/", - "class": "btn btn-block btn-danger" - } - ] -} \ No newline at end of file diff --git a/data/icon.jpeg b/data/icon.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..abdd18c00ecd49330a896317621726204bdf4bac GIT binary patch literal 15396 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 literal 0 HcmV?d00001 diff --git a/data/index.htm.gz b/data/index.htm.gz index 0e9eb07009732d5d4eceb41176264f1db8bef789..139f0040889174476a6bea5be844dae04d7ea073 100644 GIT binary patch literal 1444 zcmV;V1zY+biwFp#k1|^V0BLSyWq2-VbZr2&SJ{r!Fcf|7SC}A3$}~yKPTK%t-vkH{ zh)p9mxoJ#YJJ?P;1LEJgc9JGjHi5)T;@WpPK6gv!r|vwv{p#)WyQDB{etj^nUu0eY z&G1d;r^0aX1{UNFY=FxW)RepcL5(JlVWWU+62MVJ-pMZ&r^CTZW?+iOOgW9??RFbU zk#d%>+j|Zy8gmI5AM+v z7E-QGILMpLD3$BD)4tElgKAMrY7|{EQ&fvRp?gZMr{oDW8%9UuHRWptiVniiU40FP zI{gqnS8S7b_5vVGXb`DK()w5888|YrC2mI2f+`IrsZ1VT^_&&X#0qc46HgaXnY1#5 zp{hr$mBeFfx`g;BtoI59dE(`CV}C~YsBP#}vC@zXa!^F8H1R&^cu_H)Mb@KQspf&fnv2*wQD7`gcAs<%~9pmOVoL+K7{K%JyDA zg!)hP(ZC@!uTYmNpih{9z^z6cmrtwp zkbJE*NV5@!vwFkYcAJ_c#OXvE$}5O;$(aef55gPvMK#Kp=h8}#M+8KM>pe{lVrhz2 zDVHj+ibqyshOc?;t`WnXgM$tpVR?X(3F&|@(DG{btr6$|93&)gmfjzIY>XXDc38i4 zm^+lUcw>5})LLv*Ed(12i7$66ORl5&r4<~KQwi}Zfw_ftGOvfd7SCl`>0k$h{LBbq zX}$hR?yksC%0cgB6qrg0VpIit7j2Jn%5{78&85kfiA>rN!X>pP+oTB^B)hg zGo_91z&p!b4dAjFXY+;3j$P(vY(r8`wZ=lUV+jdS#JT|$E|%VP=YL*t!ZK`Miib_X zc&%2!vJ8aRPO!wwki0cYL`yJtIoRc`}V$LyW*tGM?Ewt?aa|@iyjqL8=x}^b+_9@vYpa;JgU(NToesY#m_CVcGVa6J ztvVyQlsKSK=*J_-nE5}P)%Tz_>6Ui394hht!Bjk^E4k4$ekp~_^TRjn9y`?dDUufPmaSNP=Fa%cwe$9Q>#loV zanIYmoy+cdr`?&HxjJ#rTI*_9;>eHigW=4Dd*?iYL9)Q_I~c_JKt|b)GvH;&)=SGW zyKYbCF>OdNP1kH?v0<$p=}L0T@(PZt5k;clgQLdZa$agWa&DkF!eI;<7 z7GT5TDzQ$mos9M0`rFGTP)aH%)TP2+-Y$#?mr7P8v8x4_>B>gZi7`=DrYGn`bd{!{ zbraTROieG2&-7r~Y1T`oelx&x+Y7qeCjJvFZYGvd6!|mzu@?Bfvi3*BC#c|&TH1S! zw%f_QsEm=~_jofZmY{wMSJMsj;M(?%2%cju=%nd%$P0A?T?18V5$S4y-x!EGm<*e- z=AZS4@5di!Hhb@2$2Ac6v47B7I`AVKh-mo*Z=iD@%C zZL@WoFZMOJx;`C5ekH;N2@U`y+qpc$_9ok-WN)-D0FokQ*S$#ga+in%f$#T&&-W*g z>1W4(J39OO$!n76l)pTfx*sx4fX4Vsrl0x#!8@3fV^{$fImj`23mMgl{25jfxFTJ+ z4#>~qw&1jPaLP1{QJBuhgTZ>e4n!7l7F`8=b#NpyO(Q)fEL#Y2PW1(8d_BFo$#JPP z!VkZG@%-Ry&9pZ9zI{v6TL$XjI~u`Uh^v-@ML8HmA{}g2f6w#}#oWzQICaT%Qp~p| zeJ4daCO=ZWVzf_wqC90F>4ERtt*4-=UGKv`3bqP8vjNDouMw$7BKH=08m{%g5H}%F zLZt#77JA{o@T?ThvMbyb4?UF#siQ&@hD$wSq=X(z=@JIlz8gy@VQqdAOtLyOAg%*#7z4oJE*7{E+lV^Visd7IF@vIEJfbc zvVh(MH82u!s#NHST>C6tqN$99LoXMKnN5us>>A>UWXnX4NBK3%&+V_sX~gu+co>X~ zpaH|bwBAH1)c~L@L&q>&f%NA~N9?rVcB2iHUbQG;aST~wr@$fYcIwRp&IxbdWHDTa zL#w^uPHaV>VHRYQ!xkEv|IgnUXM)q^_PO^K#*Y0}$l&S`e_u(5{|`*j;xquN zZf0+Uo-G)MnYvLL(!rWtG0Z52!O(Lxj=VEt4d+XM=hpkIADI=UFPRv|xTF$jHFqIo zY8jD&8w#%ArpU1>DJ+I8{u2gk*P38Oc>#SF9VUc3J=|^%oJR>5&K8s_@HQlyIW|3% z`nC)WQVLm5s_fKqs=3bmr4&U@%+s8U=&EF%Oj(v=8Qn~@Q&bT}VDf8e2Aj;rUk#r% zV3`EiuyixEnC~Xw>)nQ(A2G^UwhV%xGconOod)`(LvVpd+-&bBE8C^Nd7-t)9>yEf zY>9sQ5L`u9(12_5Cn7k(jzNWG-b7xgtpN(CjFLbVb1X}Ux;sM8%{jxZ{jSqHA6`t1 zw;iK%Ys_bZ&KKQE)Hl_`xWkN(cY0rR0%MzCd5arVki|2JEf6R@Gq9{j^v$-rO^4|J zw!lV0-6hXjCu=Z%YU#O`ak|a6={dK!J~Uj{mB5gWgxWIXJd;$fp;w2TQAxBQCr8bQ ztJl?0w~4sBsj7UyKkXXjo5XWBGm%{6K869dkLzE{F}936e>UN;(BtRBXOqgChFDut zOj9iL?Kl6>4w@a}qEzQDk6Ymo+e~`lqO9lLn~F;E-15raXc4C9oI3=SG<<$}!ZBMyIYiD7 z?R4PQ-YdwG*tdH7EbgZwF7UmqOUY=DwTFAG{c?}BU+uB>`5tS3zx!I_gS)QoQ`;l< zW!Xu3FHP(H>C$iqat91KH7C=o#G*9%e}zb4odVqeW^?}&>&S8GTFCfu)okQfReWD_ z-2v{h_9KaP;5WiuHrU-kW2`wQvp*H9wso3|>mB4ZdC{(o{F0h*K%cwb1>`tlab5R+L6%gBu=Bq`_jNklVJU_bNzJ+}PJM9_y1b=SK)4#!;^ z$Eo#iQt5dz-FEJl?jtisx__*$(s~;`?M|JTmUe+&r^m#!v6Fo`xVdACQ#ba2?%nmF z6SkH86*D&JzB%qa0;y$MYAbkU2TAw)*Jr(rInU3H;){#Na3fo8w>fk*_$l<&6{)SU zx<#~io0idlyuPMs&SCtR>dRWWrTxT>HdPM&uc?3g%K!P}fBgUc^W(q#kN*yS`Nby} z???T^;bR0*Sx?$X{$d9$3w?rO>_Kr*o*nBW<(6*DcAtEUQr|<|J@Iun-u&wL_}(-5 zuUvw_f)-rga}nFvcV{F0hzoW9ng8yQzm~myPxt@3e0$fpeA_<%cl-v^l diff --git a/data/index.json b/data/index.json index 26adcc1a..1b6413ad 100644 --- a/data/index.json +++ b/data/index.json @@ -1,7 +1,8 @@ { "configs": [ "/config.live.json", - "/config.setup.json" + "/config.setup.json", + "/lang/lang.ru.json" ], "title": "Главная", "class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6", @@ -9,104 +10,60 @@ { "type": "h5", "title": "{{name}}", - "class": "alert-warning" + "class": "alert-default" }, { - "type": "h4", - "title": "Device ID: {{chipID}}" - }, - { - "type": "h4", - "title": "IP address: {{ip}}" - }, - { - "type": "h4", - "title": "Uptime: {{uptime}}" - }, - { - "type": "h4", - "title": "Time: {{time}}" - }, - { - "type": "h4", - "title": "Build version: {{firmware_version}}" - }, - { - "type": "h4", - "title": "SPIFFS version: 2.3.3" - }, - { - "type": "hr" - }, + "type": "text", + "class": "alert alert-light", + "title": "
IoT Manager
" + }, { "type": "link", "title": "Конфигурация устройства", - "action": "/?configuration", - "class": "btn btn-block btn-primary" - }, - { - "type": "hr" + "action": "/?set.device", + "class": "btn btn-block btn-default" }, { "type": "link", "title": "Список других устройств в сети", - "action": "/?dev", - "class": "btn btn-block btn-success" + "action": "/?set.udp", + "class": "btn btn-block btn-default" }, { "type": "link", "title": "Конфигурация WIFI", - "action": "/?setup", - "class": "btn btn-block btn-success" + "action": "/?set.wifi", + "class": "btn btn-block btn-default" }, { "type": "link", "title": "Конфигурация MQTT", - "action": "/?mqtt", - "class": "btn btn-block btn-success" + "action": "/?set.mqtt", + "class": "btn btn-block btn-default" }, { "type": "link", "title": "Конфигурация push", - "action": "/?pushingbox", - "class": "btn btn-block btn-success" + "action": "/?set.push", + "class": "btn btn-block btn-default" }, { "type": "link", "title": "Утилиты", - "action": "/?utilities", - "class": "btn btn-block btn-success" - }, - { - "type": "h3", - "name": "my-block", - "style": "position:fixed;top:50%;left:50%;width:400px;margin-left:-200px;text-align:center;", - "class": "hidden" - }, - { - "type": "hr" - }, - { - "type": "button", - "title": "Обновить прошивку", - "action": "/check", - "response": "[[my-block]]", - "class": "btn btn-block btn-danger" - }, - { - "type": "hr" + "action": "/?set.utilities", + "class": "btn btn-block btn-default" }, { "type": "link", "title": "Скачать приложение IoT Manager для android", "action": "https://play.google.com/store/apps/details?id=ru.esp8266.iotmanager", - "class": "btn btn-block btn-warning" + "class": "btn btn-block btn-default" }, { "type": "link", "title": "Скачать приложение IoT Manager для iphone", "action": "https://apps.apple.com/ru/app/iot-manager/id1155934877", - "class": "btn btn-block btn-warning" + "class": "btn btn-block btn-default" } ] } diff --git a/data/js/build.chart.js.gz b/data/js/build.chart.js.gz index bb94fbc947e0700e157bf190bdafdfc173049ad4..ac021668f0edf424e2fb22d4a8fe7ba6388bb3da 100644 GIT binary patch delta 17 ZcmcbXd@Y$nzMF&N!Sb~+8#&Gy0sutp2Ymnl delta 17 YcmcbXd@Y$nzMF&Nb@;xxjU49;0YiibO8@`> diff --git a/data/js/function.js.gz b/data/js/function.js.gz index 7e661ff6e29542314bda1c757bee5e25ed3e1fde..443fbca2101295756f788b4771ce9a9c1e023b20 100644 GIT binary patch literal 17521 zcmV(xKw@V{~b6ZZ2wb0PH>KdfP^l|Me7Y?3Xk+yhPcaNhp%q zjN&Ao_{e7|lkAEbeIVHsVSxY#0CiZ=bL<1{i)~ePH_!k95VV!uB(we^iR`1guCA*a zNcT^BKZyzZT3ib+Sc$OD-U;7{Blf+x4uuynTikZoe+D1cp3~SnabwYEi#T5OyWN|c zn@-?QJ$HK5@vird13z}Aai6*VJYZ)|e9nyCldHQGObrqE!Ixh=-#fi=;~3Zb_jk_n zgDaxFZ=9)^1i@8ifw^kzOoL@No&BvFf482~;|z?lE`H>>Jmg z1vj0aU%&bemVGDwxfW4O<8Tnn_Qeg$_Sy}Y`@n#aA~)_USm#>&{C4tQOk>-6?M}lW z3g$6^KRx}yqM3WZv3MQ&5(~goq8bT*mce!%dabGBc@t-P)mn;p5zJaMCw5v+bmvbA zN2EaZuqQ*tfB5l~LwmHIEZz8G=0?uM6Eiyw*P?OwAcxarHXIJw+MkKJ>x-ErS9LHP zEzu-SL5t)hk$u|%h4O8+=x|6&9`SEqobo>BP1)S!ywO7JC8Bbg9|~u77sXC2rVGcv z6q}ME{BAom@B{|}n(UeEs!8hH0jUtJjA`Bx$Y>S#kvJ8%aRd6G|KTvhz9GVVdqO}_ zrXY@3$@@FNM}#)V%^>`^9fQ{M7URxp1v|k(0=l&qCT3iTTgui( z*)>vmUy67`+$7#a=Bb=f5`as12Q$vj0V=G-Y;3&}cd$7b!6wXUSZB447Pds=$9FG} zgC&p;xZ5zi(d0wkEa*cRXE5Nrq3}-B5^-zV5;72X8841N=uO%1K5%`Tf6g0y6nla^ z=|sz4ds+=r%2(?@Hsz?BC6ouz?}~JjDBK*a9N{K`WG$8+8p`1m_HZnImfw^)1o#Qv zh5cmDN(?gXNd>&jBBMdhkIPzQzG0Dh&LYdHV3j33U<57zRqrBpmtYjh!w^Ie2^W`c z6bmk!-$#M}gL5g;Z|{`N0oKfd>3Rv=1}g}x2J(DE32f0&!WP$YFnJGMiU;7o{rHG} z_k|kb2?R7uAc7TnA>00X_i|=)F>~YgR9Y$`4rhVE4Ua+c0Qw{jUH`H(2RC}GT5Y** z=Vswf7mZFFyb5kacS3L1VS)j|UK;z)@(i0mb>Sj<^qqT62XzLoFKB{{a663!Xb7$?LhT)z7WgvyS zKpgCN;YKZBu%~cBsl%So;`0LO9AGy&;dIdfUlkGe?Ovl3f$xA2;d85TwtwE_9Xa=K zCmK<6K~a-k6|Vh@D41S}824^sLtuh0X3hfRjyj*c}DwZHR;HNe|tvnu^ zIsz6=#W6O-Vlc%EoY}<+J`qby0D3KC0S<^#%T!afmGv-}AV8q<04r%eLGJYLRGKu$)z-_2z%8^-Gnk!-eI5k18k{mP5A7_4abCea#_EvD3}UoKy`h~^ zN_)|iw;m=%S%0dA=5)1e!@;7hJjistZZ`);Lg+YAXS+&^S@ zY#@EH8VD`Trnyy3>wIQ`puY-3=gw-L-JPE&e*Ery1MAGhj-EHH5$$9gSG*9%L2%_# zsFdj6l$umn#1DBoC#4R?_ZSg4G@#TXGaY_**Y2I`@M}n!MH1b2|G~N~&Kt;viWxnV zH-*fJ0`QE1|0=k2G5n7NeLabT5CsX^_c9hsG`Hz6q}XJWO1B`XjzRZJ_bGK7+yeE< z%xv6ezUG7EhhiUrY7V@t5p>hgH_lQpQ&X|A1UBvEda!Az36~m5;D!QYQml5G?wQX4XefSAhHWoIlY92Nie(18%b^Ry0gHC{G+pomx*~>xU-q?+qV(R z8oHcm(uQvpL@w^F{@lG4v%^Uc$HB6{e`t*ct_C@GuG{Vs?CzlJjv$ZBL}i^m`ilK&`2w^_@^vZkO)5 ze6EnMH8eIYSvmw$L_m@Ln7b$&F(DR4Ftk0dG#CSN_iT$6i=1m=wJbUvvYOWP%K8|t zY;nz6AskPHF{9twNojprf||L0|M}{cp%N)z%t3q3eDGm&^kG;%1&^J}AT3aij8of9 ze1zmA9MR9BC*5YjDs1ZbhzYW~153it!2+iojQ%57V=qINGWaiaFBdV5IWW;GsS<7U z=gUP|RndR5Zh26{D^~>-pv8Dvw-kQ`w|SK-ebft|A+@d_*Q;7pKB@;8+lpV6p^?@9 zqGxRsz*5+CN@2<1`bDvH&O`Zfm4&j*qV-BYrI% z`MKk{*Fu6n$FUjPfTd@Ou^HBV(MqrgToDWAvI`N++Kp|FuBMZ#GCk#H2Zdt_;gjuZ zR49eSzUO4{+PRwub_Wc+aljeG0izuo1rS9^CL-HJB>IwNgT+(k&LHrBJ_uhT$Ud`4 zQh+DI7>`gY^a{S>p-P9AeX2NKkD*C1j(2gPqnR5HyS%dcMqZaExB)z-C7`Qkl0{Xe zwqz6p^kJM73T>w~Y22&RFx%;%AqST*p%0CtUf;GSy3tXM?OuN$B1;7ravDl$Tq;Al zgLEO4%(zA_qs=@GICIYlqROxA_Ok{Br=+j!mtR=<$iJi`JC`5Q3S_CCrQF-lv?REt zJp{}?l38?aWtq)&xIDknsdi?NiZ)Siweyx%ihdiG3a=yRZ`oo!=9{mB*%}mSNq?f& z99&;=wu4_}f26}lEdX^$tfr+GEK~y>`X+9afIbA_&~YRBo2)NSM6O5n=PYznZ!ztX{Ey( z$$r)c*tG z2x`sFAJ8BGDRebG)dFJ#-jKrnA@<^z!_?gCJ~G&g&?q`6b ziF~n@HxnT>dCuk*EZ!rpl5IOEXnR`F_N<`oc|qHsw-d;ldP}<5K&D?9$Y9(2G zi82tKAl;OnDy5(chZtanfyb&e1gmC-p*iB}%aFq8q+OdQm_TLYMc_f8yWO~H{jxC4 zSd%qOEEEMtTcnFe9Zo2me*pn&Qh&cP9%Y0(=xU0#N_hpC-vr_8UqH%#$ZgD&JcbtX zpB(#eOnY|>o%GexGTy%DC+j%I8g^}6pyv*Lvx<;nucO(ngq9ovdL?)&@5(|bC)C&nhCrBWE42n ziCLV0?KSRA5b7g8WSK)YQ={)Ub($W97+P4JqfO<`TJnPecQod`G4GH0{uqyYerrmT zRP{cYGRtIKi4w}o3E9xMR5OcBSWaK19%=n354IJ~upZkX)+T(bFE3>@YQIpUhL-jC zO0`d{@BIOl%A~B0QqA0JEp}P5ZA-HP4*41n7IW%m49|=!=wTs~L`z$Op_9_qyxMKG zs|s#9!&FIg^^AOC0ikQPr08HLnQ@0 zW{IJdDo!#6g!8trG!ewd_;PMKUI-`aq{~t(oLnp3*kHqGAXmW-`qVbaNiR{I{ljU0 z*l&M%-o12NyiFp5sUiH#MuREfB*Mz0B6&)Xxuc>^k1&(c0J;dRi(toH!Uo{uJsgQ1 ze%b{+fPqu!19B+cporWlHl=Q8hmuSLVwmnyllhHrV5*I;)K!60*-&67M5-!x5_5EK z!FhljY($OPwk=ANQ5&SLgNvb1zG`kA_=dw1t~`IV1X=x#A3rzmu)P$ z-p6FC)%hr_$)Q0MEosZ*7L4SlFj{qRw6BwdO@k+t?VRt4PGOkP_oh{Uowy7rJWW|UK!bIJ=H z+qKk`E3&M>H>J%rjee~|gU9n%k|R0B7=&4dE{s!UpxdDo(~OhISVlZ!>&BhMi~bkS zKO0+#$j6rSAg8L}XmhI`LoB}K@y)t$+VW;?OG~$FOoUZh+@0Ih6)x@Z7{G3D559=_ zplPwPzNbxVjJeDGrk8~FF8D8?JwBR=Yj-M!!4(eH&xgWi)!zoV)MH!`PVRU#?#stN zv<~*+AAG=z>SN24S}HI46s@OI5k+I2YLBe~nogW+0TiitaI7*TkhfK&|AuW)p|8|~ z-t*5ko}ZvslH^Q>RbU>bUa+2R+J*FbF%2*-7-#mw6cjB^w!^@@JZvJq&8#SD=%!YG z{}7+&=sW8;kOqe^fJLNPuONXw{J6qRN`^0cF7Hgy0Jb(dl(H6B$AsM#>?kk+$0-`h ztfI51iT>B>8Ox6$pc7-Q`4NfG$ZV3KE&=I{UWL(-er$AzcX%w8e6>uJl4nb|WA($a zi4QuRLZ!=^+d?lahwCBc^8$#m)mtDz=|ffq=G?0)sx1m?)fX(ju>E$U_#jf6B>~k>w8c@^QD;5$txV3j>tLzM@bk zymIFu0DFv!2e70BrUjEJV|*O3K!k)@<7fiB?kv) zYEUE7z2X&Cvf#VG2HTE-Ov4)e_kRJ4Qnb$0vU`3|s9Z5`0cuJ!Z1a=6~AZReCz4SKNN^10(HSj52|CX6E%h zeBLi+v3i68udm;>?pki^LxT+=y=Ch3v*6tlym?!39*)F;_BwdZb*IB{`PC&)C(pif z*7A&_x#Z0c^kxfr;K;Te@0ba-iHungR?oBpBiiu-8^E#+EBVG&meE>hFYf)>)4aChY z{uF+GQm-=Iy2fG+zn|e6@Tty>dFaCL=kW6le5#z0a?8O--u{f-a^j*nRce>KO{PTg z(nCsFy*gGsw#-{f6p!5WSDu%uo%zhyBcUeuM7Z{QQYqn6yH^-6yn`_YD&1m5H1G6* zS#0C>F1!w4vE-Jiy?=&w_LrXga{zyyo;U11{C$2-ZH@bb2P=Q;bOS@QJ3*`|a%JH!_dm1#AYs2Z6*--%8t zd17MW zuEw7p!hj1v`Gq!}4}4PXzeddxUDX?LbGpD+iE1NjKJ%(yLqWAw&z*}l0MM_ZFy2E^ zdW``R8YjH_-*waGqFX)ni5#2_qbZ$yML5?aFzdQ&xWn>ee`$fDXtp8>_D#cSV2tS5 z`>=zs?WM2J?Nk{^C*NoEMc-+7iBF`ScSx-ohmy!^Aust+BY-Q|cCd308+k>dbGHs^G9YtaY^-21LRn3TI=whq9Lv%F6<9Pm?BFV zz!GG2%_T#Wib&jfj-+Hj5VmQ~jszP;fr0?Yo#TV>b+iInX7pa4oUwggWU;e%Vupo2 z?ZrRWw5#l4BfYi>>pTU0N#6kJQQQ^ebK`3zIsA9#T#q_)9E7mUPc^ekDCv*;m zjiUaOK;1+rp=1j}il&c2X!KDCJt-FFn;=dAKgo!+T0t{OXsPbeelfz9oDx3URKg^{ z$ixo_GV4}8Dx}ax>_A&1vYDGkt6;;Ixp{n~y{!`9thd)Sydv%;<$=5lqI(Tian+!R z*`tD|zIM%|NJK^=RbxsJmZn|+4ZHJKkn@*o^7oN4c3j%b4OyZvHF_DDLRj*ZkLTDa z0%T?LN)jzAbmckeilVAnw8LPHibB~Y*Yh~O4S#hM(Rk!BtdPWG=Gi+if?~*V5=2%p zA`OHSmQ>M?kZZ}v%Aq#4vZ2wo_snl>TD**;8awz7HoT9(ORAOXf58Kvnq_aN7-uXL z1}8d5t3RVCl567KCCF_Qs&v(e5}w>_M3Yf(Y2Z5^C!sG5>D!9i@`p!Go??+no*px~I4Jf@`9Om=lh?E^f+)s( zt361fiW))1uV{|y<`J5i0PmpC24}OZV;LuWC%jcYKcbHI0(uT)T%kY*0Q(@5D7bUE z-e#(h|!43i199S6l=|C@fk zoIVeIeDo?Eo4NY#Lo;fdeh%f`o5WLb1o_AyY_zv|s*k+x{Q zr;M3gicEeakgGbq$aA|T0zqC?m{Uu>|4;A#`u>0Y`fq>zckloE`~Ug=uSJsT$qOBM z-NFX<9ng1W$4p=px;xzFKuUd5#ug6gqFo*>INCSZhZe?{v0H^)laKhh;-h{tW!LWeKZ9ZTfthE-49GZHQI}4*JI{5Rm z)k(TcejW)g0cDC)a-ih|(tEk%XaoD9H9Rol9b+<3Aa1v}-+C3zT7CYD5$ZV%HT{($ zMdVDub0>Mh@VsQ)R971Y>(f0ssuiAvheKAqD>Mo7dn>ScCIXx9S&_}*(hQvHHzKYt z0n21lPnpSx0H6qDg+R_dNU|WAkJIH6&RwW_=~R{wvlv;b{56I{s(ZsI$O3Cl0vAqT z5>vgQTnv};IGv@-{_Ufqqd_i4_bOdT6ZXzPTC}Uc-9I-ereOaI_}^eLn&8U`-nYRP z$bz# zR?Uao*|RJLb6yI2${etwtCKOj(6)TPy~Y-4PdSM>-J&*)Bcix?%lg*OF|Ttxv|W_1 z8tABkMFgdk6V|5|x+q5fCr~X^=0)N9V0S%dEP$&RQUiqmzUIfuEW~3VSfnp%ww;SQ zKAufSOUb2Ji3pS^DWVJJ@--16WR8ix4hyf^*G|&2WroSFc02p=X)>pe-TgS5j_G4> zf8AZaJU-lzRnhnb4(aUlFh@_@-rATKFqytpd1w5Z-HZo8N5n8CSN+x^h;}mtQ?X##O;bYulWm9NFV)Z*K8}<(kdrwG|lEB+Ecl zt8P=v_4(oT<66w-x&CJ~vRbr)v;1Q8Q~D+wwO^(4^yui|hvduTAbXpv#wSr68Xn>G zMo1iew*sb6a7b1gph`6Omx!y!JhTsotjRQQO{!&sYk0wE$1+rUaN?A5-v%xGVhh7p zfnAxZ$_a|GfQdEF785{8Q8A+i$In4I&S_#l%4pS+||1&$!vEwGAXaU81gC=h7_*GdtAKNxtb?~m-ztDF(zij)YtP^}`2bck+y)*esQvJ&_j$M5rhj_v=hO5B zh{v&)@dP(JVd764>~E6rcPP zMyxcKX$lOF*9%FdRc)EHm0`dc~agq3|h$8OUpM zIv=wN>lAibvHx*hb ze|9sO#x4HC(P`|I*EvgWGub=kP2dngK@vO&J{troJ&EtdgZvP}MpAF-P>m9(3PXrS zx_!E(iz&D#P?2$V-0ONBnP)<(i`%L2G;}_hy_{ zHCm!45Y)$092h6J^qC_NJWhj|99`5Dn0m~55o63K0Maw_o_2_ltd7GA#bLXU!--)? zKn4H-;Ber{p@O^jjly;Y=#KfPkBW7bu)`oe)oPa!811VJ9y(_Z2`Yt(yUG4;luRPZ zi~_Til8dJ%BLHg)^bE{B^t)eiWuLB+w=B$jtX{j1-bPj;J=Sy9W@);tS(y5?OJS8_99!6zlZZ(%+YS3{+$DTJ zBB%!B13wEQirMX_kAKG@Z`rWlz5M+g(7)B@^BxMyJsnxE81+d{kiX5jr4vt}Gg+;W z!Ksl#Ky46g--tHY2qIsb@a4zmC7!FW5Yn+lW_j}NovOK7b)qp$???g8lkEBEc}*gr zu6HaT5f>brk;4BOYU7YNMS<9~^m&MHqO#lwE~fA{xYUTI?sZ5*T_?{SDaUWblzm5U zjC$Ht!p(gx;!WIoNeKObiGo=X+cZG-Yu;#le7cf1kvuf%7qt67SS=~7li<@8 z$i3y>{FlA?-trgxciBFU!@W5iaN=bKKYKY70oTEg7~SGsCu?E~JOOwho_u(?Y=v$Dq9!v^u!y^yPmT^iL*;A2ow(pm z^z)z{s?%;+W}(EQnut(IfQ`2pt3%WytKklZI-|jkPK;p(LN{c$Zr}LQsjJ)|9+32) zsXHGIyE`hmfe1L8o4+lGnFwghrM@hYs3J20!kT@MPuB=|!rmIR37p&33`wBQ6yngb zH$Zi}`vaMi@LcDDAO<0Qo0;sJ<-+xF20M2*nfyh@Z{U%`O6>=$WmLcA+(-zrxQRq( zG?*9|#~F5uRdE*;dJR{TI9Qzk3yg%7+q5$OAM}NA94P?hOGkP{HFkd#H>dBZTB60O z%<_Us_W5dRm6T{fJySK6by8Tvhm^fjrJls8GfPFajSRAQD`juE3@iPZCUZJq_!^<} zp6_?8#-(`dQ3aDGq-!3qM{&YYKYYXq#c2Ga9rUDMUl@nG^t!Z!%`>O8(XbnVR-4Eu zHopMEec1e`_y4u|>%V{hADZv~%dh{jf6xjr9MS%}ZVc?;W$3tIitH8+j#&sDO(Nz) z6wVhy_+m64hQ07ZL?9<-#7I($99Rp-a20tVXI{sm*$@-Zes}mI5O~eS>f~>wWF82W z3EKufp-89&yu}HK`mli%&+ot?vs&KE-Uk_RAk{YQ_P?05xk<@QaN;(10T3A_Rn!`= zOuB(mKNwsC$Uq0k!6MgCtcXV+)R0Vs;33R*2bfZOh+h>CEQ^Xfu+p0pyV;FUtYX!P zI)bcD3a+tc*al^yUJ{7G@W`W+P-0gyLk6FK%5EXxl?10Sm0GBo_00@bLMo&xk_CJ$ zNx~zz3^y#PGy;CW%m}%*wh@M}$VU(@;~yV-ji?xQhy!%IFe9mYXo%!%wFaucs9~-! zh1QY<9zZCNqfyn!VO3h@Ga$C3m9L<@j~lU&m)iJrF&ZbUi+-oo8<c% zuh*e%%PyTIoOZP;?zQWs0AxTAjmWUpRDTm$<_HwTMxWO!H1)-47QQ;?nR6pj_eKn7 zG5-p@sS!}AkSW}C%Aee|AIKF2kewY|9BjxNxGS~uu6!k-g-fVH1rhefA9j$3X;wmR z3Pu_dc}6L+IdoxJM0I)4K3rGx$>^e3PiznSXMNcT!{N+#V>>T`qI$=1h0qn}3}q$5 zSouyT5yi?KhKdA5VXZ4NoJ(OhnX57A4Cfal*rN0$%Y zZU{_7W#X7pHmKg!Kyk1s8`Rd-Kyef*8`Rw^j*7xl*`V%S4HU<%vO(Ry@)}Y=D?53; z*{H~(nt@hq9+f0UzGDhcjJ0I3W8P168;8ZiC#=jfvW=DQQUyHKuFX=n;yr1L0SU|# zSF5z>$Y$9SyM0cgS1ZX-7YTT@#zB%L9TuALTuzSx8t@On%jxmc^F=MJ?e6VmdwZ|; z8#{Fn_~1)pZ*S5-3)Jv5ITp;PPtjgbwLu3OPowxS9@pQA)iitkOEPI-S7E~(aU=W# z%p3h_YvcM(81_e(ZWnK%us5;B?kGV%lwuVfz2Dthds~w#pC8^V;h&T#Wc!P2t-Yu4 zcXpvL^pVWaw@C;2OVDQ2q9(MgE-EcqeaWqk>$dukR4f7OSO|(kQ)v#7O!|P=Ee&4G zr#OKF=ByE6c;ex3sMy&ZS=8ScjMiyX+YUFudzdu#JLEy4hF(9dAA|#dG=qvmak3li z9)Aeea9uY&XdhD)G5rfr69Xd)Jr^L1b5Q__(O-ft}vFq-z1W`*uy zpKeHo6M1_wU5eMBO!1eto(q3r{UH28N)x!L{14Chr~~4WzTW5#{8~z1E4=8aYw_}D z4Ak~)-I9s2&@3}MTVPCmZn@ptDeePmDzjDs5}^UbpNQ;dzCss1LcV5?x2_giB5H7l zB7|`Cp&N5wwj!6+UFqt%W>g20P*5tSq8@r`dwCvw1B4S(!#f=fEe0U_OTE(aG)-qyMxvs(QmLKRAOqZKqg1XIScOWT} ze&Z`JUH&#VpxKY-0<^2#;QeRKapUXH#?aqyzrWvp)o(wWc0R!6XLs-c@4mw3EZyCI zzxmuZpNS{$#b;IW-Ft>`oF4v2*PcK+|JwR#dXZ643#-=fJz#P+o+_UVOwySFb;JSG zWU-ll*oE)t1PE>Eus2_3;<5p0YKMdc(NuIuKS&?Y*z5CK>e9Vnp&&V6@IXOfZ>2q{iW$q;yn!-Rwlkes;^lsCjhr@`_6y>5skYyqvvXZxY)Sv;GzEVcg>rHr^b&xz>?q!=l zYPjZGG-K*pFOSSe)i-jYTzgjVHHn)+jfkw%cua;}ScNU?zoqQ`n%k(p9eSlbDt9Sv zQafx_K8az}Sf$FiT7Y&j?WG%wIdbTs#z5;mE$O#o!zlE8+9$a+#7Tje>jW zuqlHD@%ldJ*I`#J?!I#*RncTY5;pmMy!mUhffZ|byyjtr<~po5wbYo&UuemqbuvZ% zct?E_mJw$&E5Buq87X}bp0a6Xphpcb-K$4@Nh>MvMhTdr6k@ zvH*atG5Pdt#1zJ%lYqvoZWXgdf>y9tgkP%|E2_qIH&dM>#~Wa%{SNoS5a(}<5amH( z@m+4Z$TyLM;H8v&#flW;XBck2+ZT4JQkJ5u)}DdE-Nt9UX6|VE;PI5S_mj>mm;y3A`wf02bu7WDL$ z%)ZvFzG0_HQ&3}OO=8J)f~VV>*nfjtB8RI%W9n(g|DND|O(=OwpdwCZ%)gin3Kk}l z7~cclRlQ%6iF_WA;d9@Km6Xp4dhM8N!UA9h17HLr3~yL??-9BbtCd1^K7iBB4j9G- zjAtVvH4tj9q;^obaEGVUENq0?2>v>rh8V`;c?vC7!7^%aY>P&;M2}>9?pCBA=qYBG z15Aiw!v}c5>F=lmg>p1Uh9X{-9!!!9<8e)DGUy@2_DYwhPe!Ye==)3YwI-fn=u2y~Sil4^dgy8t##9mH z*~8i{Pj5dC-q9mNKcGx@ZC3qU*5e>-hYdM-1lex0l(c}^*J=U{hR3z|g*A4RY$J-_ zVYhub7@tHWa0sXIbYA25dMO5~NTXLhTM#kw zit`!XZs%SMp&u?M(wgG=BkJp;6;P(*RLWr@!PO*6@>UThF%qI}Vx+7uI3T?eqGXL1 zJGR3sX?`}Fp<<7I_{0ojQ&$>l*}No1r{UL3ki^ph9Q;@DVXk)gNoV6$MzOqmakFPW zIH*?+dV0e-+P~P74c^Hkf(oAljhjB&^yA>N2%IdDEa3Eu4>(sJ=4!hDlite$Ouys- z-%?>7Wf!Z_F^?Y3j%UwbeE-_)U!E#{MV8%NeQ;Uc!;@$K7zMxl;wpNG1%a#N>#o13 z=P%mw7v1$2-SZdSH&J5;Vb}~kdi_{Ssl)Fh*QXZ@*HaR<*nBb(kDKdyFiTuseHfM_ zm+7T{Z*d-U2BAO5luRhPZTjh}&@C!4nU(<_pbT(lwi@sYnd5cLrya81(LE>DhWDV) zF3Qx^l^lK9+N0k-bo@`#aH5leB>WJmo8gMf?p<{MDk_K0ub#e^i>IFbFaQFgz+pQ% zOEBw}nTu!zoO_1%4rSOI82O1Pn={CHt7#KD7*C}K0T?dSXMT=F6BE=|G<(zJiC&HoRIG#=% zh{f66)x1EFEtSp0;cdlnHu<}OzUs|k1lu}dWS}YoTn9Ut)m1xv#^u^xUp@Wi>0_%~PZD}M zLHK#o#0&MO>NwuPxQPM3^rhK9L$n*`tH)nQ_ebw!4$}b>DF%Yglh4ZUQ~`s6$#xeq zo9!+WjJBt+S5~-HR(Q9p@LpNreR~sJhv_!6n!0;?{qWH@PovzXMD|mW3I(G^QNL!_ zh~3n_w#SEdZ=6(3cc&ZS#b**Z*DQ8(WqINT1qx+UrUeJ{xHXu~3gX7dlr^#n!bTwh zT24cFRSex2em0tpG%RYjiT2O}{(R*R(4E&u37M*rhB$k4@tR4q7V0Sau7Ld#6$Q4# zkow7R4^Rzc4rpQnWJ7$WNY-MMMAtOVK|#AJyhV~p%%7+q?50G;U6)1@l@#K9N25Q- zz@7o-UR;fmc~(;{NM^PG8V*qp`>y1)&dcd(`es@)yqC<<(F9G6mCuWtP<0Oyh^G$& zkllmTxl?g{YVIOA6!3y(A;WnFDGC&I_k41*@-Yst0jH1Bt!!DXf9_Z{u;cbcD7 z2Jo2!z-OK2=am6`?f~$4r};%?0ADx&e9>ukI}!q|jZ$)ynJX*mRaVQ+p0g~O({{|#YwpJR$|-v+rr5;G5Y?suqiHWWIc z!_oMsvqfvMOx{d^&w0}ZJhg!_6^n_Ed{n>HIe+x1)9D->!7e*F$daF@2i0z4t}6S>S7h=4i`?gX!BFhPx`7{KfTnq57p zFunRtu(vmNg-iIJSNs{U=DlCibe6kz-OKrJ7}w zp+JX76=?MF(dfcC;`$D)p|i}nC}p>jMo&|By~#zz*}_rNbVT6`%@O#ew(05sU1|<~ zPUq-dB*nGk)797M*)kIb8c)#amIBUTP6@309gr*BBK7wD&Zo_;G;u;u{{*E`tRP_5 z)+1Z8i0ycm2oBI~G%!cFoTBL-=6pKA()cu)$JunO%(!8>V30cLQ=~E|_DPDQR_I8$ z+d*|NG^a1!eHz!8zVzf5j$L0v_!M%8!|0EsJ zRp|>>#^$;*{k%Qw-Idk3$e2gWbsls(cka-q)+&9)8?-L&D@+9#cESb~_eD=I?*@*A z8p6N+W>DCtnNSm$3^btv_}E7r@Y<~o)EeLe0nEIag00;pL z+qa7P4d`Jp0_3;D0)bBqR4Bs6FHirq0Z-UYjYpzBXA_1 zLWIHWxHUc*Eg!CG9p+{N;AE(taYuAx_{tEqbG!1B<+0aAW>9(X8qK+a0APdC9^$A1 z%jJ}r&K}NYjIB(&axfAyFJ45>Qzu@ysRuc7NkuJzCZe2wevxLXL^}u%Lq%M3ev#pt z+d;FtBL^k@kh!eh=idkB?U1LYfuzpYCuecc=>~rU0jvAPXPuza>C=A!kZU+77;7dI zvBg+Hr?!{828$xc6h)4@WrYANI}GZ1I+<#nRZ-8A+tacv-nxHJ_Ffnt`xK%JQbrD) z($UKtmRjfaS~UYiS<=#h%XU~u2}(i=+w2>a32Q<*G{3N8JRGinB2aW9dif@qPhTW+ z$FHXL{d5HKSFQb*)~B_aPQg+CC_c)&kxLCIKua?eG+PM+rFF(5Kb_Amw%cuc>|2&vK8Zt9k+SE~r0j*; zp^NVBom0-YO!jwBm*xv*hw%X@$#bws=FKH$YZtN%m-L_n4;QP5Fqep2kX$L9 z1NP1q9QutSJdn&IfCFr3ig2(w!`h2torOT>rOpvE+f)rWq+Qeyd~RWm0*{R?06|+z z2jSc0T)c23w+?hdUQEN=yLV~Dm&w7z%@@$HY|9Pb^1Ocd`0Ed{I%*A8qwz^@34Ewm z^*;idKLBoDJbV6~WutNPv=4tk&TtdIRd!wKXJEfu^1sOyDBN8ipAOew=Efa%%eM9P zwO9#%a0=`hHLCHAKq=(9;lAEo$i(1>q9+`n$@yx!RQ6je20u5Yz{KMvo;|vFESqTn zDs0sm@EOl0!;VMlNhXdLbkbgF_Fg{m>YP*B?oy2tc|~r>n?|G*xiJetjF?nWT4)}q@{Lk$U7l~1F3tUZ0EGvNvcpP0P|(KaHkMLqjtr^4_}dN{&S z2KC1vu}?tOfFoI@kd9#U+?GrjTNRMY>0^GhDP#5Rez2XgXtR!*Vm$-C;h7sp_B!Tg zNv9CbGB-gu&Y_yLucy}>qsGwqVn(uSpd|}nrYp5pjw7sw_^5MHNp*Ztjb?L$=Ut0<<`0krNxDVMKd)b zq5K`>>c5%Aw2l(tj!Vz1bM@Gsh}HdMeY91!iKLB2Z?p8>CW4Ju7Ow(I1D|X|%$Ca7|vyk{e0KOBBrx)5*mq&1l%zSK-0iFhSP%2}EV)hfdZS z6H`mWmKd9?v$d!?_gp?zY9%I6U|tx%yAu2R4uPF8f#}nECj%9k3m2k3BV$6@7wv9< zUBSs`tX04&`mxnN{c3CIN+$~=z{cF$QU_3VZ3O?q!A-AJzVfqRb(TZ;K`IpY-ogK0 zHFowc_by>nr;62sdWG23LtKdmP~vlm1*RHGP3zmB*%SPHyIt_^PbMlzBn*kXP?ic? zMvCU>-MgrP20xdVa8Mp2?HAz4PBsNZZqT81a)u2w>68F%U&33aMK2=Oa&fqG2Y&iw zhz}U_k!QDBUf7`)m{(njLvc(iA?Z=nfnvGv`qUIjx6Dh zrlLeutvxArB-~r9e&*wJGX4JLv&ZQvkRQ}n?O3#`4E*)eKfQkV^6A6t!*}7qj!U8H zmv6T{pq0H{-g0|DF?;)R+X3jhp{>{3%cOsc>!YmGFTZ+(Lg=$6F}owc2bSL9gS@Ao zJ(1Q7$th--Kd42ms6nleeLgumJ;V|ig?M8a&EJeNu6SEl9A~P=l9DhKK=IG2)?x`f z6ihx}P5ch^&goi;)$Ig_3)!eBq3{+C3`OFnZvf{gA5Q`6H4z}i6dq}fvHi(1J)H^( ztCf;<#-D)x&xh*U;6i==^FUbk13NiAO3!a8f`Z1g(ZzHr+wvD`N*}r9SvGx4*s3wo zVi<00u!6Vv#Dpyh6B!*(@uhwwFXjb3Ib$>2!z4AH0}I%ja7v?R*npyeoX5dM9CYEo zdJ6$4ftD~@e}~5>6G5;%K75^iJw2~2KoX7@yIuUNw_mSoYhXzzIR;n&s7dm%&dr_3 zG*n@Qpgt-UM9tB|mx0X@;2q8mb1f7?&>WN^|An{1hHun#;@^nhH`0W)PRKw?mGD4*h4qj4d!YUis25 zhEuZ#ejs!mqLxR?GM(A2#`3&kRB6kflj%7bB`Eur?tNnnP%6Dbhr>YF$xP4t@W%qL z)?gV2$8m6I=5xt)y{tEKzZ@5SIkX3lO1>9qrV_=_yXe^x-PVzzjq%GWT@Z82cP`Wv zoAd=ey7L`2N%=6AZ5xy%MpXO;o!~_&0<#KVrwe8;gmDLy1ZKJDWuV!LcfomIb_6@H zFTq|8%!65N68m@t^uA7C9v{}=gK4A1=Vtpaw|8p0qvp}xWdB|7vhMr*hj!AMo=?XF zMXxEt*&!CFuan8~&$xR6AOSpukBg-}U3yq7-QrT1V7~!c1f~0Ebt2;)C#$SR=F#z( zzCDJmyxPF18U-x)w-L3ueO6{T%`%{+$Zii*kLX?RDAjInd z5I03^9xY*N!|>p6Hk$t=EjeBNo=&q2jyi4Ex$wL<6e7=N8C)}hY!dpS$c9)G`e|MG z!HBB~gb%JjaSUKR!I>Qu>5XSoYR1o1%I)~i7Px?ugV74D`Smwx)31La%YL(hY2WXl zZtmS6Zv7*#CtRK&grvu4(g4JYm-(vq#pmn^yr#0@6rnWcatuu6)+iVT6=X^hagB+q z?9xAMKTO@hp2%{}@`kNoh{a6~V`l;bIS3v1WIjg2*W627+)*y#1-cPA+)F1(b_z6- zpxVoDINg50ewN0r#>DN)_L|Jl_Nb?39P@Fw#USAjJnWSL}WQ0 z%}_0PFdB#A8m}gX+XlRryNN$05tM9^xe0q^Ey{ItcpH3AOCoNAfIVK~z;F$LFHr3X z8sp#%;Z(E}68KT-Y!jBFs>@bIpREt%w3TyQ>4*anjxfWn3Uu8ro zmeWc{x_MM^pc2h3*C_`q)3*9%4=gzI#{4 zLIGQDsKfyLB;G zRgTsoXBi%PJz#IB)Uv;Ts@NBBj@jy&a6O37jN?Jjm0Dk{fSg=gvM_M_O<$&|wCs6| zrXw}=BUzH5g+Dq0f)Fb*x`neKH7Q z!xNl6(GS5ITp>g<4mykj+1`#y{N(93PhUR`aqS9$hsz@Rt_0^HGwa~@EXS4DW!V1z M1Nbs_X6-rw00Qs^$p8QV literal 19860 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переформировать список устройств
ждите примерно минуту, а затем обновите страницу и список появится вновь", + + "SetUDPUpdateList":"Переформировать список устройств", + "SetUDPUpdatePage":"Обновить страницу", + "SetUDPNameOfDev":"Имя этого устройства:", + "SetUDPDateExchange":"Включить обмен данными между устройствами", + "SetUDPWarn2":"Если обмен данными включен, то устройства будут обмениваться широковещательными пакетами udp для формирования списка устройств и для осуществления посылки настроек mqtt. Данный обмен создает дополнительную нагрузку на wifi сеть.", + + "SetWiFiNameOfDev":"Имя устройства:", + "SetWiFiRouterConnect":"Подключение к WiFi роутеру:", + "SetWiFiAccessPoint":"Точка доступа:", + "SetWiFiWeb":"Логин и пароль web interface:", + "SetWiFiTimeZone":"Временная зона:", + "SetWiFiNTP":"Сервер NTP:", + "SetWiFiWarn1":"Имя устройства должно состоять из английских букв и иметь длинну от 6 до 12 символов", + "SetWiFiWarn2":"После того как вы введете логин пароль от вашего wifi роутера необходимо нажать кнопку сохранить, а затем обязательно нажать кнопку перезагрузить устройство внизу этой страницы", + "SetWiFiWarn3":"Устройство постоянно сканирует сеть на наличие wifi. Если роутер отключен, то устройство автоматически перейдет в режим точки доступа. Когда wifi появится устройство автоматически подключится к роутеру снова, и выключит точку доступа", + "SetWiFiWarn4":"После изменения поля NTP сервер необходимо перезагрузить устройство", + "SetWiFiWarn5":"Светодиод статуса подключения показывает четыре состояния подключения:
1. мигает редко - идет подключение к wifi
2. мигает часто - идет подключение к серверу mqtt
3. горит постоянно - модуль в режиме точки доступа,
4. не горит - модуль подключен к wifi и к mqtt.
Светодиод подключен к gpio2. Если галочка стоит - то использовать этот пин нельзя", + + "SetMQTTServerName":"Имя сервера:", + "SetMQTTPort":"Номер порта:", + "SetMQTTPrefix":"Префикс:", + "SetMQTTUserName":"Имя пользователя:", + "SetMQTTPassword":"Пароль:", + + "SetMQTTSendSettings":"Отправить настройки MQTT с этого устройства на все остальные", + "SetMQTTWarn1":"Обратите внимание что поле префикс может состоять только из одного слова и одного разделителя: /prefix, вариант вида: /prefix1/prefix2 работать не будет. После изменения поля prefix необходимо перезагрузить устройство", + "SetMQTTWarn2":"Прежде чем нажимать на кнопку Отправить настройки MQTT сохрание их, если Вы их меняли. Настройки получат и перезапишут все устройства в локальной сети" +} \ No newline at end of file diff --git a/data/mqtt.json b/data/mqtt.json deleted file mode 100644 index 0bd4acc5..00000000 --- a/data/mqtt.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "configs": [ - "/config.setup.json" - ], - "class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6", - "content": [ - { - "type": "h5", - "title": "{{name}}", - "class": "alert-warning" - }, - { - "type": "text", - "class": "alert alert-warning", - "title": "Обратите внимание что поле prefix может состоять только из одного слова и одного разделителя: /prefix, вариант вида: /prefix1/prefix2 работать не будет. После изменения поля prefix необходимо перезагрузить устройство" - }, - { - "type": "h4", - "title": "Server name:" - }, - { - "type": "input", - "title": "", - "name": "1", - "state": "{{mqttServer}}" - }, - { - "type": "h4", - "title": "Port:" - }, - { - "type": "input", - "title": "", - "name": "2", - "state": "{{mqttPort}}" - }, - { - "type": "h4", - "title": "Prefix:" - }, - { - "type": "input", - "title": "", - "name": "3", - "state": "{{mqttPrefix}}" - }, - { - "type": "h4", - "title": "User name:" - }, - { - "type": "input", - "title": "", - "name": "4", - "state": "{{mqttUser}}" - }, - { - "type": "h4", - "title": "Password:" - }, - { - "type": "input", - "title": "", - "name": "5", - "state": "{{mqttPass}}" - }, - { - "type": "h3", - "name": "my-block", - "style": "position:fixed;top:30%;left:50%;width:400px;margin-left:-200px;text-align:center;", - "class": "hidden" - }, - { - "type": "text", - "class": "alert alert-warning", - "title": "Прежде чем нажимать на кнопку 'Отправить настройки MQTT' сохрание их, если Вы их меняли. Настройки получат и перезапишут все устройства в локальной сети" - }, - { - "type": "button", - "title": "Сохранить", - "action": "mqttSave?mqttServer=[[1]]&mqttPort=[[2]]&mqttPrefix=[[3]]&mqttUser=[[4]]&mqttPass=[[5]]", - "class": "btn btn-block btn-success" - }, - { - "type": "button", - "title": "Отправить настройки MQTT с этого устройства на все остальные", - "action": "udp?arg=2", - "class": "btn btn-block btn-success" - }, - - { - "type": "button", - "title": "Проверить соединение с MQTT", - "action": "mqttCheck", - "response": "[[my-block]]", - "class": "btn btn-block btn-success" - }, - { - "type": "link", - "title": "Перезагрузить устройство", - "action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/restart?device=ok');}", - "class": "btn btn-block btn-success" - }, - { - "type": "link", - "title": "Главная", - "action": "/", - "class": "btn btn-block btn-danger btn-sm" - } - ] -} \ No newline at end of file diff --git a/data/pushingbox.json b/data/pushingbox.json deleted file mode 100644 index eac5a080..00000000 --- a/data/pushingbox.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "configs": [ -"/config.setup.json" - ], - "class":"col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6", - "content": [ - { - "type": "h5", - "title": "{{name}}", - "class":"alert-warning" - }, - { - "type": "h4", - "title": "Device id:" - }, -{ - "type": "input", - "title": "", - "name":"1", - "state": "{{pushingbox_id}}" - }, - -{ - "type": "button", - "title":"Сохранить", - "action": "pushingboxDate?pushingbox_id=[[1]]", - "class": "btn btn-block btn-success", - "style": "width:100%;display:inline" - }, -{ - "type": "hr" - }, - { - "type": "link", - "title": "Перезагрузить устройство", - "action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/restart?device=ok');}", - "class": "btn btn-block btn-warning" - }, - { - "type": "link", - "title": "Главная", - "action": "/", - "class": "btn btn-block btn-danger btn-sm" - } - ] -} diff --git a/data/set.device.json b/data/set.device.json new file mode 100644 index 00000000..7236fb0c --- /dev/null +++ b/data/set.device.json @@ -0,0 +1,143 @@ +{ + "configs": [ + "/config.setup.json", + "/config.option.json", + "/config.live.json", + "/lang/lang.ru.json" + ], + "class": "col-sm-offset-1 col-sm-10", + "content": [ + { + "type": "h5", + "title": "{{name}}", + "class": "alert-default" + }, + { + "type": "link", + "title": "{{ButMainPage}}", + "action": "/", + "class": "btn btn-block btn-default" + }, + { + "type": "hr" + }, + { + "type": "h4", + "title": "Device ID: {{chipID}}" + }, + { + "type": "h4", + "title": "IP address: {{ip}}" + }, + { + "type": "h4", + "title": "Time: {{time}}" + }, + { + "type": "h4", + "title": "Uptime: {{uptime}}" + }, + { + "type": "h4", + "title": "Build version: {{firmware_version}}" + }, + { + "type": "h4", + "title": "SPIFFS version: 2.3.4" + }, + { + "type": "hr" + }, + { + "type": "dropdown", + "name": "help-url", + "class": "btn btn-default", + "style": "display:inline", + "title": { + "#": "{{SetDevPreset}}", + "/set?preset=1": "1.Вкл. выкл. локального реле", + "/set?preset=2": "2.Вкл. выкл. локального реле в определенное время", + "/set?preset=3": "3.Вкл. выкл. локального реле на определенный период времени", + "/set?preset=4": "4.Вкл. выкл. нескольких локальных реле кнопкой в приложении", + "/set?preset=5": "5.Вкл. выкл. локального реле физической кнопкой и кнопкой в приложении параллельно (для выключателя света)", + "/set?preset=6": "6.Вкл. выкл. нескольких удаленных реле кнопкой в приложении (нужно указать Device ID)", + "/set?preset=7": "7.Вкл. выкл. нескольких удаленных реле физической кнопкой (нужно указать Device ID)", + "/set?preset=8": "8.Широтно импульсная модуляция", + "/set?preset=9": "9.Сенсор DHT11 (темп, влажность) и логгирование", + "/set?preset=10": "10.Сенсор DHT22, DHT33, DHT44, AM2302, RHT03 (темп, влажность) и логгирование", + "/set?preset=11": "11.Аналоговый сенсор и логгирование", + "/set?preset=12": "12.Cенсор bmp280 (темп, давление) и логгирование", + "/set?preset=13": "13.Cенсор bme280 (темп, давление, влажность, высота) и логгирование", + "/set?preset=14": "12.Сенсор DS18B20 (темп) и логгирование", + "/set?preset=15": "13.Термостат на DS18B20 с переключением в ручной режим и логгированием", + "/set?preset=16": "14.Котроль уровня в баке (датчик расстояния) на сенсорах: JSN-SR04T, HC-SR04, HY-SRF05 и логгирование", + "/set?preset=17": "15.Датчик движения включающий свет", + "/set?preset=18": "16.Охранный датчик движения", + "/set?preset=19": "17.Система управления шаговыми двигателями на основе драйвера A4988 (открытие закрытие штор)", + "/set?preset=20": "18.Система управления сервоприводами", + "/set?preset=21": "Настройки по умолчанию" + } + }, + { + "type": "h2", + "title": "{{SetDevConf}}" + }, + { + "type": "file", + "state": "firmware.c.txt", + "style": "width:100%;height:350px", + "title": "Сохранить", + "action": "/set?devinit", + "class": "btn btn-block btn-default" + }, + { + "type": "h2", + "title": "Сценарии" + }, + { + "type": "checkbox", + "name": "scen", + "title": "Включить сценарии", + "action": "/set?scen=[[scen]]", + "state": "{{scen}}" + }, + { + "type": "file", + "state": "firmware.s.txt", + "style": "width:100%;height:350px", + "title": "Сохранить", + "action": "/set?sceninit", + "class": "btn btn-block btn-default" + }, + + { + "type": "link", + "title": "Инструкция к системе автоматизации", + "action": "https://github.com/DmitryBorisenko33/esp32-esp8266_iot-manager_modules_firmware/wiki/Instruction", + "class": "btn btn-block btn-default" + }, + { + "type": "link", + "title": "Очистить логи сенсоров", + "action": "/set?cleanlog", + "class": "btn btn-block btn-default" + }, + { + "type": "hr" + }, + { + "type": "h3", + "name": "my-block", + "style": "position:fixed;top:50%;left:50%;width:400px;margin-left:-200px;text-align:center;", + "class": "hidden" + }, + + { + "type": "button", + "title": "Обновить прошивку устройства", + "action": "/check", + "response": "[[my-block]]", + "class": "btn btn-block btn-default" + } + ] +} \ No newline at end of file diff --git a/data/set.mqtt.json b/data/set.mqtt.json new file mode 100644 index 00000000..a088c2dc --- /dev/null +++ b/data/set.mqtt.json @@ -0,0 +1,133 @@ +{ + "configs": [ + "/config.setup.json", + "/lang/lang.ru.json" + ], + "class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6", + "content": [ + { + "type": "h5", + "title": "{{name}}", + "class": "alert-default" + + }, + { + "type": "link", + "title": "{{ButMainPage}}", + "action": "/", + "class": "btn btn-block btn-default" + }, + { + "type": "hr" + }, + + { + "type": "h4", + "title": "{{SetMQTTServerName}}", + "style": "width:60%;float:left;" + }, + { + "type": "input", + "title": "", + "name": "mqttServer-arg", + "state": "{{mqttServer}}", + "style": "width:40%;float:right" + }, + { + "type": "h4", + "title": "{{SetMQTTPort}}", + "style": "width:60%;float:left;" + }, + { + "type": "input", + "title": "", + "name": "mqttPort-arg", + "state": "{{mqttPort}}", + "style": "width:40%;float:right" + }, + { + "type": "h4", + "title": "{{SetMQTTPrefix}}", + "style": "width:60%;float:left;" + }, + { + "type": "input", + "title": "", + "name": "mqttPrefix-arg", + "state": "{{mqttPrefix}}", + "style": "width:40%;float:right" + }, + { + "type": "h4", + "title": "{{SetMQTTUserName}}", + "style": "width:60%;float:left;" + }, + { + "type": "input", + "title": "", + "name": "mqttUser-arg", + "state": "{{mqttUser}}", + "style": "width:40%;float:right" + }, + { + "type": "h4", + "title": "{{SetMQTTPassword}}", + "style": "width:60%;float:left;" + }, + { + "type": "input", + "title": "", + "name": "mqttPass-arg", + "state": "{{mqttPass}}", + "style": "width:40%;float:right" + }, + { + "type": "h3", + "name": "my-block", + "style": "position:fixed;top:30%;left:50%;width:400px;margin-left:-200px;text-align:center;", + "class": "hidden" + }, + + { + "type": "button", + "title": "{{ButSave}}", + "style": "width:100%;float:left;", + "action": "set?mqttServer=[[mqttServer-arg]]&mqttPort=[[mqttPort-arg]]&mqttPrefix=[[mqttPrefix-arg]]&mqttUser=[[mqttUser-arg]]&mqttPass=[[mqttPass-arg]]", + "class": "btn btn-block btn-default" + }, + { + "type": "button", + "style": "width:100%;float:left;", + "title": "{{SetMQTTSendSettings}}", + "action": "set?mqttsend", + "class": "btn btn-block btn-default" + }, + + { + "type": "button", + "style": "width:100%;float:left;", + "title": "Проверить соединение с MQTT", + "action": "set?mqttcheck", + "response": "[[my-block]]", + "class": "btn btn-block btn-default" + }, + { + "type": "text", + "style": "width:100%;float:left;", + "title": "

{{SetMQTTWarn1}}

" + + }, + { + "type": "text", + "style": "width:100%;float:left;", + "title": "

{{SetMQTTWarn2}}

" + }, + { + "type": "link", + "style": "width:100%;float:left;", + "title": "Перезагрузить устройство", + "action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/restart?device=ok');}", + "class": "btn btn-block btn-danger" + } + ] +} \ No newline at end of file diff --git a/data/set.push.json b/data/set.push.json new file mode 100644 index 00000000..555797e4 --- /dev/null +++ b/data/set.push.json @@ -0,0 +1,51 @@ +{ + "configs": [ + "/config.setup.json", + "/lang/lang.ru.json" + ], + "class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6", + "content": [ + { + "type": "h5", + "title": "{{name}}", + "class": "alert-default" + }, + { + "type": "link", + "title": "{{ButMainPage}}", + "action": "/", + "class": "btn btn-block btn-default" + }, + { + "type": "hr" + }, + { + "type": "h4", + "style": "width:60%;float:left;", + "title": "Device id:" + }, + { + "type": "input", + "title": "", + "name": "push-arg", + "style": "width:40%;float:right", + "state": "{{pushingboxid}}" + }, + { + "type": "button", + "title": "{{ButSave}}", + "action": "set?pushingboxid=[[push-arg]]", + "class": "btn btn-block btn-default", + "style": "width:100%;display:inline" + }, + { + "type": "hr" + }, + { + "type": "link", + "title": "Перезагрузить устройство", + "action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/restart?device=ok');}", + "class": "btn btn-block btn-danger" + } + ] +} \ No newline at end of file diff --git a/data/set.udp.json b/data/set.udp.json new file mode 100644 index 00000000..6bea3042 --- /dev/null +++ b/data/set.udp.json @@ -0,0 +1,96 @@ +{ + "configs": [ + "/config.setup.json", + "/lang/lang.ru.json" + ], + "title": "Главная", + "class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6", + "content": [ + { + "type": "h5", + "title": "{{name}}", + "class": "alert-default" + }, + { + "type": "link", + "title": "{{ButMainPage}}", + "action": "/", + "class": "btn btn-block btn-default" + }, + { + "type": "hr" + }, + { + "type": "h3", + "title": "{{SetUDPList}}" + }, + { + "type": "hr" + }, + { + "type": "csv", + "title": [ + "html", + "html", + "html" + ], + "state": "dev.csv", + "style": "width:100%;", + "class": "nan" + }, + { + "type": "hr" + }, + { + "type": "link", + "title": "{{SetUDPUpdateList}}", + "action": "/set?updatelist", + "class": "btn btn-block btn-default" + }, + { + "type": "link", + "title": "{{SetUDPUpdatePage}}", + "action": "/set?updatepage", + "class": "btn btn-block btn-default" + }, + { + "type": "hr" + }, + { + "type": "text", + "title": "

{{SetUDPWarn1}}

", + "style": "width:100%;float:left;" + }, + { + "type": "h3", + "title": "{{SetUDPNameOfDev}}" + }, + { + "type": "input", + "title": "{{SetUDPNameOfDev}}", + "name": "devname-arg", + "state": "{{name}}", + "pattern": "[A-Za-z0-9]{6,12}" + }, + { + "type": "button", + "title": "{{ButSave}}", + "action": "/set?devname=[[devname-arg]]", + "class": "btn btn-block btn-default" + }, + { + "type": "hr" + }, + { + "type": "checkbox", + "name": "udponoff", + "title": "{{SetUDPDateExchange}}", + "action": "/set?udponoff=[[udponoff]]", + "state": "{{udponoff}}" + }, + { + "type": "text", + "title": "

{{SetUDPWarn2}}

" + } + ] +} \ No newline at end of file diff --git a/data/utilities.json b/data/set.utilities.json similarity index 70% rename from data/utilities.json rename to data/set.utilities.json index ee82a0c0..92769f85 100644 --- a/data/utilities.json +++ b/data/set.utilities.json @@ -1,7 +1,8 @@ { "configs": [ "/config.live.json", - "/config.setup.json" + "/config.setup.json", + "/lang/lang.ru.json" ], "title": "Главная", "class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6", @@ -9,7 +10,13 @@ { "type": "h5", "title": "{{name}}", - "class": "alert-warning" + "class": "alert-default" + }, + { + "type": "link", + "title": "{{ButMainPage}}", + "action": "/", + "class": "btn btn-block btn-default" }, { "type": "hr" @@ -25,17 +32,8 @@ { "type": "link", "title": "Сканировать", - "action": "/init?arg=5", - "class": "btn btn-block btn-success" - }, - { - "type": "hr" - }, - { - "type": "link", - "title": "Главная", - "action": "/", - "class": "btn btn-block btn-danger" + "action": "/set?itoc", + "class": "btn btn-block btn-default" } ] } \ No newline at end of file diff --git a/data/set.wifi.json b/data/set.wifi.json new file mode 100644 index 00000000..d68edc7f --- /dev/null +++ b/data/set.wifi.json @@ -0,0 +1,185 @@ +{ + "configs": [ + "/config.setup.json", + "/lang/lang.ru.json" + ], + "title": "Конфигурация", + "class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6", + "content": [ + { + "type": "h5", + "title": "{{name}}", + "class": "alert-default" + }, + { + "type": "link", + "title": "{{ButMainPage}}", + "action": "/", + "class": "btn btn-block btn-default" + }, + { + "type": "hr" + }, + { + "type": "h3", + "title": "{{SetWiFiNameOfDev}}" + }, + { + "type": "input", + "title": "{{SetWiFiNameOfDev}}", + "name": "devname-arg", + "state": "{{name}}", + "pattern": "[A-Za-z0-9]{6,12}" + }, + { + "type": "button", + "title": "{{ButSave}}", + "action": "set?devname=[[devname-arg]]", + "class": "btn btn-block btn-default" + }, + { + "type": "text", + "title": "

{{SetWiFiWarn1}}

" + }, + { + "type": "hr" + }, + { + "type": "h3", + "title": "{{SetWiFiRouterConnect}}" + }, + { + "type": "input", + "title": "", + "name": "routerssid-arg", + "state": "{{routerssid}}" + }, + { + "type": "password", + "title": "", + "name": "routerpass-arg", + "state": "{{routerpass}}" + }, + { + "type": "button", + "title": "{{ButSave}}", + "class": "btn btn-block btn-default", + "action": "set?routerssid=[[routerssid-arg]]&routerpass=[[routerpass-arg]]" + }, + { + "type": "text", + "title": "

{{SetWiFiWarn2}}

" + }, + { + "type": "hr" + }, + { + "type": "checkbox", + "name": "blink", + "title": "Включить светодиод статуса подключения", + "action": "/set?blink=[[blink]]", + "state": "{{blink}}" + }, + { + "type": "text", + "title": "

{{SetWiFiWarn5}}

" + }, + { + "type": "hr" + }, + { + "type": "h3", + "title": "{{SetWiFiAccessPoint}}" + }, + { + "type": "input", + "title": "", + "name": "apssid-arg", + "state": "{{apssid}}", + "pattern": ".{1,20}" + }, + { + "type": "password", + "title": "", + "name": "appass-arg", + "state": "{{appass}}", + "pattern": ".{8,20}" + }, + { + "type": "button", + "title": "{{ButSave}}", + "action": "set?apssid=[[apssid-arg]]&appass=[[appass-arg]]", + "class": "btn btn-block btn-default" + }, + { + "type": "text", + "title": "

{{SetWiFiWarn3}}

" + }, + { + "type": "hr" + }, + { + "type": "h3", + "title": "{{SetWiFiWeb}}" + }, + { + "type": "input", + "title": "Логин", + "name": "weblogin-arg", + "state": "{{weblogin}}", + "pattern": ".{1,20}" + }, + { + "type": "password", + "title": "Пароль", + "name": "webpass-arg", + "state": "{{webpass}}", + "pattern": ".{1,20}" + }, + { + "type": "button", + "title": "{{ButSave}}", + "action": "set?weblogin=[[weblogin-arg]]&webpass=[[webpass-arg]]", + "class": "btn btn-block btn-default" + }, + { + "type": "hr" + }, + { + "type": "h3", + "title": "{{SetWiFiTimeZone}}" + }, + { + "type": "input", + "title": "", + "name": "timezone-arg", + "state": "{{timezone}}", + "pattern": ".{1,20}" + }, + { + "type": "input", + "title": "", + "name": "ntp-arg", + "state": "{{ntp}}" + }, + { + "type": "button", + "title": "{{ButSave}}", + "action": "set?timezone=[[timezone-arg]]&ntp=[[ntp-arg]]", + "class": "btn btn-block btn-default" + }, + { + "type": "text", + "title": "

{{SetWiFiWarn4}}

" + }, + { + "type": "hr" + }, + { + "type": "link", + "title": "Перезагрузить устройство", + "action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/set?device=ok');}", + "class": "btn btn-block btn-danger" + } + ] +} \ No newline at end of file diff --git a/data/setup.json b/data/setup.json deleted file mode 100644 index 18ebf108..00000000 --- a/data/setup.json +++ /dev/null @@ -1,162 +0,0 @@ -{ - "configs": [ - "/config.setup.json" - ], - "title": "Конфигурация", - "class": "col-sm-offset-1 col-sm-10 col-md-offset-2 col-md-8 col-lg-offset-3 col-lg-6", - "content": [ - { - "type": "h5", - "title": "{{name}}", - "class": "alert-warning" - }, - { - "type": "link", - "title": "Главная", - "action": "/", - "class": "btn btn-block btn-danger" - }, - { - "type": "hr" - }, - { - "type": "h2", - "title": "Имя устройства" - }, - { - "type": "input", - "title": "Имя устройства", - "name": "dev_name", - "state": "{{name}}", - "pattern": "[A-Za-z0-9]{6,12}" - }, - { - "type": "button", - "title": "Сохранить", - "action": "name?arg=[[dev_name]]", - "class": "btn btn-block btn-success" - }, - { - "type": "hr" - }, - { - "type": "h2", - "title": "Подключение к Wi-Fi роутеру" - }, - { - "type": "input", - "title": "Сеть", - "name": "ssid", - "state": "{{ssid}}" - }, - { - "type": "password", - "title": "Введите пароль", - "name": "ssidPass", - "state": "{{password}}" - }, - { - "type": "button", - "title": "Сохранить", - "class": "btn btn-block btn-success", - "action": "ssid?ssid=[[ssid]]&password=[[ssidPass]]" - }, - { - "type": "hr" - }, - { - "type": "h2", - "title": "Точка доступа" - }, - { - "type": "input", - "title": "Имя WI-FI сети", - "name": "ssidap", - "state": "{{ssidAP}}", - "pattern": ".{1,20}" - }, - { - "type": "password", - "title": "Пароль", - "name": "ssidApPass", - "state": "{{passwordAP}}", - "pattern": ".{8,20}" - }, - { - "type": "button", - "title": "Сохранить", - "action": "ssidap?ssidAP=[[ssidap]]&passwordAP=[[ssidApPass]]", - "class": "btn btn-block btn-success" - }, - { - "type": "hr" - }, - { - "type": "h2", - "title": "Логин и пароль web interface" - }, - { - "type": "input", - "title": "Логин", - "name": "web-login", - "state": "{{web_login}}", - "pattern": ".{1,20}" - }, - { - "type": "password", - "title": "Пароль", - "name": "web-pass", - "state": "{{web_pass}}", - "pattern": ".{1,20}" - }, - { - "type": "button", - "title": "Сохранить", - "action": "web?web_login=[[web-login]]&web_pass=[[web-pass]]", - "class": "btn btn-block btn-success" - }, - { - "type": "hr" - }, - { - "type": "h2", - "title": "Временная зона" - }, - { - "type": "input", - "title": "Временная зона", - "name": "1", - "state": "{{timezone}}", - "pattern": ".{1,20}" - }, - { - "type": "input", - "title": "Название ntp сервера", - "name": "2", - "state": "{{ntp}}" - }, - { - "type": "button", - "title": "Сохранить", - "action": "time?timezone=[[1]]&ntp=[[2]]", - "class": "btn btn-block btn-success" - }, - { - "type": "hr" - }, - { - "type": "text", - "class": "alert alert-warning", - "title": "После изменения поля 'NTP сервер' необходимо перезагрузить устройство" - }, - { - "type": "hr" - }, - { - "type": "link", - "title": "Перезагрузить устройство", - "action": "javascript:if(confirm(renameBlock(jsonResponse,'Перезагрузить?'))){send_request(this,'/restart?device=ok');}", - "class": "btn btn-block btn-warning" - } - ] -} \ No newline at end of file diff --git a/data/widgets/outstanding/widget.select.json b/data/widgets/outstanding/widget.select.json new file mode 100644 index 00000000..c6531b70 --- /dev/null +++ b/data/widgets/outstanding/widget.select.json @@ -0,0 +1,7 @@ +{ + "widget" : "select", + "size" : "small", + "fill" : "outline", + "options" : "["Zero item", "First item", "Second item"]", + "status" : 2 +} \ No newline at end of file diff --git a/include/Consts.h b/include/Consts.h index c9ef6d63..30c750ae 100644 --- a/include/Consts.h +++ b/include/Consts.h @@ -1,4 +1,5 @@ #pragma once +//Здесь хранятся все настройки прошивки #define firmware_version "2.3.3" diff --git a/include/Global.h b/include/Global.h index 331d95cd..5bf3e39c 100644 --- a/include/Global.h +++ b/include/Global.h @@ -1,21 +1,27 @@ #pragma once +//=========ПОДКЛЮЧЕНИЕ ОБЩИХ БИБЛИОТЕК=============== #include #include #include #include +extern AsyncWebServer server; #include #include #include #include #include #include - #include "Consts.h" - -/* -* ESP8266 -*/ +#include +#include "GyverFilters.h" +#include +#include +#include +#include +#include +#include +//==============ESP8266 БИБЛИОТЕКИ=============== #ifdef ESP8266 #include #include @@ -29,10 +35,7 @@ WiFiUDP Udp; #include #endif #endif - -/* -* ESP32 -*/ +//==============ESP32 БИБЛИОТЕКИ=============== #ifdef ESP32 #include #include @@ -55,9 +58,63 @@ extern Servo myServo2; #include #endif + + +//==============================Objects.h(без данных)================================== + +#ifdef WS_enable +extern AsyncWebSocket ws; +#endif + +//extern AsyncEventSource events; + +extern TickerScheduler ts; +enum {ROUTER_SEARCHING, WIFI_MQTT_CONNECTION_CHECK, SENSORS, STEPPER1, STEPPER2, LOG1, LOG2, LOG3, LOG4, LOG5, TIMER_COUNTDOWN, TIME, TIME_SYNC, STATISTICS, UPTIME, UDP, UDP_DB, TEST }; + +extern WiFiClient espClient; + +extern PubSubClient client_mqtt; + +extern StringCommand sCmd; + extern AsyncWebServer server; -// Global vars +//AsyncWebSocket ws; + +//AsyncEventSource events; + +#define NUM_BUTTONS +extern boolean but[NUM_BUTTONS]; +extern Bounce * buttons; + +extern GMedian<10, int> medianFilter; + +extern OneWire *oneWire; +extern DallasTemperature sensors; + +extern DHTesp dht; + +extern Adafruit_BMP280 bmp; +extern Adafruit_Sensor *bmp_temp; +extern Adafruit_Sensor *bmp_pressure; + +extern Adafruit_BME280 bme; +extern Adafruit_Sensor *bme_temp; +extern Adafruit_Sensor *bme_pressure; +extern Adafruit_Sensor *bme_humidity; + +uptime_interval myUpTime; + +///////////////////////////////////// Global vars //////////////////////////////////////////////////////////////////// + +extern boolean udp_busy; +extern unsigned int udp_port; +extern IPAddress udp_multicastIP; +extern String received_ip; +extern String received_udp_line; +extern int udp_period; + + extern boolean just_load; extern const char *hostName; @@ -107,83 +164,10 @@ extern boolean udp_data_parse; extern boolean mqtt_send_settings_to_udp; extern boolean i2c_scanning; -#ifdef WS_enable -extern AsyncWebSocket ws; -#endif - -extern AsyncEventSource events; - extern int sensors_reading_map[15]; -enum { - ROUTER_SEARCHING, - WIFI_MQTT_CONNECTION_CHECK, - SENSORS, - STEPPER1, - STEPPER2, - LOG1, - LOG2, - LOG3, - LOG4, - LOG5, - TIMER_COUNTDOWN, - TIME, - TIME_SYNC, - STATISTICS, - UDP, - UDP_DB, - TEST -}; -extern TickerScheduler ts; - -extern WiFiClient espClient; -extern PubSubClient client_mqtt; -extern StringCommand sCmd; - -#define NUM_BUTTONS 6 -extern boolean but[NUM_BUTTONS]; -extern Bounce *buttons; - -extern boolean udp_busy; -extern unsigned int udp_port; -extern IPAddress udp_multicastIP; -extern String received_ip; -extern String received_udp_line; -extern int udp_period; - -#ifdef level_enable -#include "GyverFilters.h" -extern GMedian<10, int> medianFilter; -#endif - -#include -#include -extern OneWire *oneWire; -extern DallasTemperature sensors; - -#include -extern DHTesp dht; - -#include - -#ifdef bmp_enable -#include -extern Adafruit_BMP280 bmp; -extern Adafruit_Sensor *bmp_temp; -extern Adafruit_Sensor *bmp_pressure; -#endif - -#ifdef bme_enable -#include -extern Adafruit_BME280 bme; -extern Adafruit_Sensor *bme_temp; -extern Adafruit_Sensor *bme_pressure; -extern Adafruit_Sensor *bme_humidity; -#endif - -//#include -//SoftwareSerial mySerial(14, 12); +///////////////////////////////////// Functions//////////////////////////////////////////////////////////////////// // StringUtils extern uint8_t hexStringToUint8(String hex); @@ -381,4 +365,10 @@ extern void handleButton(); extern void handleScenario(); extern void handleUdp(); extern void do_upgrade_url(); -extern void do_upgrade(); \ No newline at end of file +extern void do_upgrade(); + +//uptime +extern void handle_uptime(); +extern void handle_statistics(); +extern void uptime_init(); +extern void web_init(); \ No newline at end of file diff --git a/lib/Arduino-UpTime/Changelog b/lib/Arduino-UpTime/Changelog new file mode 100644 index 00000000..16c1e045 --- /dev/null +++ b/lib/Arduino-UpTime/Changelog @@ -0,0 +1,2 @@ +0.01 2019-01-14 + - initial version diff --git a/lib/Arduino-UpTime/Makefile b/lib/Arduino-UpTime/Makefile new file mode 100644 index 00000000..3d0fb738 --- /dev/null +++ b/lib/Arduino-UpTime/Makefile @@ -0,0 +1,15 @@ +all: README examples/UpTime_tick/README examples/UpTime_synopsis/README + +clean: + rm -f README README.bak \ + examples/UpTime_tick/README examples/UpTime_tick/README.bak \ + examples/UpTime_synopsis/README examples/UpTime_synopsis/README.bak + +README: UpTime.h + pod2readme $< $@ && rm -f $@.bak + +examples/UpTime_tick/README: examples/UpTime_tick/UpTime_tick.ino + pod2readme $< $@ && rm -f $@.bak + +examples/UpTime_synopsis/README: examples/UpTime_synopsis/UpTime_synopsis.ino + pod2readme $< $@ && rm -f $@.bak diff --git a/lib/Arduino-UpTime/README b/lib/Arduino-UpTime/README new file mode 100644 index 00000000..6a3fa83c --- /dev/null +++ b/lib/Arduino-UpTime/README @@ -0,0 +1,99 @@ +NAME + + UpTime.h - Arduino uptime and events in seconds + +SYNOPSIS + + #include + #include // https://github.com/jozef/Arduino-UpTime + + uptime_interval fire2(2); + uptime_interval fire5(5,UPTIME_RIGHT_AWAY); + + void setup () { + Serial.begin(9600); + } + + void loop () { + Serial.println("uptime: "+uptime_as_string()+" or "+uptime()+"s"); + if (fire2.check()) Serial.println("2s elapsed"); + if (fire5.check()) Serial.println("5s elapsed"); + delay(1400); + } + + will output: + + uptime: 00:00:00 or 0s + 5s elapsed + uptime: 00:00:01 or 1s + uptime: 00:00:02 or 2s + 2s elapsed + uptime: 00:00:04 or 4s + 2s elapsed + uptime: 00:00:05 or 5s + 5s elapsed + uptime: 00:00:07 or 7s + 2s elapsed + uptime: 00:00:08 or 8s + 2s elapsed + uptime: 00:00:09 or 9s + uptime: 00:00:11 or 11s + 2s elapsed + 5s elapsed + … + uptime: 04:41:23 or 16883s + uptime: 04:41:25 or 16885s + 2s elapsed + 5s elapsed + uptime: 04:41:26 or 16886s + 2s elapsed + uptime: 04:41:28 or 16888s + 2s elapsed + uptime: 04:41:29 or 16889s + uptime: 04:41:30 or 16890s + 2s elapsed + 5s elapsed + +DESCRIPTION + + Uptime class is made to to track uptime of Arduino in seconds. The + uptime() or check() functions has to be called at least once for 0xFFFF + seconds (once in 18h) to work. Seconds will be counted even after + Arduinos millis() overrun and the seconds of unsigned long are enough + to not overrun sooner then in 136+ years. Once 0xFFFF0000 seconds is + elapsed, will trigger reset so that Arduino program clearly starts all + over again. + +METHODS + + bool check() + + Returns true/false if the interval elapset. + + void reset(bool postpone = true) + + Will reset the time to count from current moment in until interval. If + postpone is set to false, check() will return true with next call. + +INSTALL + + git clone https://github.com/jozef/Arduino-UpTime sketchbook/libraries/UpTime + +EXAMPLES + + examples/UpTime_tick/UpTime_synopsis.ino + + synopsis section example + + examples/UpTime_tick/UpTime_tick.ino + + print formatted and raw uptime in seconds und 4x interval + +LICENSE + + This is free software, licensed under the MIT License. + +AUTHOR + + Jozef Kutej + diff --git a/lib/Arduino-UpTime/UpTime.cpp b/lib/Arduino-UpTime/UpTime.cpp new file mode 100644 index 00000000..846638af --- /dev/null +++ b/lib/Arduino-UpTime/UpTime.cpp @@ -0,0 +1,65 @@ +/* see UpTime.h */ + +#include +#include + +unsigned long _uptime_seconds = 0; +void (*time_to_die)(void) = 0; // reset Arduino after 136+ years + +unsigned long uptime() { + unsigned int cur_second = millis() / 1000; + unsigned int _uptime_seconds_uint = _uptime_seconds; + + while (_uptime_seconds_uint != cur_second) { + _uptime_seconds++; + _uptime_seconds_uint++; + if (_uptime_seconds > 0xFFFF0000) time_to_die(); + } + + return _uptime_seconds; +} + +uptime_interval::uptime_interval(unsigned int inte, bool postpone) : interval(inte) { + reset(postpone); +} + +bool uptime_interval::check() { + if (next <= uptime()) { + next += interval; + return true; + } + return false; +} + +void uptime_interval::reset(bool postpone) { + next = (postpone ? _uptime_seconds + interval : _uptime_seconds); +} + +String _uptime_two_dig(uint8_t x) { + if (x > 9) { + return String(x); + } + else { + return "0"+String(x); + } +} + +String uptime_as_string() { + unsigned long tmp_uptime = uptime(); + unsigned long seconds; + unsigned long minutes; + unsigned long hours; + unsigned long days; + seconds = tmp_uptime % 60; + tmp_uptime = tmp_uptime / 60; + + minutes = tmp_uptime % 60; + tmp_uptime = tmp_uptime / 60; + hours = tmp_uptime % 24; + days = tmp_uptime / 24; + + return (days ? String(days)+'d'+' ' : "") + + _uptime_two_dig(hours) + + ':' + _uptime_two_dig(minutes) + + ':' + _uptime_two_dig(seconds); +} diff --git a/lib/Arduino-UpTime/UpTime.h b/lib/Arduino-UpTime/UpTime.h new file mode 100644 index 00000000..e643a99c --- /dev/null +++ b/lib/Arduino-UpTime/UpTime.h @@ -0,0 +1,124 @@ +/* VERSION 0.01; 14.1.2019; see below for description and documentation */ +#ifndef UpTime_h +#define UpTime_h + +#define UPTIME_RIGHT_AWAY false + +unsigned long uptime(); +String uptime_as_string(); + +class uptime_interval { + private: + unsigned long next; + unsigned int interval; + public: + uptime_interval(unsigned int inte, bool postpone = true); + bool check(); + void reset(bool postpone = true); +}; + +#endif + +/* + +=head1 NAME + + UpTime.h - Arduino uptime and events in seconds + +=head1 SYNOPSIS + + #include + #include // https://github.com/jozef/Arduino-UpTime + + uptime_interval fire2(2); + uptime_interval fire5(5,UPTIME_RIGHT_AWAY); + + void setup () { + Serial.begin(9600); + } + + void loop () { + Serial.println("uptime: "+uptime_as_string()+" or "+uptime()+"s"); + if (fire2.check()) Serial.println("2s elapsed"); + if (fire5.check()) Serial.println("5s elapsed"); + delay(1400); + } + +will output: + + uptime: 00:00:00 or 0s + 5s elapsed + uptime: 00:00:01 or 1s + uptime: 00:00:02 or 2s + 2s elapsed + uptime: 00:00:04 or 4s + 2s elapsed + uptime: 00:00:05 or 5s + 5s elapsed + uptime: 00:00:07 or 7s + 2s elapsed + uptime: 00:00:08 or 8s + 2s elapsed + uptime: 00:00:09 or 9s + uptime: 00:00:11 or 11s + 2s elapsed + 5s elapsed + … + uptime: 04:41:23 or 16883s + uptime: 04:41:25 or 16885s + 2s elapsed + 5s elapsed + uptime: 04:41:26 or 16886s + 2s elapsed + uptime: 04:41:28 or 16888s + 2s elapsed + uptime: 04:41:29 or 16889s + uptime: 04:41:30 or 16890s + 2s elapsed + 5s elapsed + +=head1 DESCRIPTION + +Uptime class is made to to track uptime of Arduino in seconds. The uptime() +or check() functions has to be called at least once for 0xFFFF seconds +(once in 18h) to work. Seconds will be counted even after Arduinos +millis() overrun and the seconds of unsigned long are enough to not overrun +sooner then in 136+ years. Once 0xFFFF0000 seconds is elapsed, will trigger +reset so that Arduino program clearly starts all over again. + +=head1 METHODS + +=head2 bool check() + +Returns true/false if the interval elapset. + +=head2 void reset(bool postpone = true) + +Will reset the time to count from current moment in until interval. If +C is set to false, check() will return true with next call. + +=head1 INSTALL + + git clone https://github.com/jozef/Arduino-UpTime sketchbook/libraries/UpTime + +=head1 EXAMPLES + +=head2 examples/UpTime_tick/UpTime_synopsis.ino + +synopsis section example + +=head2 examples/UpTime_tick/UpTime_tick.ino + +print formatted and raw uptime in seconds und 4x interval + +=head1 LICENSE + +This is free software, licensed under the MIT License. + +=head1 AUTHOR + + Jozef Kutej + +=cut + +*/ diff --git a/lib/Arduino-UpTime/examples/UpTime_synopsis/README b/lib/Arduino-UpTime/examples/UpTime_synopsis/README new file mode 100644 index 00000000..6640df09 --- /dev/null +++ b/lib/Arduino-UpTime/examples/UpTime_synopsis/README @@ -0,0 +1,4 @@ +DESCRIPTION + + synopsis section example from UpTime.h + diff --git a/lib/Arduino-UpTime/examples/UpTime_synopsis/UpTime_synopsis.ino b/lib/Arduino-UpTime/examples/UpTime_synopsis/UpTime_synopsis.ino new file mode 100644 index 00000000..f6ad1bb1 --- /dev/null +++ b/lib/Arduino-UpTime/examples/UpTime_synopsis/UpTime_synopsis.ino @@ -0,0 +1,24 @@ +/* +=head1 DESCRIPTION + +synopsis section example from UpTime.h + +=cut +*/ + +#include +#include // https://github.com/jozef/Arduino-UpTime + +uptime_interval fire2(2); +uptime_interval fire5(5,UPTIME_RIGHT_AWAY); + +void setup () { + Serial.begin(9600); +} + +void loop () { + Serial.println("uptime: "+uptime_as_string()+" or "+uptime()+"s"); + if (fire2.check()) Serial.println("2s elapsed"); + if (fire5.check()) Serial.println("5s elapsed"); + delay(1400); +} diff --git a/lib/Arduino-UpTime/examples/UpTime_tick/README b/lib/Arduino-UpTime/examples/UpTime_tick/README new file mode 100644 index 00000000..34869144 --- /dev/null +++ b/lib/Arduino-UpTime/examples/UpTime_tick/README @@ -0,0 +1,11 @@ +NAME + + UpTime_tick.ino - print formatted and raw uptime in seconds und 4x + interval + +DESCRIPTION + + On serial port will print current uptime in seconds with 4 interval + checks. Each loop has random 0-5s delay. Intervals will be printed once + elapsed. + diff --git a/lib/Arduino-UpTime/examples/UpTime_tick/UpTime_tick.ino b/lib/Arduino-UpTime/examples/UpTime_tick/UpTime_tick.ino new file mode 100644 index 00000000..f532c5c8 --- /dev/null +++ b/lib/Arduino-UpTime/examples/UpTime_tick/UpTime_tick.ino @@ -0,0 +1,52 @@ +/* + +=head1 NAME + +UpTime_tick.ino - print formatted and raw uptime in seconds und 4x interval + +=head1 DESCRIPTION + +On serial port will print current uptime in seconds with 4 interval checks. +Each loop has random 0-5s delay. Intervals will be printed once elapsed. + +=cut + +*/ + +#include +#include // https://github.com/jozef/Arduino-UpTime + +uptime_interval fire2(2); +uptime_interval fire5(5); +uptime_interval fire10(10, UPTIME_RIGHT_AWAY); +uptime_interval fire60(60, UPTIME_RIGHT_AWAY); + +void setup () { + Serial.begin(9600); + while (Serial.available()) { Serial.read(); } + randomSeed(analogRead(0)); +} + +void loop () { + Serial.print("uptime: "); + Serial.println(uptime_as_string()); + + if (fire2.check()) { + Serial.println("fire 2s"); + } + if (fire5.check()) { + Serial.println("fire 5s"); + } + if (fire10.check()) { + Serial.println("fire 10s"); + } + if (fire60.check()) { + Serial.println("fire 60s"); + } + + int rand_delay = random(5000); + Serial.print("delay("); + Serial.print(rand_delay); + Serial.println(")"); + delay(rand_delay); +} diff --git a/src/Cmd.cpp b/src/Cmd.cpp index 2390ccb7..8a792241 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -2,573 +2,545 @@ #include "push_pushingbox.h" -void CMD_init() -{ - sCmd.addCommand("button", button); - sCmd.addCommand("buttonSet", buttonSet); - sCmd.addCommand("buttonChange", buttonChange); +void CMD_init() { - sCmd.addCommand("pinSet", pinSet); - sCmd.addCommand("pinChange", pinChange); + sCmd.addCommand("button", button); + sCmd.addCommand("buttonSet", buttonSet); + sCmd.addCommand("buttonChange", buttonChange); - sCmd.addCommand("pwm", pwm); - sCmd.addCommand("pwmSet", pwmSet); + sCmd.addCommand("pinSet", pinSet); + sCmd.addCommand("pinChange", pinChange); - sCmd.addCommand("switch", switch_); + sCmd.addCommand("pwm", pwm); + sCmd.addCommand("pwmSet", pwmSet); + + sCmd.addCommand("switch", switch_); #ifdef analog_enable - sCmd.addCommand("analog", analog); + sCmd.addCommand("analog", analog); #endif #ifdef level_enable - sCmd.addCommand("levelPr", levelPr); - sCmd.addCommand("ultrasonicCm", ultrasonicCm); + sCmd.addCommand("levelPr", levelPr); + sCmd.addCommand("ultrasonicCm", ultrasonicCm); #endif #ifdef dallas_enable - sCmd.addCommand("dallas", dallas); + sCmd.addCommand("dallas", dallas); #endif #ifdef dht_enable - sCmd.addCommand("dhtT", dhtT); - sCmd.addCommand("dhtH", dhtH); - sCmd.addCommand("dhtPerception", dhtP); - sCmd.addCommand("dhtComfort", dhtC); - sCmd.addCommand("dhtDewpoint", dhtD); + sCmd.addCommand("dhtT", dhtT); + sCmd.addCommand("dhtH", dhtH); + sCmd.addCommand("dhtPerception", dhtP); + sCmd.addCommand("dhtComfort", dhtC); + sCmd.addCommand("dhtDewpoint", dhtD); #endif #ifdef bmp_enable - sCmd.addCommand("bmp280T", bmp280T); - sCmd.addCommand("bmp280P", bmp280P); + sCmd.addCommand("bmp280T", bmp280T); + sCmd.addCommand("bmp280P", bmp280P); #endif #ifdef bme_enable - sCmd.addCommand("bme280T", bme280T); - sCmd.addCommand("bme280P", bme280P); - sCmd.addCommand("bme280H", bme280H); - sCmd.addCommand("bme280A", bme280A); + sCmd.addCommand("bme280T", bme280T); + sCmd.addCommand("bme280P", bme280P); + sCmd.addCommand("bme280H", bme280H); + sCmd.addCommand("bme280A", bme280A); #endif #ifdef stepper_enable - sCmd.addCommand("stepper", stepper); - sCmd.addCommand("stepperSet", stepperSet); + sCmd.addCommand("stepper", stepper); + sCmd.addCommand("stepperSet", stepperSet); #endif #ifdef servo_enable - sCmd.addCommand("servo", servo_); - sCmd.addCommand("servoSet", servoSet); + sCmd.addCommand("servo", servo_); + sCmd.addCommand("servoSet", servoSet); #endif #ifdef serial_enable - sCmd.addCommand("serialBegin", serialBegin); - sCmd.addCommand("serialWrite", serialWrite); + sCmd.addCommand("serialBegin", serialBegin); + sCmd.addCommand("serialWrite", serialWrite); #endif #ifdef logging_enable - sCmd.addCommand("logging", logging); + sCmd.addCommand("logging", logging); #endif - sCmd.addCommand("inputDigit", inputDigit); - sCmd.addCommand("digitSet", digitSet); + sCmd.addCommand("inputDigit", inputDigit); + sCmd.addCommand("digitSet", digitSet); - sCmd.addCommand("inputTime", inputTime); - sCmd.addCommand("timeSet", timeSet); + sCmd.addCommand("inputTime", inputTime); + sCmd.addCommand("timeSet", timeSet); - sCmd.addCommand("timerStart", timerStart_); - sCmd.addCommand("timerStop", timerStop_); + sCmd.addCommand("timerStart", timerStart_); + sCmd.addCommand("timerStop", timerStop_); - sCmd.addCommand("text", text); - sCmd.addCommand("textSet", textSet); + sCmd.addCommand("text", text); + sCmd.addCommand("textSet", textSet); - sCmd.addCommand("mqtt", mqttOrderSend); - sCmd.addCommand("http", httpOrderSend); + sCmd.addCommand("mqtt", mqttOrderSend); + sCmd.addCommand("http", httpOrderSend); #ifdef push_enable - sCmd.addCommand("push", pushControl); + sCmd.addCommand("push", pushControl); #endif - sCmd.addCommand("firmwareUpdate", firmwareUpdate); - sCmd.addCommand("firmwareVersion", firmwareVersion); + sCmd.addCommand("firmwareUpdate", firmwareUpdate); + sCmd.addCommand("firmwareVersion", firmwareVersion); - handle_time_init(); + handle_time_init(); } -void button() -{ - String button_number = sCmd.next(); - String button_param = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String start_state = sCmd.next(); - String page_number = sCmd.next(); - jsonWriteStr(configOptionJson, "button_param" + button_number, button_param); - jsonWriteStr(configLiveJson, "button" + button_number, start_state); - if (isDigitStr(button_param)) - { - pinMode(button_param.toInt(), OUTPUT); - digitalWrite(button_param.toInt(), start_state.toInt()); +//========================================================================================================== +//==========================================Модуль кнопок=================================================== +void button() { + + String button_number = sCmd.next(); + String button_param = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String start_state = sCmd.next(); + String page_number = sCmd.next(); + + jsonWriteStr(configOptionJson, "button_param" + button_number, button_param); + jsonWriteStr(configLiveJson, "button" + button_number, start_state); + + if (isDigitStr (button_param)) { + pinMode(button_param.toInt(), OUTPUT); + digitalWrite(button_param.toInt(), start_state.toInt()); + } + + if (button_param == "scen") { + jsonWriteStr(configSetupJson, "scen", start_state); + Scenario_init(); + saveConfig(); + } + + if (button_param.indexOf("line") != -1) { + String str = button_param; + while (str.length() != 0) { + if (str == "") return; + String tmp = selectToMarker (str, ","); //line1, + String number = deleteBeforeDelimiter(tmp, "e"); //1, + number.replace(",", ""); + Serial.println(number); + int number_int = number.toInt(); + scenario_line_status[number_int] = start_state.toInt(); + str = deleteBeforeDelimiter(str, ","); } - - if (button_param == "scenario") - { - jsonWriteStr(configSetupJson, "scenario", start_state); - Scenario_init(); - saveConfig(); - } - - if (button_param.indexOf("line") != -1) - { - String str = button_param; - while (str.length() != 0) - { - if (str == "") - return; - String tmp = selectToMarker(str, ","); //line1, - String number = deleteBeforeDelimiter(tmp, "e"); //1, - number.replace(",", ""); - Serial.println(number); - int number_int = number.toInt(); - scenario_line_status[number_int] = start_state.toInt(); - str = deleteBeforeDelimiter(str, ","); - } - } - createWidget(widget_name, page_name, page_number, "widgets/widget.toggle.json", "button" + button_number); + } + createWidget (widget_name, page_name, page_number, "widgets/widget.toggle.json", "button" + button_number); } -void buttonSet() -{ - String button_number = sCmd.next(); - String button_state = sCmd.next(); - String button_param = jsonReadStr(configOptionJson, "button_param" + button_number); +void buttonSet() { - if (button_param != "na" || button_param != "scenario" || button_param.indexOf("line") != -1) - { - digitalWrite(button_param.toInt(), button_state.toInt()); + String button_number = sCmd.next(); + String button_state = sCmd.next(); + String button_param = jsonReadStr(configOptionJson, "button_param" + button_number); + + if (button_param != "na" || button_param != "scen" || button_param.indexOf("line") != -1) { + digitalWrite(button_param.toInt(), button_state.toInt()); + } + + if (button_param == "scen") { + jsonWriteStr(configSetupJson, "scen", button_state); + Scenario_init(); + saveConfig(); + } + + if (button_param.indexOf("line") != -1) { + String str = button_param; + while (str.length() != 0) { + if (str == "") return; + String tmp = selectToMarker (str, ","); //line1, + String number = deleteBeforeDelimiter(tmp, "e"); //1, + number.replace(",", ""); + Serial.println(number); + int number_int = number.toInt(); + scenario_line_status[number_int] = button_state.toInt(); + str = deleteBeforeDelimiter(str, ","); } + } - if (button_param == "scenario") - { - jsonWriteStr(configSetupJson, "scenario", button_state); - Scenario_init(); - saveConfig(); - } + eventGen ("button", button_number); - if (button_param.indexOf("line") != -1) - { - String str = button_param; - while (str.length() != 0) - { - if (str == "") - return; - String tmp = selectToMarker(str, ","); //line1, - String number = deleteBeforeDelimiter(tmp, "e"); //1, - number.replace(",", ""); - Serial.println(number); - int number_int = number.toInt(); - scenario_line_status[number_int] = button_state.toInt(); - str = deleteBeforeDelimiter(str, ","); - } - } - - eventGen("button", button_number); - - jsonWriteStr(configLiveJson, "button" + button_number, button_state); - sendSTATUS("button" + button_number, button_state); + jsonWriteStr(configLiveJson, "button" + button_number, button_state); + sendSTATUS("button" + button_number, button_state); } -void buttonChange() -{ - String button_number = sCmd.next(); - String current_state = jsonReadStr(configLiveJson, "button" + button_number); - if (current_state == "1") - { - current_state = "0"; - } - else if (current_state == "0") - { - current_state = "1"; - } - order_loop += "buttonSet " + button_number + " " + current_state + ","; - jsonWriteStr(configLiveJson, "button" + button_number, current_state); - sendSTATUS("button" + button_number, current_state); +void buttonChange() { + String button_number = sCmd.next(); + String current_state = jsonReadStr(configLiveJson, "button" + button_number); + if (current_state == "1") { + current_state = "0"; + } else if (current_state == "0") { + current_state = "1"; + } + order_loop += "buttonSet " + button_number + " " + current_state + ","; + jsonWriteStr(configLiveJson, "button" + button_number, current_state); + sendSTATUS("button" + button_number, current_state); } -void pinSet() -{ - String pin_number = sCmd.next(); - String pin_state = sCmd.next(); - pinMode(pin_number.toInt(), OUTPUT); - digitalWrite(pin_number.toInt(), pin_state.toInt()); +void pinSet() { + String pin_number = sCmd.next(); + String pin_state = sCmd.next(); + pinMode(pin_number.toInt(), OUTPUT); + digitalWrite(pin_number.toInt(), pin_state.toInt()); } -void pinChange() -{ - String pin_number = sCmd.next(); - pinMode(pin_number.toInt(), OUTPUT); - digitalWrite(pin_number.toInt(), !digitalRead(pin_number.toInt())); +void pinChange() { + String pin_number = sCmd.next(); + pinMode(pin_number.toInt(), OUTPUT); + digitalWrite(pin_number.toInt(), !digitalRead(pin_number.toInt())); +} +//================================================================================================================== +//==========================================Модуль управления ШИМ=================================================== +void pwm() { + + static boolean flag = true; + String pwm_number = sCmd.next(); + String pwm_pin = sCmd.next(); + String widget_name = sCmd.next(); + widget_name.replace("#", " "); + String page_name = sCmd.next(); + String start_state = sCmd.next(); + String page_number = sCmd.next(); + + + uint8_t pwm_pin_int = pwm_pin.toInt(); + jsonWriteStr(configOptionJson, "pwm_pin" + pwm_number, pwm_pin); + pinMode(pwm_pin_int, INPUT); + analogWrite(pwm_pin_int, start_state.toInt()); + //analogWriteFreq(32000); + jsonWriteStr(configLiveJson, "pwm" + pwm_number, start_state); + + createWidget (widget_name, page_name, page_number, "widgets/widget.range.json", "pwm" + pwm_number); } -void pwm() -{ - // TODO Unused - // static boolean flag = true; - String pwm_number = sCmd.next(); - String pwm_pin = sCmd.next(); - String widget_name = sCmd.next(); - widget_name.replace("#", " "); - String page_name = sCmd.next(); - String start_state = sCmd.next(); - String page_number = sCmd.next(); +void pwmSet() { - uint8_t pwm_pin_int = pwm_pin.toInt(); - jsonWriteStr(configOptionJson, "pwm_pin" + pwm_number, pwm_pin); - pinMode(pwm_pin_int, INPUT); - analogWrite(pwm_pin_int, start_state.toInt()); - jsonWriteStr(configLiveJson, "pwm" + pwm_number, start_state); - createWidget(widget_name, page_name, page_number, "widgets/widget.range.json", "pwm" + pwm_number); -} + String pwm_number = sCmd.next(); + String pwm_state = sCmd.next(); + int pwm_state_int = pwm_state.toInt(); -void pwmSet() -{ - String pwm_number = sCmd.next(); - String pwm_state = sCmd.next(); - int pwm_state_int = pwm_state.toInt(); + int pin = jsonReadInt(configOptionJson, "pwm_pin" + pwm_number); + analogWrite(pin, pwm_state_int); - int pin = jsonReadInt(configOptionJson, "pwm_pin" + pwm_number); - analogWrite(pin, pwm_state_int); + eventGen ("pwm", pwm_number); - eventGen("pwm", pwm_number); - - jsonWriteStr(configLiveJson, "pwm" + pwm_number, pwm_state); - sendSTATUS("pwm" + pwm_number, pwm_state); + jsonWriteStr(configLiveJson, "pwm" + pwm_number, pwm_state); + sendSTATUS("pwm" + pwm_number, pwm_state); } //================================================================================================================== //==========================================Модуль физической кнопки================================================ -void switch_() -{ - String switch_number = sCmd.next(); - String switch_pin = sCmd.next(); - String switch_delay = sCmd.next(); +void switch_ () { - buttons[switch_number.toInt()].attach(switch_pin.toInt()); - buttons[switch_number.toInt()].interval(switch_delay.toInt()); - but[switch_number.toInt()] = true; + String switch_number = sCmd.next(); + String switch_pin = sCmd.next(); + String switch_delay = sCmd.next(); + + buttons[switch_number.toInt()].attach(switch_pin.toInt()); + buttons[switch_number.toInt()].interval(switch_delay.toInt()); + but[switch_number.toInt()] = true; } -void handleButton() -{ - static uint8_t switch_number = 1; +void handleButton() { - if (but[switch_number]) - { - buttons[switch_number].update(); - if (buttons[switch_number].fell()) - { - eventGen("switch", String(switch_number)); + static uint8_t switch_number = 1; - jsonWriteStr(configLiveJson, "switch" + String(switch_number), "1"); - } - if (buttons[switch_number].rose()) - { - eventGen("switch", String(switch_number)); + if (but[switch_number]) { + buttons[switch_number].update(); + if (buttons[switch_number].fell()) { - jsonWriteStr(configLiveJson, "switch" + String(switch_number), "0"); - } + eventGen ("switch", String(switch_number)); + + jsonWriteStr(configLiveJson, "switch" + String(switch_number), "1"); } - switch_number++; - if (switch_number == NUM_BUTTONS) - switch_number = 0; -} + if (buttons[switch_number].rose()) { -void inputDigit() -{ - String value_name = sCmd.next(); - String number = value_name.substring(5); - String widget_name = sCmd.next(); - widget_name.replace("#", " "); - String page_name = sCmd.next(); - page_name.replace("#", " "); - String start_state = sCmd.next(); - String page_number = sCmd.next(); - jsonWriteStr(configLiveJson, "digit" + number, start_state); - createWidget(widget_name, page_name, page_number, "widgets/widget.inputNum.json", "digit" + number); -} + eventGen ("switch", String(switch_number)); -void digitSet() -{ - String number = sCmd.next(); - String value = sCmd.next(); - jsonWriteStr(configLiveJson, "digit" + number, value); - sendSTATUS("digit" + number, value); -} - -void inputTime() -{ - String value_name = sCmd.next(); - String number = value_name.substring(4); - String widget_name = sCmd.next(); - widget_name.replace("#", " "); - String page_name = sCmd.next(); - page_name.replace("#", " "); - String start_state = sCmd.next(); - String page_number = sCmd.next(); - jsonWriteStr(configLiveJson, "time" + number, start_state); - createWidget(widget_name, page_name, page_number, "widgets/widget.inputTime.json", "time" + number); -} - -void timeSet() -{ - String number = sCmd.next(); - String value = sCmd.next(); - jsonWriteStr(configLiveJson, "time" + number, value); - sendSTATUS("time" + number, value); -} - -void handle_time_init() -{ - ts.add( - TIME, 1000, [&](void *) { - String tmp = GetTime(); - jsonWriteStr(configLiveJson, "time", tmp); - tmp.replace(":", "-"); - jsonWriteStr(configLiveJson, "timenow", tmp); - eventGen("timenow", ""); - }, - nullptr, true); -} - -void text() -{ - String number = sCmd.next(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); - String page_number = sCmd.next(); - - createWidget(widget_name, page_name, page_number, "widgets/widget.anyData.json", "text" + number); -} - -void textSet() -{ - String number = sCmd.next(); - String text = sCmd.next(); - text.replace("_", " "); - - if (text.indexOf("-time") >= 0) - { - text.replace("-time", ""); - text.replace("#", " "); - String time = GetTime(); - time.replace(":", "."); - text = text + " " + GetDataDigital() + " " + time; + jsonWriteStr(configLiveJson, "switch" + String(switch_number), "0"); } - - jsonWriteStr(configLiveJson, "text" + number, text); - sendSTATUS("text" + number, text); + } + switch_number++; + if (switch_number == 6) switch_number = 0; } +//===================================================================================================================================== +//=========================================Добавление окна ввода цифры================================================================= +void inputDigit() { + String value_name = sCmd.next(); + String number = value_name.substring(5); + String widget_name = sCmd.next(); + widget_name.replace("#", " "); + String page_name = sCmd.next(); + page_name.replace("#", " "); + String start_state = sCmd.next(); + String page_number = sCmd.next(); + jsonWriteStr(configLiveJson, "digit" + number, start_state); + createWidget (widget_name, page_name, page_number, "widgets/widget.inputNum.json", "digit" + number); +} +void digitSet() { + String number = sCmd.next(); + String value = sCmd.next(); + jsonWriteStr(configLiveJson, "digit" + number, value); + sendSTATUS("digit" + number, value); +} +//===================================================================================================================================== +//=========================================Добавление окна ввода времени=============================================================== +void inputTime() { + String value_name = sCmd.next(); + String number = value_name.substring(4); + String widget_name = sCmd.next(); + widget_name.replace("#", " "); + String page_name = sCmd.next(); + page_name.replace("#", " "); + String start_state = sCmd.next(); + String page_number = sCmd.next(); + jsonWriteStr(configLiveJson, "time" + number, start_state); + createWidget (widget_name, page_name, page_number, "widgets/widget.inputTime.json", "time" + number); +} +void timeSet() { + String number = sCmd.next(); + String value = sCmd.next(); + jsonWriteStr(configLiveJson, "time" + number, value); + sendSTATUS("time" + number, value); +} + +void handle_time_init() { + ts.add(TIME, 1000, [&](void*) { + + String tmp = GetTime(); + jsonWriteStr(configLiveJson, "time", tmp); + tmp.replace(":", "-"); + jsonWriteStr(configLiveJson, "timenow", tmp); + eventGen ("timenow", ""); + + }, nullptr, true); +} + +//===================================================================================================================================== +//=========================================Добавление текстового виджета============================================================ +void text() { + + String number = sCmd.next(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); + String page_number = sCmd.next(); + + createWidget (widget_name, page_name, page_number, "widgets/widget.anyData.json", "text" + number); +} + + +void textSet() { + + String number = sCmd.next(); + String text = sCmd.next(); + text.replace("_", " "); + + if (text.indexOf("-time") >= 0) { + text.replace("-time", ""); + text.replace("#", " "); + String time = GetTime(); + time.replace(":", "."); + text = text + " " + GetDataDigital() + " " + time; + } + + jsonWriteStr(configLiveJson, "text" + number, text); + sendSTATUS("text" + number, text); +} +//===================================================================================================================================== +//=========================================Модуль шагового мотора====================================================================== #ifdef stepper_enable //stepper 1 12 13 -void stepper() -{ - String stepper_number = sCmd.next(); - String pin_step = sCmd.next(); - String pin_dir = sCmd.next(); +void stepper() { + String stepper_number = sCmd.next(); + String pin_step = sCmd.next(); + String pin_dir = sCmd.next(); - jsonWriteStr(configOptionJson, "stepper" + stepper_number, pin_step + " " + pin_dir); - pinMode(pin_step.toInt(), OUTPUT); - pinMode(pin_dir.toInt(), OUTPUT); + jsonWriteStr(configOptionJson, "stepper" + stepper_number, pin_step + " " + pin_dir); + pinMode(pin_step.toInt(), OUTPUT); + pinMode(pin_dir.toInt(), OUTPUT); } //stepperSet 1 100 5 -void stepperSet() -{ - String stepper_number = sCmd.next(); - String steps = sCmd.next(); - jsonWriteStr(configOptionJson, "steps" + stepper_number, steps); - String stepper_speed = sCmd.next(); - String pin_step = selectToMarker(jsonReadStr(configOptionJson, "stepper" + stepper_number), " "); - String pin_dir = deleteBeforeDelimiter(jsonReadStr(configOptionJson, "stepper" + stepper_number), " "); - Serial.println(pin_step); - Serial.println(pin_dir); - if (steps.toInt() > 0) - digitalWrite(pin_dir.toInt(), HIGH); - if (steps.toInt() < 0) - digitalWrite(pin_dir.toInt(), LOW); - if (stepper_number == "1") - { - ts.add( - STEPPER1, stepper_speed.toInt(), [&](void *) { - int steps_int = abs(jsonReadInt(configOptionJson, "steps1") * 2); - static int count; - count++; - String pin_step = selectToMarker(jsonReadStr(configOptionJson, "stepper1"), " "); - digitalWrite(pin_step.toInt(), !digitalRead(pin_step.toInt())); - yield(); - if (count > steps_int) - { - digitalWrite(pin_step.toInt(), LOW); - ts.remove(STEPPER1); - count = 0; - } - }, - nullptr, true); - } - if (stepper_number == "2") - { - ts.add( - STEPPER2, stepper_speed.toInt(), [&](void *) { - int steps_int = abs(jsonReadInt(configOptionJson, "steps2") * 2); - static int count; - count++; - String pin_step = selectToMarker(jsonReadStr(configOptionJson, "stepper2"), " "); - digitalWrite(pin_step.toInt(), !digitalRead(pin_step.toInt())); - yield(); - if (count > steps_int) - { - digitalWrite(pin_step.toInt(), LOW); - ts.remove(STEPPER2); - count = 0; - } - }, - nullptr, true); - } +void stepperSet() { + String stepper_number = sCmd.next(); + String steps = sCmd.next(); + jsonWriteStr(configOptionJson, "steps" + stepper_number, steps); + String stepper_speed = sCmd.next(); + String pin_step = selectToMarker (jsonReadStr(configOptionJson, "stepper" + stepper_number), " "); + String pin_dir = deleteBeforeDelimiter (jsonReadStr(configOptionJson, "stepper" + stepper_number), " "); + Serial.println(pin_step); + Serial.println(pin_dir); + if (steps.toInt() > 0) digitalWrite(pin_dir.toInt(), HIGH); + if (steps.toInt() < 0) digitalWrite(pin_dir.toInt(), LOW); + if (stepper_number == "1") { + ts.add(STEPPER1, stepper_speed.toInt(), [&](void*) { + int steps_int = abs(jsonReadInt(configOptionJson, "steps1") * 2); + static int count; + count++; + String pin_step = selectToMarker (jsonReadStr(configOptionJson, "stepper1"), " "); + digitalWrite(pin_step.toInt(), !digitalRead(pin_step.toInt())); + yield(); + if (count > steps_int) { + digitalWrite(pin_step.toInt(), LOW); + ts.remove(STEPPER1); + count = 0; + } + }, nullptr, true); + } + if (stepper_number == "2") { + ts.add(STEPPER2, stepper_speed.toInt(), [&](void*) { + int steps_int = abs(jsonReadInt(configOptionJson, "steps2") * 2); + static int count; + count++; + String pin_step = selectToMarker (jsonReadStr(configOptionJson, "stepper2"), " "); + digitalWrite(pin_step.toInt(), !digitalRead(pin_step.toInt())); + yield(); + if (count > steps_int) { + digitalWrite(pin_step.toInt(), LOW); + ts.remove(STEPPER2); + count = 0; + } + }, nullptr, true); + } } #endif //==================================================================================================================================================== //=================================================================Сервоприводы======================================================================= #ifdef servo_enable //servo 1 13 50 Мой#сервопривод Сервоприводы 0 100 0 180 2 -void servo_() -{ - String servo_number = sCmd.next(); - String servo_pin = sCmd.next(); - String start_state = sCmd.next(); - int start_state_int = start_state.toInt(); - String widget_name = sCmd.next(); - String page_name = sCmd.next(); +void servo_() { + String servo_number = sCmd.next(); + String servo_pin = sCmd.next(); + String start_state = sCmd.next(); + int start_state_int = start_state.toInt(); + String widget_name = sCmd.next(); + String page_name = sCmd.next(); - String min_value = sCmd.next(); - String max_value = sCmd.next(); + String min_value = sCmd.next(); + String max_value = sCmd.next(); - String min_deg = sCmd.next(); - String max_deg = sCmd.next(); + String min_deg = sCmd.next(); + String max_deg = sCmd.next(); - String page_number = sCmd.next(); + String page_number = sCmd.next(); - jsonWriteStr(configOptionJson, "servo_pin" + servo_number, servo_pin); - start_state_int = map(start_state_int, min_value.toInt(), max_value.toInt(), min_deg.toInt(), max_deg.toInt()); + jsonWriteStr(configOptionJson, "servo_pin" + servo_number, servo_pin); + start_state_int = map(start_state_int, min_value.toInt(), max_value.toInt(), min_deg.toInt(), max_deg.toInt()); - if (servo_number == "1") - { + if (servo_number == "1") { #ifdef ESP8266 - myServo1.attach(servo_pin.toInt()); - myServo1.write(start_state_int); + myServo1.attach(servo_pin.toInt()); + myServo1.write(start_state_int); #endif #ifdef ESP32 - myServo1.attach(servo_pin.toInt(), 500, 2400); - myServo1.write(start_state_int); + myServo1.attach(servo_pin.toInt(), 500, 2400); + myServo1.write(start_state_int); #endif - } + } - if (servo_number == "2") - { + if (servo_number == "2") { #ifdef ESP8266 - myServo2.attach(servo_pin.toInt()); - myServo2.write(start_state_int); + myServo2.attach(servo_pin.toInt()); + myServo2.write(start_state_int); #endif #ifdef ESP32 - myServo2.attach(servo_pin.toInt(), 500, 2400); - myServo2.write(start_state_int); + myServo2.attach(servo_pin.toInt(), 500, 2400); + myServo2.write(start_state_int); #endif - } + } - jsonWriteStr(configOptionJson, "s_min_val" + servo_number, min_value); - jsonWriteStr(configOptionJson, "s_max_val" + servo_number, max_value); - jsonWriteStr(configOptionJson, "s_min_deg" + servo_number, min_deg); - jsonWriteStr(configOptionJson, "s_max_deg" + servo_number, max_deg); + jsonWriteStr(configOptionJson, "s_min_val" + servo_number, min_value); + jsonWriteStr(configOptionJson, "s_max_val" + servo_number, max_value); + jsonWriteStr(configOptionJson, "s_min_deg" + servo_number, min_deg); + jsonWriteStr(configOptionJson, "s_max_deg" + servo_number, max_deg); - jsonWriteStr(configLiveJson, "servo" + servo_number, start_state); + jsonWriteStr(configLiveJson, "servo" + servo_number, start_state); - createWidgetParam(widget_name, page_name, page_number, "widgets/widget.range.json", "servo" + servo_number, "min", min_value, "max", max_value, "k", "1"); + createWidgetParam (widget_name, page_name, page_number, "widgets/widget.range.json", "servo" + servo_number, "min", min_value, "max", max_value, "k", "1"); } -void servoSet() -{ - String servo_number = sCmd.next(); - String servo_state = sCmd.next(); - int servo_state_int = servo_state.toInt(); +void servoSet() { + String servo_number = sCmd.next(); + String servo_state = sCmd.next(); + int servo_state_int = servo_state.toInt(); - // TODO Unused - //int pin = jsonReadInt(configOptionJson, "servo_pin" + servo_number); + int pin = jsonReadInt(configOptionJson, "servo_pin" + servo_number); - servo_state_int = map(servo_state_int, - jsonReadInt(configOptionJson, "s_min_val" + servo_number), - jsonReadInt(configOptionJson, "s_max_val" + servo_number), - jsonReadInt(configOptionJson, "s_min_deg" + servo_number), - jsonReadInt(configOptionJson, "s_max_deg" + servo_number)); + servo_state_int = map(servo_state_int, + jsonReadInt(configOptionJson, "s_min_val" + servo_number), + jsonReadInt(configOptionJson, "s_max_val" + servo_number), + jsonReadInt(configOptionJson, "s_min_deg" + servo_number), + jsonReadInt(configOptionJson, "s_max_deg" + servo_number)); - if (servo_number == "1") - { + if (servo_number == "1") { #ifdef ESP8266 - myServo1.write(servo_state_int); + myServo1.write(servo_state_int); #endif #ifdef ESP32 - myServo1.write(servo_state_int); + myServo1.write(servo_state_int); #endif - } + } - if (servo_number == "2") - { + if (servo_number == "2") { #ifdef ESP8266 - myServo2.write(servo_state_int); + myServo2.write(servo_state_int); #endif #ifdef ESP32 - myServo2.write(servo_state_int); + myServo2.write(servo_state_int); #endif - } + } - eventGen("servo", servo_number); + //Serial.println(servo_state_int); - jsonWriteStr(configLiveJson, "servo" + servo_number, servo_state); - sendSTATUS("servo" + servo_number, servo_state); + eventGen ("servo", servo_number); + + jsonWriteStr(configLiveJson, "servo" + servo_number, servo_state); + sendSTATUS("servo" + servo_number, servo_state); } #endif //==================================================================================================================================================== //===================================================================================serial=========================================================== #ifdef serial_enable -void serialBegin() -{ - //String s_speed = sCmd.next(); - //String rxPin = sCmd.next(); - //String txPin = sCmd.next(); - //SoftwareSerial mySerial(rxPin.toInt(), txPin.toInt()); - //mySerial.begin(s_speed.toInt()); +void serialBegin() { + //String s_speed = sCmd.next(); + //String rxPin = sCmd.next(); + //String txPin = sCmd.next(); + //SoftwareSerial mySerial(rxPin.toInt(), txPin.toInt()); + //mySerial.begin(s_speed.toInt()); } -void serialWrite() -{ - //String text = sCmd.next(); - //mySerial.println(text); +void serialWrite() { + //String text = sCmd.next(); + //mySerial.println(text); } #endif //==================================================================================================================================================== //=================================================Глобальные команды удаленного управления=========================================================== -void mqttOrderSend() -{ - String id = sCmd.next(); - String order = sCmd.next(); +void mqttOrderSend() { - String all_line = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + id + "/order"; - client_mqtt.publish(all_line.c_str(), order.c_str(), false); + String id = sCmd.next(); + String order = sCmd.next(); + + String all_line = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + id + "/order"; + //Serial.print(all_line); + //Serial.print("->"); + //Serial.println(order); + int send_status = client_mqtt.publish (all_line.c_str(), order.c_str(), false); } -void httpOrderSend() -{ - String ip = sCmd.next(); - String order = sCmd.next(); - order.replace("_", "%20"); - String url = "http://" + ip + "/cmd?command=" + order; - getURL(url); +void httpOrderSend() { + + String ip = sCmd.next(); + String order = sCmd.next(); + order.replace("_", "%20"); + String url = "http://" + ip + "/cmd?command=" + order; + getURL(url); } void firmwareUpdate() { @@ -585,45 +557,47 @@ void firmwareVersion() { //============================================================================================================================== //============================выполнение команд (в лупе) по очереди из строки order============================================= -void handleCMD_loop() -{ - if (order_loop != "") - { - String tmp = selectToMarker(order_loop, ","); //выделяем из страки order первую команду rel 5 1, - sCmd.readStr(tmp); //выполняем первую команду - Serial.println("[ORDER] => " + order_loop); - order_loop = deleteBeforeDelimiter(order_loop, ","); //осекаем выполненную команду - } +void handleCMD_loop() { + + if (order_loop != "") { + + String tmp = selectToMarker(order_loop, ","); //выделяем из страки order первую команду rel 5 1, + sCmd.readStr(tmp); //выполняем первую команду + Serial.println("[ORDER] => " + order_loop); + order_loop = deleteBeforeDelimiter(order_loop, ","); //осекаем выполненную команду + } } -void txtExecution(String file) -{ - String command_all = readFile(file, 2048) + "\r\n"; +//======================================================================================================================================= +//======================================================================================================================================= +void txtExecution(String file) { - command_all.replace("\r\n", "\n"); - command_all.replace("\r", "\n"); + String command_all = readFile(file, 2048) + "\r\n"; - while (command_all.length() != 0) - { - String tmp = selectToMarker(command_all, "\n"); - sCmd.readStr(tmp); - command_all = deleteBeforeDelimiter(command_all, "\n"); - } - command_all = ""; + command_all.replace("\r\n", "\n"); + command_all.replace("\r", "\n"); + + while (command_all.length() != 0) { + + String tmp = selectToMarker (command_all, "\n"); + sCmd.readStr(tmp); + command_all = deleteBeforeDelimiter(command_all, "\n"); + } + command_all = ""; } -void stringExecution(String str) -{ - str = str + "\r\n"; +void stringExecution(String str) { - str.replace("\r\n", "\n"); - str.replace("\r", "\n"); + str = str + "\r\n"; - while (str.length()) - { - String tmp = selectToMarker(str, "\n"); - sCmd.readStr(tmp); + str.replace("\r\n", "\n"); + str.replace("\r", "\n"); - str = deleteBeforeDelimiter(str, "\n"); - } -} + while (str.length() != 0) { + + String tmp = selectToMarker (str, "\n"); + sCmd.readStr(tmp); + + str = deleteBeforeDelimiter(str, "\n"); + } +} \ No newline at end of file diff --git a/src/FileSystem.cpp b/src/FileSystem.cpp index 82c2ca7a..85aaac54 100644 --- a/src/FileSystem.cpp +++ b/src/FileSystem.cpp @@ -1,35 +1,40 @@ #include "Global.h" void File_system_init() { - Serial.begin(115200); - //Serial.setDebugOutput(true); - Serial.println("--------------started----------------"); - //-------------------------------------------------------------- - SPIFFS.begin(); - configSetupJson = readFile("config.json", 4096); - configSetupJson.replace(" ", ""); - configSetupJson.replace("\r\n", ""); - Serial.println(configSetupJson); - jsonWriteStr(configLiveJson, "name", jsonReadStr(configSetupJson, "name")); - jsonWriteStr(configLiveJson, "lang", jsonReadStr(configSetupJson, "lang")); + + Serial.begin(115200); + //Serial.setDebugOutput(true); + Serial.println("--------------started----------------"); + //-------------------------------------------------------------- + SPIFFS.begin(); + configSetupJson = readFile("config.json", 4096); + configSetupJson.replace(" ", ""); + configSetupJson.replace("\r\n", ""); + Serial.println(configSetupJson); + //jsonWriteStr(configLiveJson, "name", jsonReadStr(configSetupJson, "name")); + //jsonWriteStr(configLiveJson, "lang", jsonReadStr(configSetupJson, "lang")); + #ifdef ESP32 - uint32_t chipID_u = ESP.getEfuseMac(); - chipID = String(chipID_u); - jsonWriteStr(configSetupJson, "chipID", chipID); + uint32_t chipID_u = ESP.getEfuseMac(); + chipID = String(chipID_u); + jsonWriteStr(configSetupJson, "chipID", chipID); #endif #ifdef ESP8266 - chipID = String(ESP.getChipId()) + "-" + String(ESP.getFlashChipId()); - jsonWriteStr(configSetupJson, "chipID", chipID); - Serial.setDebugOutput(0); + chipID = String( ESP.getChipId() ) + "-" + String(ESP.getFlashChipId()); + jsonWriteStr(configSetupJson, "chipID", chipID); + Serial.setDebugOutput(0); #endif - jsonWriteStr(configSetupJson, "firmware_version", firmware_version); + jsonWriteStr(configSetupJson, "firmware_version", firmware_version); - prex = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipID; - Serial.println(chipID); + prex = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipID; + Serial.println(chipID); + } void get_esp_info() { + + } diff --git a/src/Global.cpp b/src/Global.cpp index 337258c6..158c2b27 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -1,23 +1,52 @@ #include "Global.h" - #include "JsonUtils.h" +//==============================Objects.cpp(с данными)================================== + +#ifdef WS_enable +AsyncWebSocket ws; +#endif + +//AsyncEventSource events; + TickerScheduler ts(TEST + 1); WiFiClient espClient; + PubSubClient client_mqtt(espClient); + StringCommand sCmd; -// Web AsyncWebServer server(80); -#ifdef WS_enable -AsyncWebSocket ws("/ws"); -#endif +//AsyncWebSocket ws("/ws"); -AsyncEventSource events("/events"); +//AsyncEventSource events("/events"); + +#define NUM_BUTTONS 6 +boolean but[NUM_BUTTONS]; +Bounce * buttons = new Bounce[NUM_BUTTONS]; + +GMedian<10, int> medianFilter; + +OneWire *oneWire; +DallasTemperature sensors; + +DHTesp dht; + +Adafruit_BMP280 bmp; +Adafruit_Sensor *bmp_temp; +Adafruit_Sensor *bmp_pressure; + +Adafruit_BME280 bme; +Adafruit_Sensor *bme_temp; +Adafruit_Sensor *bme_pressure; +Adafruit_Sensor *bme_humidity; + +uptime_interval myUpTime(10); + +////////////////////////////////////// Global vars //////////////////////////////////////////////////////////////////// -// Global vars boolean just_load = true; const char *hostName = "IoT Manager"; @@ -77,13 +106,11 @@ boolean udp_data_parse = false; boolean mqtt_send_settings_to_udp = false; boolean i2c_scanning = false; -// Servo -Servo myServo1; -Servo myServo2; + //Buttons -boolean but[NUM_BUTTONS]; -Bounce *buttons = new Bounce[NUM_BUTTONS]; +//boolean but[6]; + // Udp boolean udp_busy = false; @@ -102,24 +129,6 @@ int udp_period; // i2c String i2c_list; -OneWire *oneWire; -DallasTemperature sensors; -DHTesp dht; -#ifdef level_enable -GMedian<10, int> medianFilter; -#endif -#ifdef bmp_enable -Adafruit_BMP280 bmp; -Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor(); -Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor(); -#endif - -#ifdef bme_enable -Adafruit_BME280 bme; -Adafruit_Sensor *bme_temp = bme.getTemperatureSensor(); -Adafruit_Sensor *bme_pressure = bme.getPressureSensor(); -Adafruit_Sensor *bme_humidity = bme.getHumiditySensor(); -#endif diff --git a/src/Init.cpp b/src/Init.cpp index d0a45e8d..84db15e1 100644 --- a/src/Init.cpp +++ b/src/Init.cpp @@ -1,241 +1,103 @@ #include "Global.h" void All_init() { - server.on("/init", HTTP_GET, [](AsyncWebServerRequest* request) { - String value; - if (request->hasArg("arg")) { - value = request->getParam("arg")->value(); - } - if (value == "0") { //выкл сценариев - jsonWriteStr(configSetupJson, "scenario", value); - saveConfig(); - Scenario_init(); - request->send(200, "text/text", "OK"); - } - if (value == "1") { //вкл сценариев - jsonWriteStr(configSetupJson, "scenario", value); - saveConfig(); - Scenario_init(); - request->send(200, "text/text", "OK"); - } - if (value == "2") { //инициализация - Device_init(); - request->send(200, "text/text", "OK"); - } - if (value == "3") { -#ifdef logging_enable - clean_log_date(); -#endif - request->send(200, "text/text", "OK"); - } - if (value == "4") { - Scenario_init(); - request->send(200, "text/text", "OK"); - } - if (value == "5") { - i2c_scanning = true; - request->redirect("/?utilities"); - } - }); - - prsets_init(); - Device_init(); - Scenario_init(); - Timer_countdown_init(); + Device_init(); + Scenario_init(); + Timer_countdown_init(); } void Device_init() { - logging_value_names_list = ""; - enter_to_logging_counter = LOG1 - 1; - analog_value_names_list = ""; - enter_to_analog_counter = 0; + logging_value_names_list = ""; + enter_to_logging_counter = LOG1 - 1; - levelPr_value_name = ""; + analog_value_names_list = ""; + enter_to_analog_counter = 0; - dhtT_value_name = ""; - dhtH_value_name = ""; + levelPr_value_name = ""; + ultrasonicCm_value_name = ""; - bmp280T_value_name = ""; - bmp280P_value_name = ""; + dhtT_value_name = ""; + dhtH_value_name = ""; - bme280T_value_name = ""; - bme280P_value_name = ""; - bme280H_value_name = ""; - bme280A_value_name = ""; + bmp280T_value_name = ""; + bmp280P_value_name = ""; - int array_sz = sizeof(sensors_reading_map) / sizeof(sensors_reading_map[0]); + bme280T_value_name = ""; + bme280P_value_name = ""; + bme280H_value_name = ""; + bme280A_value_name = ""; - for (int i = 0; i < array_sz; i++) { - sensors_reading_map[i] = 0; - } + int array_sz = sizeof(sensors_reading_map) / sizeof(sensors_reading_map[0]); - for (int i = LOG1; i <= LOG5; i++) { - ts.remove(i); - } + for (int i = 0; i < array_sz; i++) { + sensors_reading_map[i] = 0; + } + + for (int i = LOG1; i <= LOG5; i++) { + ts.remove(i); + } #ifdef layout_in_ram - all_widgets = ""; + all_widgets = ""; #else - SPIFFS.remove("/layout.txt"); + SPIFFS.remove("/layout.txt"); #endif - txtExecution("firmware.c.txt"); - //outcoming_date(); + txtExecution("firmware.c.txt"); + //outcoming_date(); } +//-------------------------------сценарии----------------------------------------------------- void Scenario_init() { - if (jsonReadStr(configSetupJson, "scenario") == "1") { - scenario = readFile("firmware.s.txt", 2048); - } + if (jsonReadStr(configSetupJson, "scen") == "1") { + scenario = readFile("firmware.s.txt", 2048); + } } -void prsets_init() { - server.on("/preset", HTTP_GET, [](AsyncWebServerRequest* request) { - String value; - if (request->hasArg("arg")) { - value = request->getParam("arg")->value(); - } - if (value == "1") { - writeFile("firmware.c.txt", readFile("configs/relay.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay.s.txt", 2048)); - } - if (value == "2") { - writeFile("firmware.c.txt", readFile("configs/relay_t.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay_t.s.txt", 2048)); - } - if (value == "3") { - writeFile("firmware.c.txt", readFile("configs/relay_c.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay_c.s.txt", 2048)); - } - if (value == "4") { - writeFile("firmware.c.txt", readFile("configs/relay_s.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay_s.s.txt", 2048)); - } - if (value == "5") { - writeFile("firmware.c.txt", readFile("configs/relay_sw.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay_sw.s.txt", 2048)); - } - if (value == "6") { - writeFile("firmware.c.txt", readFile("configs/relay_br.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay_br.s.txt", 2048)); - } - if (value == "7") { - writeFile("firmware.c.txt", readFile("configs/relay_sr.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/relay_sr.s.txt", 2048)); - } - if (value == "8") { - writeFile("firmware.c.txt", readFile("configs/pwm.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/pwm.s.txt", 2048)); - } - if (value == "9") { - writeFile("firmware.c.txt", readFile("configs/dht11.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/dht11.s.txt", 2048)); - } - if (value == "10") { - writeFile("firmware.c.txt", readFile("configs/dht22.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/dht22.s.txt", 2048)); - } - if (value == "11") { - writeFile("firmware.c.txt", readFile("configs/analog.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/analog.s.txt", 2048)); - } - if (value == "12") { - writeFile("firmware.c.txt", readFile("configs/dallas.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/dallas.s.txt", 2048)); - } - if (value == "13") { - writeFile("firmware.c.txt", readFile("configs/termostat.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/termostat.s.txt", 2048)); - } - if (value == "14") { - writeFile("firmware.c.txt", readFile("configs/level.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/level.s.txt", 2048)); - } - if (value == "15") { - writeFile("firmware.c.txt", readFile("configs/moution_r.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/moution_r.s.txt", 2048)); - } - if (value == "16") { - writeFile("firmware.c.txt", readFile("configs/moution_s.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/moution_s.s.txt", 2048)); - } - if (value == "17") { - writeFile("firmware.c.txt", readFile("configs/stepper.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/stepper.s.txt", 2048)); - } - if (value == "18") { - writeFile("firmware.c.txt", readFile("configs/servo.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/servo.s.txt", 2048)); - } - if (value == "19") { - writeFile("firmware.c.txt", readFile("configs/firmware.c.txt", 2048)); - writeFile("firmware.s.txt", readFile("configs/firmware.s.txt", 2048)); - } - Device_init(); - Scenario_init(); - request->redirect("/?configuration"); - }); +void uptime_init() { + ts.add(UPTIME, 5000, [&](void*) { + handle_uptime(); + }, nullptr, true); + ts.add(STATISTICS, statistics_update, [&](void*) { + handle_statistics(); + }, nullptr, true); } -void up_time() { - uint32_t ss = millis() / 1000; - uint32_t mm = ss / 60; - uint32_t hh = mm / 60; - uint32_t dd = hh / 24; - - String out = ""; - - if (ss != 0) { - out = "[i] uptime = " + String(ss) + " sec"; - jsonWriteStr(configLiveJson, "uptime", String(ss) + " sec"); - } - if (mm != 0) { - out = "[i] uptime = " + String(mm) + " min"; - jsonWriteStr(configLiveJson, "uptime", String(mm) + " min"); - } - if (hh != 0) { - out = "[i] uptime = " + String(hh) + " hours"; - jsonWriteStr(configLiveJson, "uptime", String(hh) + " hours"); - } - if (dd != 0) { - out = "[i] uptime = " + String(dd) + " days"; - jsonWriteStr(configLiveJson, "uptime", String(dd) + " days"); - } - Serial.println(out + ", mqtt_lost_error: " + String(mqtt_lost_error) + ", wifi_lost_error: " + String(wifi_lost_error)); +void handle_uptime() { + if (myUpTime.check()) { + jsonWriteStr(configSetupJson, "uptime", uptime_as_string()); + } } -void statistics() { - if (WiFi.status() == WL_CONNECTED) { - String urls = "http://backup.privet.lv/visitors/?"; - //----------------------------------------------------------------- - urls += WiFi.macAddress().c_str(); - urls += "&"; - //----------------------------------------------------------------- +void handle_statistics() { + if (WiFi.status() == WL_CONNECTED) { + String urls = "http://backup.privet.lv/visitors/?"; + //----------------------------------------------------------------- + urls += WiFi.macAddress().c_str(); + urls += "&"; + //----------------------------------------------------------------- #ifdef ESP8266 - urls += "iot-manager_esp8266"; + urls += "iot-manager_esp8266"; #endif #ifdef ESP32 - urls += "iot-manager_esp32"; + urls += "iot-manager_esp32"; #endif - urls += "&"; + urls += "&"; + //----------------------------------------------------------------- #ifdef ESP8266 - urls += ESP.getResetReason(); + urls += ESP.getResetReason(); + //Serial.println(ESP.getResetReason()); #endif #ifdef ESP32 - urls += "Power on"; + urls += "Power on"; #endif - urls += "&"; - urls += "ver: "; - urls += String(firmware_version); - String stat = getURL(urls); - } -} - -void statistics_init() { - ts.add( - STATISTICS, statistics_update, [&](void*) { - statistics(); - }, - nullptr, true); -} + urls += "&"; + //----------------------------------------------------------------- + urls += "ver: "; + urls += String(firmware_version); + //----------------------------------------------------------------- + String stat = getURL(urls); + //Serial.println(stat); + } +} \ No newline at end of file diff --git a/src/Logging.cpp b/src/Logging.cpp index ac8c9d83..cfb6f00d 100644 --- a/src/Logging.cpp +++ b/src/Logging.cpp @@ -6,141 +6,125 @@ void sendLogData(String file, String topic); //===============================================Логирование============================================================ //logging temp1 1 10 Температура Датчики 2 void logging() { - String value_name = sCmd.next(); - String period_min = sCmd.next(); - String maxCount = sCmd.next(); - String widget_name = sCmd.next(); - widget_name.replace("#", " "); - String page_name = sCmd.next(); - String page_number = sCmd.next(); - logging_value_names_list += value_name + ","; - // считаем количество входов в эту функцию - enter_to_logging_counter++; - //создаем в файловой системе переменную количества точек на графике с отметкой _c что значит count - jsonWriteStr(configOptionJson, value_name + "_c", maxCount); - - //создаем график в приложении с топиком _ch /prefix/3234045-1589487/value_name_ch - createChart(widget_name, page_name, page_number, "widgets/widget.chart.json", value_name + "_ch", maxCount); - if (enter_to_logging_counter == LOG1) { - ts.add( - LOG1, period_min.toInt() * 1000 * 60, [&](void*) { - String tmp_buf_1 = selectFromMarkerToMarker(logging_value_names_list, ",", 0); - deleteOldDate("log." + tmp_buf_1 + ".txt", jsonReadInt(configOptionJson, tmp_buf_1 + "_c"), jsonReadStr(configLiveJson, tmp_buf_1)); - Serial.println("[i] LOGGING for sensor '" + tmp_buf_1 + "' done"); - }, - nullptr, false); - } - if (enter_to_logging_counter == LOG2) { - ts.add( - LOG2, period_min.toInt() * 1000 * 60, [&](void*) { - String tmp_buf_2 = selectFromMarkerToMarker(logging_value_names_list, ",", 1); - deleteOldDate("log." + tmp_buf_2 + ".txt", jsonReadInt(configOptionJson, tmp_buf_2 + "_c"), jsonReadStr(configLiveJson, tmp_buf_2)); - Serial.println("[i] LOGGING for sensor '" + tmp_buf_2 + "' done"); - }, - nullptr, false); - } - if (enter_to_logging_counter == LOG3) { - ts.add( - LOG3, period_min.toInt() * 1000 * 60, [&](void*) { - String tmp_buf_3 = selectFromMarkerToMarker(logging_value_names_list, ",", 2); - deleteOldDate("log." + tmp_buf_3 + ".txt", jsonReadInt(configOptionJson, tmp_buf_3 + "_c"), jsonReadStr(configLiveJson, tmp_buf_3)); - Serial.println("[i] LOGGING for sensor '" + tmp_buf_3 + "' done"); - }, - nullptr, false); - } - if (enter_to_logging_counter == LOG4) { - ts.add( - LOG4, period_min.toInt() * 1000 * 60, [&](void*) { - String tmp_buf_4 = selectFromMarkerToMarker(logging_value_names_list, ",", 3); - deleteOldDate("log." + tmp_buf_4 + ".txt", jsonReadInt(configOptionJson, tmp_buf_4 + "_c"), jsonReadStr(configLiveJson, tmp_buf_4)); - Serial.println("[i] LOGGING for sensor '" + tmp_buf_4 + "' done"); - }, - nullptr, false); - } - if (enter_to_logging_counter == LOG5) { - ts.add( - LOG5, period_min.toInt() * 1000 * 60, [&](void*) { - String tmp_buf_5 = selectFromMarkerToMarker(logging_value_names_list, ",", 4); - deleteOldDate("log." + tmp_buf_5 + ".txt", jsonReadInt(configOptionJson, tmp_buf_5 + "_c"), jsonReadStr(configLiveJson, tmp_buf_5)); - Serial.println("[i] LOGGING for sensor '" + tmp_buf_5 + "' done"); - }, - nullptr, false); - } + String value_name = sCmd.next(); + String period_min = sCmd.next(); + String maxCount = sCmd.next(); + String widget_name = sCmd.next(); + widget_name.replace("#", " "); + String page_name = sCmd.next(); + String page_number = sCmd.next(); + logging_value_names_list += value_name + ","; + enter_to_logging_counter++; //считаем количество входов в эту функцию + jsonWriteStr(configOptionJson, value_name + "_c", maxCount); //создаем в файловой системе переменную количества точек на графике с отметкой _c что значит count + createChart (widget_name, page_name, page_number, "widgets/widget.chart.json", value_name + "_ch", maxCount); //создаем график в приложении с топиком _ch /prefix/3234045-1589487/value_name_ch + if (enter_to_logging_counter == LOG1) { + ts.add(LOG1, period_min.toInt() * 1000 * 60, [&](void*) { + String tmp_buf_1 = selectFromMarkerToMarker(logging_value_names_list, ",", 0); + deleteOldDate("log." + tmp_buf_1 + ".txt", jsonReadInt(configOptionJson, tmp_buf_1 + "_c"), jsonReadStr(configLiveJson, tmp_buf_1)); + Serial.println("[i] LOGGING for sensor '" + tmp_buf_1 + "' done"); + }, nullptr, false); + } + if (enter_to_logging_counter == LOG2) { + ts.add(LOG2, period_min.toInt() * 1000 * 60, [&](void*) { + String tmp_buf_2 = selectFromMarkerToMarker(logging_value_names_list, ",", 1); + deleteOldDate("log." + tmp_buf_2 + ".txt", jsonReadInt(configOptionJson, tmp_buf_2 + "_c"), jsonReadStr(configLiveJson, tmp_buf_2)); + Serial.println("[i] LOGGING for sensor '" + tmp_buf_2 + "' done"); + }, nullptr, false); + } + if (enter_to_logging_counter == LOG3) { + ts.add(LOG3, period_min.toInt() * 1000 * 60, [&](void*) { + String tmp_buf_3 = selectFromMarkerToMarker(logging_value_names_list, ",", 2); + deleteOldDate("log." + tmp_buf_3 + ".txt", jsonReadInt(configOptionJson, tmp_buf_3 + "_c"), jsonReadStr(configLiveJson, tmp_buf_3)); + Serial.println("[i] LOGGING for sensor '" + tmp_buf_3 + "' done"); + }, nullptr, false); + } + if (enter_to_logging_counter == LOG4) { + ts.add(LOG4, period_min.toInt() * 1000 * 60, [&](void*) { + String tmp_buf_4 = selectFromMarkerToMarker(logging_value_names_list, ",", 3); + deleteOldDate("log." + tmp_buf_4 + ".txt", jsonReadInt(configOptionJson, tmp_buf_4 + "_c"), jsonReadStr(configLiveJson, tmp_buf_4)); + Serial.println("[i] LOGGING for sensor '" + tmp_buf_4 + "' done"); + }, nullptr, false); + } + if (enter_to_logging_counter == LOG5) { + ts.add(LOG5, period_min.toInt() * 1000 * 60, [&](void*) { + String tmp_buf_5 = selectFromMarkerToMarker(logging_value_names_list, ",", 4); + deleteOldDate("log." + tmp_buf_5 + ".txt", jsonReadInt(configOptionJson, tmp_buf_5 + "_c"), jsonReadStr(configLiveJson, tmp_buf_5)); + Serial.println("[i] LOGGING for sensor '" + tmp_buf_5 + "' done"); + }, nullptr, false); + } } //=========================================Удаление стрых данных и запись новых================================================================== void deleteOldDate(String file, int seted_number_of_lines, String date_to_add) { - String log_date = readFile(file, 5000); - int current_number_of_lines = count(log_date, "\r\n"); - Serial.println("=====> [i] in log file " + file + " " + current_number_of_lines + " lines"); + String log_date = readFile(file, 5000); + int current_number_of_lines = count(log_date, "\r\n"); + Serial.println("=====> [i] in log file " + file + " " + current_number_of_lines + " lines"); - if (current_number_of_lines > seted_number_of_lines + 1) { - SPIFFS.remove("/" + file); - current_number_of_lines = 0; + if (current_number_of_lines > seted_number_of_lines + 1) { + SPIFFS.remove("/" + file); + current_number_of_lines = 0; + } + if (current_number_of_lines == 0) { + SPIFFS.remove("/" + file); + current_number_of_lines = 0; + } + if (current_number_of_lines > seted_number_of_lines) { + log_date = deleteBeforeDelimiter(log_date, "\r\n"); + if (GetTimeUnix() != "failed") { + log_date += GetTimeUnix() + " " + date_to_add + "\r\n"; + writeFile(file, log_date); } - if (current_number_of_lines == 0) { - SPIFFS.remove("/" + file); - current_number_of_lines = 0; + } else { + if (GetTimeUnix() != "failed") { + addFile(file, GetTimeUnix() + " " + date_to_add); } - if (current_number_of_lines > seted_number_of_lines) { - log_date = deleteBeforeDelimiter(log_date, "\r\n"); - if (GetTimeUnix() != "failed") { - log_date += GetTimeUnix() + " " + date_to_add + "\r\n"; - writeFile(file, log_date); - } - } else { - if (GetTimeUnix() != "failed") { - addFile(file, GetTimeUnix() + " " + date_to_add); - } - } - log_date = ""; + } + log_date = ""; } //=========================================Выбор какие данные отправлять================================================================== void choose_log_date_and_send() { - String all_line = logging_value_names_list; - while (all_line.length() != 0) { - String tmp = selectToMarker(all_line, ","); - sendLogData("log." + tmp + ".txt", tmp + "_ch" - ); - all_line = deleteBeforeDelimiter(all_line, ","); - } - all_line = ""; + String all_line = logging_value_names_list; + while (all_line.length() != 0) { + String tmp = selectToMarker (all_line, ","); + sendLogData("log." + tmp + ".txt", tmp + "_ch"); + all_line = deleteBeforeDelimiter(all_line, ","); + } + all_line = ""; } - //=========================================Отправка данных=================================================================================== void sendLogData(String file, String topic) { - String log_date = readFile(file, 5000); - if (log_date != "Failed") { - log_date.replace("\r\n", "\n"); - log_date.replace("\r", "\n"); - String buf = "{}"; - String json_array; - String unix_time; - String value; - while (log_date.length() != 0) { - String tmp = selectToMarker(log_date, "\n"); - log_date = deleteBeforeDelimiter(log_date, "\n"); - unix_time = selectToMarker(tmp, " "); - jsonWriteInt(buf, "x", unix_time.toInt()); - value = deleteBeforeDelimiter(tmp, " "); - jsonWriteFloat(buf, "y1", value.toFloat()); - if (log_date.length() < 3) { - json_array += buf; - } else { - json_array += buf + ","; - } - buf = "{}"; - } - unix_time = ""; - value = ""; - log_date = ""; - json_array = "{\"status\":[" + json_array + "]}"; - Serial.println(json_array); - sendCHART(topic, json_array); - json_array = ""; - getMemoryLoad("[i] after send log date"); + String log_date = readFile(file, 5000); + if (log_date != "Failed") { + log_date.replace("\r\n", "\n"); + log_date.replace("\r", "\n"); + String buf = "{}"; + String json_array; + String unix_time; + String value; + while (log_date.length() != 0) { + String tmp = selectToMarker (log_date, "\n"); + log_date = deleteBeforeDelimiter(log_date, "\n"); + unix_time = selectToMarker (tmp, " "); + jsonWriteInt(buf, "x", unix_time.toInt()); + value = deleteBeforeDelimiter(tmp, " "); + jsonWriteFloat(buf, "y1", value.toFloat()); + if (log_date.length() < 3) { + json_array += buf; + } else { + json_array += buf + ","; + } + buf = "{}"; } + unix_time = ""; + value = ""; + log_date = ""; + json_array = "{\"status\":[" + json_array + "]}"; + Serial.println(json_array); + sendCHART(topic, json_array); + json_array = ""; + getMemoryLoad("[i] after send log date"); + } } /* @@ -162,12 +146,12 @@ void sendLogData(String file, String topic) { */ //=========================================Очистка данных=================================================================================== void clean_log_date() { - String all_line = logging_value_names_list; - while (all_line.length() != 0) { - String tmp = selectToMarker(all_line, ","); - SPIFFS.remove("/log." + tmp + ".txt"); - all_line = deleteBeforeDelimiter(all_line, ","); - } - all_line = ""; + String all_line = logging_value_names_list; + while (all_line.length() != 0) { + String tmp = selectToMarker (all_line, ","); + SPIFFS.remove("/log." + tmp + ".txt"); + all_line = deleteBeforeDelimiter(all_line, ","); + } + all_line = ""; } -#endif +#endif \ No newline at end of file diff --git a/src/Mqtt.cpp b/src/Mqtt.cpp index 7acbcf16..bdf03cf3 100644 --- a/src/Mqtt.cpp +++ b/src/Mqtt.cpp @@ -1,6 +1,7 @@ #include "Global.h" void callback(char* topic, byte* payload, unsigned int length); + String stateMQTT(); void sendAllData(); void sendAllWigets(); @@ -9,74 +10,41 @@ void outcoming_date(); //===============================================ИНИЦИАЛИЗАЦИЯ================================================ void MQTT_init() { - ts.add( - WIFI_MQTT_CONNECTION_CHECK, wifi_mqtt_reconnecting, [&](void*) { - up_time(); - if (WiFi.status() == WL_CONNECTED) { - Serial.println("[VV] WiFi-ok"); - if (client_mqtt.connected()) { - Serial.println("[VV] MQTT-ok"); - led_blink("off"); - } else { - MQTT_Connecting(); - if (!just_load) mqtt_lost_error++; - } - } else { - Serial.println("[E] Lost WiFi connection"); - wifi_lost_error++; - ts.remove(WIFI_MQTT_CONNECTION_CHECK); - StartAPMode(); - } - }, - nullptr, true); - - server.on("/mqttSave", HTTP_GET, [](AsyncWebServerRequest* request) { - if (request->hasArg("mqttServer")) { - jsonWriteStr(configSetupJson, "mqttServer", request->getParam("mqttServer")->value()); - } - if (request->hasArg("mqttPort")) { - int port = (request->getParam("mqttPort")->value()).toInt(); - jsonWriteInt(configSetupJson, "mqttPort", port); - } - if (request->hasArg("mqttPrefix")) { - jsonWriteStr(configSetupJson, "mqttPrefix", request->getParam("mqttPrefix")->value()); - } - if (request->hasArg("mqttUser")) { - jsonWriteStr(configSetupJson, "mqttUser", request->getParam("mqttUser")->value()); - } - if (request->hasArg("mqttPass")) { - jsonWriteStr(configSetupJson, "mqttPass", request->getParam("mqttPass")->value()); - } - saveConfig(); - mqtt_connection = true; - - request->send(200, "text/text", "ok"); - }); - - server.on("/mqttCheck", HTTP_GET, [](AsyncWebServerRequest* request) { - String tmp = "{}"; - jsonWriteStr(tmp, "title", "" + stateMQTT()); - jsonWriteStr(tmp, "class", "pop-up"); - request->send(200, "text/text", tmp); - }); + ts.add(WIFI_MQTT_CONNECTION_CHECK, wifi_mqtt_reconnecting, [&](void*) { + if (WiFi.status() == WL_CONNECTED) { + Serial.println("[VV] WiFi-ok"); + if (client_mqtt.connected()) { + Serial.println("[VV] MQTT-ok"); + led_blink("off"); + } else { + MQTT_Connecting(); + if (!just_load) mqtt_lost_error++; + } + } else { + Serial.println("[E] Lost WiFi connection"); + wifi_lost_error++; + ts.remove(WIFI_MQTT_CONNECTION_CHECK); + StartAPMode(); + } + }, nullptr, true); } void do_mqtt_connection() { - if (mqtt_connection) { - mqtt_connection = false; - client_mqtt.disconnect(); - MQTT_Connecting(); - } + if (mqtt_connection) { + mqtt_connection = false; + client_mqtt.disconnect(); + MQTT_Connecting(); + } } -void handleMQTT() { - if (WiFi.status() == WL_CONNECTED) { - if (client_mqtt.connected()) { - client_mqtt.loop(); - } +//================================================ОБНОВЛЕНИЕ==================================================== +void handleMQTT() { + if (WiFi.status() == WL_CONNECTED) { + if (client_mqtt.connected()) { + client_mqtt.loop(); } + } } - boolean MQTT_Connecting() { bool res = false; String mqtt_server = jsonReadStr(configSetupJson, "mqttServer"); @@ -94,6 +62,9 @@ boolean MQTT_Connecting() { 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 { @@ -108,145 +79,168 @@ boolean MQTT_Connecting() { return res; } + //=====================================================ВХОДЯЩИЕ ДАННЫЕ======================================================== -void callback(char* topic, byte* payload, unsigned int length) { - Serial.print("[MQTT] "); - Serial.print(topic); - String topic_str = String(topic); +void callback(char* topic, byte * payload, unsigned int length) { + Serial.print("[MQTT] "); + Serial.print(topic); + String topic_str = String(topic); - String str; - for (int i = 0; i < length; i++) { - str += (char)payload[i]; - } - Serial.println(" => " + str); + String str; + for (int i = 0; i < length; i++) { + str += (char)payload[i]; + } + Serial.println(" => " + str); - if (str == "HELLO") outcoming_date(); + if (str == "HELLO") outcoming_date(); - //превращает название топика в команду, а значение в параметр команды - 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("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") { - upgrade = true; - } + if (topic_str.indexOf("order") > 0) { + str.replace("_", " "); + //Serial.println(str); + order_loop += str + ","; + } + if (topic_str.indexOf("update") > 0) { + if (str == "1") { + upgrade = true; } + } + if (topic_str.indexOf("devc") > 0) { + writeFile("firmware.c.txt", str); + Device_init(); + } + if (topic_str.indexOf("devs") > 0) { + writeFile("firmware.s.txt", str); + Scenario_init(); + } } //данные которые отправляем при подключении или отбновлении страницы void outcoming_date() { - sendAllWigets(); - sendAllData(); + + sendAllWigets(); + sendAllData(); #ifdef logging_enable - choose_log_date_and_send(); + choose_log_date_and_send(); #endif - Serial.println("[V] Sending all date to iot manager completed"); + Serial.println("[V] Sending all date to iot manager completed"); } + +//======================================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; + 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 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; + 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 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; +} + +//======================================STATUS================================================== void sendSTATUS(String topik, String state) { - topik = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipID + "/" + topik + "/" + "status"; - String json_ = "{}"; - jsonWriteStr(json_, "status", state); - client_mqtt.publish(topik.c_str(), json_.c_str(), false); + topik = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipID + "/" + topik + "/" + "status"; + String json_ = "{}"; + jsonWriteStr(json_, "status", state); + int send_status = 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); + String all_line = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + id + "/" + topik + "/control"; + int send_status = client_mqtt.publish (all_line.c_str(), state.c_str(), false); } //=====================================================ОТПРАВЛЯЕМ ВИДЖЕТЫ======================================================== #ifdef layout_in_ram void sendAllWigets() { - if (all_widgets != "") { - int counter = 0; - String line; - int psn_1 = 0; - int psn_2; - do { - psn_2 = all_widgets.indexOf("\r\n", psn_1); //\r\n - line = all_widgets.substring(psn_1, psn_2); - line.replace("\n", ""); - line.replace("\r\n", ""); - //jsonWriteStr(line, "id", String(counter)); - //jsonWriteStr(line, "pageId", String(counter)); - counter++; - sendMQTT("config", line); - Serial.println("[V] " + line); - psn_1 = psn_2 + 1; - } while (psn_2 + 2 < all_widgets.length()); - getMemoryLoad("[i] after send all widgets"); - } + if (all_widgets != "") { + int counter = 0; + String line; + int psn_1 = 0; + int psn_2; + do { + psn_2 = all_widgets.indexOf("\r\n", psn_1); //\r\n + line = all_widgets.substring(psn_1, psn_2); + line.replace("\n", ""); + line.replace("\r\n", ""); + //jsonWriteStr(line, "id", String(counter)); + //jsonWriteStr(line, "pageId", String(counter)); + counter++; + sendMQTT("config", line); + Serial.println("[V] " + line); + psn_1 = psn_2 + 1; + } while (psn_2 + 2 < all_widgets.length()); + getMemoryLoad("[i] after send all widgets"); + } } #endif #ifndef layout_in_ram void sendAllWigets() { - File configFile = SPIFFS.open("/layout.txt", "r"); - if (!configFile) { - return; - } - configFile.seek(0, SeekSet); //поставим курсор в начало файла - while (configFile.position() != configFile.size()) { - String widget_to_send = configFile.readStringUntil('\n'); - Serial.println("[V] " + widget_to_send); - sendMQTT("config", widget_to_send); - } + File configFile = SPIFFS.open("/layout.txt", "r"); + if (!configFile) { + return; + } + configFile.seek(0, SeekSet); //поставим курсор в начало файла + while (configFile.position() != configFile.size()) { + String widget_to_send = configFile.readStringUntil('\n'); + Serial.println("[V] " + widget_to_send); + sendMQTT("config", widget_to_send); + } } #endif //=====================================================ОТПРАВЛЯЕМ ДАННЫЕ В ВИДЖЕТЫ ПРИ ОБНОВЛЕНИИ СТРАНИЦЫ======================================================== -void sendAllData() { //берет строку json и ключи превращает в топики а значения колючей в них посылает +void sendAllData() { //берет строку json и ключи превращает в топики а значения колючей в них посылает - String current_config = configLiveJson; //{"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"} - getMemoryLoad("[i] after send all date"); - current_config.replace("{", ""); - current_config.replace("}", ""); //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1" - current_config += ","; //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1", + String current_config = configLiveJson; //{"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"} + getMemoryLoad("[i] after send all date"); + current_config.replace("{", ""); + current_config.replace("}", ""); //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1" + current_config += ","; //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1", - while (current_config.length() != 0) { - String tmp = selectToMarker(current_config, ","); - String topic = selectToMarker(tmp, ":"); - topic.replace("\"", ""); - String state = selectToMarkerLast(tmp, ":"); - state.replace("\"", ""); - if (topic != "name" && topic != "lang" && topic != "ip" && topic.indexOf("_in") < 0) { - sendSTATUS(topic, state); - //Serial.println("-->" + topic + " " + state); - } - current_config = deleteBeforeDelimiter(current_config, ","); + while (current_config.length() != 0) { + + String tmp = selectToMarker (current_config, ","); + String topic = selectToMarker (tmp, ":"); + topic.replace("\"", ""); + String state = selectToMarkerLast (tmp, ":"); + state.replace("\"", ""); + if (topic != "name" && topic != "lang" && topic != "ip" && topic.indexOf("_in") < 0) { + sendSTATUS(topic, state); + //Serial.println("-->" + topic + " " + state); } + current_config = deleteBeforeDelimiter(current_config, ","); + } } + + String stateMQTT() { int state = client_mqtt.state(); switch (state) { @@ -285,69 +279,3 @@ String stateMQTT() { break; } } - -/*void scenario_devices_topiks_subscribe() { - - //SCENARIO ANALOG > 5 800324-1458415 rel1 0 - if (jsonReadStr(configSetupJson, "scenario") == "1") { - //String all_text = readFile("firmware.s.txt", 1024) + "\r\n"; - String all_text = scenario + "\r\n"; - all_text.replace("\r\n", "\n"); - all_text.replace("\r", "\n"); - while (all_text.length() != 0) { - String line_ = selectToMarker (all_text, "\n"); - String id = selectFromMarkerToMarker(line_, " ", 4); - if (id != "not found") { - client_mqtt.subscribe((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + id + "/+/status").c_str(), 0); - Serial.println("subscribed to device, id: " + id); - } - all_text = deleteBeforeDelimiter(all_text, "\n"); - } - } - } -*/ -/*void scenario_devices_test_msg_send() { - - if (jsonReadStr(configSetupJson, "scenario") == "1") { - - String all_text = scenario + "\r\n"; - all_text.replace("\r\n", "\n"); - all_text.replace("\r", "\n"); - while (all_text.length() != 0) { - String line_ = selectToMarker (all_text, "\n"); - String id = selectFromMarkerToMarker(line_, " ", 4); - if (id != "not found") { - //Serial.println(); - Serial.println(client_mqtt.publish ((jsonReadStr(configSetupJson, "mqttPrefix") + "/" + id).c_str(), "CHECK", true)); - - } - all_text = deleteBeforeDelimiter(all_text, "\n"); - } - } - }*/ - -/* - //----------------------------------------------------------------------------------------------------------------------------------------------- - //jsonWriteStr(tmp, "status", "1"); - - String current_config = configLiveJson; //{"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1"} - current_config.replace("{", ""); - current_config.replace("}", ""); //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1" - current_config += ","; //"name":"MODULES","lang":"","ip":"192.168.43.60","DS":"34.00","rel1":"1","rel2":"1", - - while (current_config.length() != 0) { - - String tmp = selectToMarker (current_config, ","); //"rel1":"1" - String topic = selectToMarker (tmp, ":"); //"rel1" - topic.replace("\"", ""); //rel1 - Serial.println(topic); - String state = selectToMarkerLast (tmp, ":"); //"1" - state.replace("\"", ""); //1 - - //if (widget.lastIndexOf(topic) > 0) { - jsonWriteStr(tmp, "status", state); - //} - current_config = deleteBeforeDelimiter(current_config, ","); - } - //------------------------------------------------------------------------------------------------------------------------------------------------- -*/ diff --git a/src/Scenario.cpp b/src/Scenario.cpp index a653dd2b..37dfecb0 100644 --- a/src/Scenario.cpp +++ b/src/Scenario.cpp @@ -1,95 +1,96 @@ #include "Global.h" void handleScenario() { - if (jsonReadStr(configSetupJson, "scenario") == "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 (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++; - 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 (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 (flag) { - //удаляем строку самого сценария оставляя только команды - tmp = deleteBeforeDelimiter(tmp, "\n"); - //выполняем все команды - stringExecution(tmp); - Serial.println("[SCENARIO] '" + condition + "'"); - } - } - } - str = deleteBeforeDelimiter(str, "end\n"); //удаляем первый сценарий - //----------------------------------------------------------------------------------------------------------------------- + String sign = selectFromMarkerToMarker(condition, " " , 1); //читаем знак (=) + String value = selectFromMarkerToMarker(condition, " " , 2); //читаем значение (1) + if (value.indexOf("digit") != -1) { + // value = add_set(value); + value = jsonReadStr(configLiveJson, value); } - String tmp2 = jsonReadStr(configOptionJson, "scenario_status"); //читаем файл событий - tmp2 = deleteBeforeDelimiter(tmp2, ","); //удаляем выполненное событие - jsonWriteStr(configOptionJson, "scenario_status", tmp2); //записываем обновленный файл событий - i = 0; + 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); //выполняем все команды + + 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; } + } } -//событие выглядит как имя плюс set плюс номер: button+Set+1 -void eventGen(String event_name, String number) { - if (jsonReadStr(configSetupJson, "scenario") == "1") { - String tmp = jsonReadStr(configOptionJson, "scenario_status"); //генерирование события - //Serial.println(event_name); - jsonWriteStr(configOptionJson, "scenario_status", tmp + event_name + number + ","); - } +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 + ","); + } } 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/TimeUtils.cpp b/src/TimeUtils.cpp index b7cda1cc..b16d414e 100644 --- a/src/TimeUtils.cpp +++ b/src/TimeUtils.cpp @@ -1,146 +1,133 @@ #include "Global.h" void Time_Init() { - server.on("/time", HTTP_GET, [](AsyncWebServerRequest* request) { - if (request->hasArg("timezone")) { - jsonWriteStr(configSetupJson, "timezone", request->getParam("timezone")->value()); - } - if (request->hasArg("ntp")) { - jsonWriteStr(configSetupJson, "ntp", request->getParam("ntp")->value()); - } - saveConfig(); - reconfigTime(); - request->send(200, "text/text", "OK"); - }); - - ts.add( - TIME_SYNC, 30000, [&](void*) { - time_check(); - }, - nullptr, true); + ts.add(TIME_SYNC, 30000, [&](void*) { + time_check(); + }, nullptr, true); } void time_check() { - if (GetTimeUnix() == "failed") { - Serial.println("[i] Time is not synchronized, start synchronization"); - reconfigTime(); - } + if (GetTimeUnix() == "failed") { + Serial.println("[i] Time is not synchronized, start synchronization"); + reconfigTime(); + } } void reconfigTime() { - if (WiFi.status() == WL_CONNECTED) { - String ntp = jsonReadStr(configSetupJson, "ntp"); - configTime(0, 0, ntp.c_str()); - int i = 0; - Serial.println("[i] Awaiting for time "); + if (WiFi.status() == WL_CONNECTED) { + String ntp = jsonReadStr(configSetupJson, "ntp"); + configTime(0, 0, ntp.c_str()); + int i = 0; + Serial.println("[i] Awaiting for time "); #ifdef ESP32 - struct tm timeinfo; - while (!getLocalTime(&timeinfo) && i <= 4) { - Serial.print("."); - i++; - delay(1000); - } + struct tm timeinfo; + while (!getLocalTime(&timeinfo) && i <= 4) { + Serial.print("."); + i++; + delay(1000); + } #endif #ifdef ESP8266 - //while (!time(nullptr) && i < 4) { - // Serial.print("."); - // i++; - delay(2000); - //} + //while (!time(nullptr) && i < 4) { + // Serial.print("."); + // i++; + delay(2000); + //} #endif - if (GetTimeUnix() != "failed") { - Serial.print("[V] Time synchronized = "); - Serial.print(GetDataDigital()); - Serial.print(" "); - Serial.println(GetTime()); - } else { - Serial.println("[E] Time server or internet connection error, will try again in 30 sec"); - } + if (GetTimeUnix() != "failed") { + Serial.print("[V] Time synchronized = "); + Serial.print(GetDataDigital()); + Serial.print(" "); + Serial.println(GetTime()); } else { - Serial.println("[E] Get time impossible, no wifi connection"); + Serial.println("[E] Time server or internet connection error, will try again in 30 sec"); } + } else { + Serial.println("[E] Get time impossible, no wifi connection"); + } } //Получаем время в формате linux gmt String GetTimeUnix() { - time_t now = time(nullptr); - if (now < 30000) { - return "failed"; - } else { - return String(now); - } + time_t now = time(nullptr); + if (now < 30000) { + return "failed"; + } else { + return String(now); + } } - // Получение текущего времени String GetTime() { - time_t now = time(nullptr); // получаем время с помощью библиотеки time.h - int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); - now = now + zone; - String Time = ""; // Строка для результатов времени - Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 - int i = Time.indexOf(":"); //Ишем позицию первого символа : - Time = Time.substring(i - 2, i + 6); // Выделяем из строки 2 символа перед символом : и 6 символов после - return Time; // Возврашаем полученное время + time_t now = time(nullptr); // получаем время с помощью библиотеки time.h + int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); + now = now + zone; + String Time = ""; // Строка для результатов времени + Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 + int i = Time.indexOf(":"); //Ишем позицию первого символа : + Time = Time.substring(i - 2, i + 6); // Выделяем из строки 2 символа перед символом : и 6 символов после + return Time; // Возврашаем полученное время } String GetTimeWOsec() { - time_t now = time(nullptr); // получаем время с помощью библиотеки time.h - int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); - now = now + zone; - String Time = ""; // Строка для результатов времени - Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 - int i = Time.indexOf(":"); //Ишем позицию первого символа : - Time = Time.substring(i - 2, i + 3); // Выделяем из строки 2 символа перед символом : и 6 символов после - return Time; // Возврашаем полученное время + time_t now = time(nullptr); // получаем время с помощью библиотеки time.h + int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); + now = now + zone; + String Time = ""; // Строка для результатов времени + Time += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 + int i = Time.indexOf(":"); //Ишем позицию первого символа : + Time = Time.substring(i - 2, i + 3); // Выделяем из строки 2 символа перед символом : и 6 символов после + return Time; // Возврашаем полученное время } // Получение даты String GetDate() { - time_t now = time(nullptr); // получаем время с помощью библиотеки time.h - int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); - now = now + zone; - String Data = ""; // Строка для результатов времени - Data += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 - Data.replace("\n", ""); - uint8_t i = Data.lastIndexOf(" "); //Ишем позицию последнего символа пробел - String Time = Data.substring(i - 8, i + 1); // Выделяем время и пробел - Data.replace(Time, ""); // Удаляем из строки 8 символов времени и пробел - return Data; // Возврашаем полученную дату + time_t now = time(nullptr); // получаем время с помощью библиотеки time.h + int zone = 3600 * jsonReadStr(configSetupJson, "timezone").toInt(); + now = now + zone; + String Data = ""; // Строка для результатов времени + Data += ctime(&now); // Преобразуем время в строку формата Thu Jan 19 00:55:35 2017 + Data.replace("\n", ""); + uint8_t i = Data.lastIndexOf(" "); //Ишем позицию последнего символа пробел + String Time = Data.substring(i - 8, i + 1); // Выделяем время и пробел + Data.replace(Time, ""); // Удаляем из строки 8 символов времени и пробел + return Data; // Возврашаем полученную дату } String GetDataDigital() { - String date = GetDate(); - date = deleteBeforeDelimiter(date, " "); - date.replace("Jan", "01"); - date.replace("Feb", "02"); - date.replace("Mar", "03"); - date.replace("Apr", "04"); - date.replace("May", "05"); - date.replace("Jun", "06"); - date.replace("Jul", "07"); - date.replace("Aug", "08"); - date.replace("Sep", "09"); - date.replace("Oct", "10"); - date.replace("Nov", "11"); - date.replace("Dec", "12"); + String date = GetDate(); - String month = date.substring(0, 2); - String day = date.substring(3, 5); - String year = date.substring(8, 10); + date = deleteBeforeDelimiter(date, " "); - String out = day; - out += "."; - out += month; - out += "."; - out += year; + date.replace("Jan", "01"); + date.replace("Feb", "02"); + date.replace("Mar", "03"); + date.replace("Apr", "04"); + date.replace("May", "05"); + date.replace("Jun", "06"); + date.replace("Jul", "07"); + date.replace("Aug", "08"); + date.replace("Sep", "09"); + date.replace("Oct", "10"); + date.replace("Nov", "11"); + date.replace("Dec", "12"); - return out; + String month = date.substring(0, 2); + String day = date.substring(3, 5); + String year = date.substring(8, 10); + + String out = day; + out += "."; + out += month; + out += "."; + out += year; + + return out; } int timeToMin(String Time) { - //"00:00:00" время в секунды - long min = selectToMarker(Time, ":").toInt() * 60; //общее количество секунд в полных часах - Time = deleteBeforeDelimiter(Time, ":"); // Теперь здесь минуты секунды - min += selectToMarker(Time, ":").toInt(); // Добавим секунды из полных минут - return min; -} + //"00:00:00" время в секунды + long min = selectToMarker(Time, ":").toInt() * 60; //общее количество секунд в полных часах + Time = deleteBeforeDelimiter (Time, ":"); // Теперь здесь минуты секунды + min += selectToMarker(Time, ":").toInt(); // Добавим секунды из полных минут + return min; +} \ No newline at end of file diff --git a/src/Timers.cpp b/src/Timers.cpp index 73dfe5e9..6cef52ba 100644 --- a/src/Timers.cpp +++ b/src/Timers.cpp @@ -1,89 +1,91 @@ #include "Global.h" +//================================================================================================================ +//=========================================Таймеры================================================================= void Timer_countdown_init() { - ts.add( - TIMER_COUNTDOWN, 1000, [&](void*) { - String old_line = jsonReadStr(configOptionJson, "timers"); - if (old_line != "") { - //Serial.println(old_line); - int i = 0; - do { - String timer = selectFromMarkerToMarker(old_line, ",", i); - Serial.print("timer no " + String(i) + ": "); - Serial.println(timer); - if (timer == "not found" || timer == "") return; - int number = selectToMarker(timer, ":").toInt(); - int time = readTimer(number); - if (time == 0) { - delTimer(String(number)); - jsonWriteStr(configLiveJson, "timer" + String(number), "0"); - eventGen("timer", String(number)); - } else { - time--; - addTimer(String(number), String(time)); - } - i++; - } while (i <= 9); - } - }, - nullptr, true); + + ts.add(TIMER_COUNTDOWN, 1000, [&](void*) { + + String old_line = jsonReadStr(configOptionJson, "timers"); + if (old_line != "") { + //Serial.println(old_line); + int i = 0; + do { + String timer = selectFromMarkerToMarker(old_line, "," , i); + Serial.print("timer no " + String (i) + ": "); + Serial.println(timer); + if (timer == "not found" || timer == "") return; + int number = selectToMarker (timer, ":").toInt(); + int time = readTimer(number); + if (time == 0) { + delTimer (String (number)); + jsonWriteStr(configLiveJson, "timer" + String(number), "0"); + eventGen ("timer", String(number)); + } else { + time--; + addTimer(String (number), String (time)); + } + i++; + } while (i <= 9); + } + }, nullptr, true); } void timerStart_() { - String number = sCmd.next(); - String period_of_time = sCmd.next(); - String type = sCmd.next(); - if (period_of_time.indexOf("digit") != -1) { - period_of_time = jsonReadStr(configLiveJson, period_of_time); - } - if (type == "sec") period_of_time = period_of_time; - if (type == "min") period_of_time = String(period_of_time.toInt() * 60); - if (type == "hours") period_of_time = String(period_of_time.toInt() * 60 * 60); - addTimer(number, period_of_time); - jsonWriteStr(configLiveJson, "timer" + number, "1"); + String number = sCmd.next(); + String period_of_time = sCmd.next(); + String type = sCmd.next(); + if (period_of_time.indexOf("digit") != -1) { + //period_of_time = add_set(period_of_time); + period_of_time = jsonReadStr(configLiveJson, period_of_time); + } + if (type == "sec") period_of_time = period_of_time; + if (type == "min") period_of_time = String(period_of_time.toInt() * 60); + if (type == "hours") period_of_time = String(period_of_time.toInt() * 60 * 60); + addTimer(number, period_of_time); + jsonWriteStr(configLiveJson, "timer" + number, "1"); } - void addTimer(String number, String time) { - String tmp = jsonReadStr(configOptionJson, "timers"); //1:60,2:120, - String new_timer = number + ":" + time; - int psn1 = tmp.indexOf(number + ":"); //0 ищем позицию таймера который надо заменить - if (psn1 != -1) { //если он есть - int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой - String timer = tmp.substring(psn1, psn2); //1:60 выделяем таймер который надо заменить - ///tmp.replace(timer, new_timer); //заменяем таймер на новый (во всей стороке) - tmp.replace(timer + ",", ""); - tmp += new_timer + ","; - } else { //если его нет - tmp += new_timer + ","; - } - jsonWriteStr(configOptionJson, "timers", tmp); - //Serial.println("ura"); + String tmp = jsonReadStr(configOptionJson, "timers"); //1:60,2:120, + String new_timer = number + ":" + time; + int psn1 = tmp.indexOf(number + ":"); //0 ищем позицию таймера который надо заменить + if (psn1 != -1) { //если он есть + int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой + String timer = tmp.substring(psn1, psn2); //1:60 выделяем таймер который надо заменить + ///tmp.replace(timer, new_timer); //заменяем таймер на новый (во всей стороке) + tmp.replace(timer + ",", ""); + tmp += new_timer + ","; + } else { //если его нет + tmp += new_timer + ","; + } + jsonWriteStr(configOptionJson, "timers", tmp); + //Serial.println("ura"); } void timerStop_() { - String number = sCmd.next(); - delTimer(number); + String number = sCmd.next(); + delTimer(number); } -void delTimer(String number) { - String tmp = jsonReadStr(configOptionJson, "timers"); //1:60,2:120, - int psn1 = tmp.indexOf(number + ":"); //0 ищем позицию таймера который надо удалить - if (psn1 != -1) { //если он есть - int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой - String timer = tmp.substring(psn1, psn2) + ","; //1:60, выделяем таймер который надо удалить - tmp.replace(timer, ""); //удаляем таймер - jsonWriteStr(configOptionJson, "timers", tmp); - } +void delTimer (String number) { + String tmp = jsonReadStr(configOptionJson, "timers"); //1:60,2:120, + int psn1 = tmp.indexOf(number + ":"); //0 ищем позицию таймера который надо удалить + if (psn1 != -1) { //если он есть + int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой + String timer = tmp.substring(psn1, psn2) + ","; //1:60, выделяем таймер который надо удалить + tmp.replace(timer, ""); //удаляем таймер + jsonWriteStr(configOptionJson, "timers", tmp); + } } int readTimer(int number) { - String tmp = jsonReadStr(configOptionJson, "timers"); //1:60,2:120, - int psn1 = tmp.indexOf(String(number) + ":"); //0 ищем позицию таймера который надо прочитать - String timer; - if (psn1 != -1) { //если он есть - int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой - timer = tmp.substring(psn1, psn2); //1:60 выделяем таймер который надо прочитать - timer = deleteBeforeDelimiter(timer, ":"); - } - return timer.toInt(); -} + String tmp = jsonReadStr(configOptionJson, "timers"); //1:60,2:120, + int psn1 = tmp.indexOf(String(number) + ":"); //0 ищем позицию таймера который надо прочитать + String timer; + if (psn1 != -1) { //если он есть + int psn2 = tmp.indexOf(",", psn1); //4 от этой позиции находим позицию запятой + timer = tmp.substring(psn1, psn2); //1:60 выделяем таймер который надо прочитать + timer = deleteBeforeDelimiter(timer, ":"); + } + return timer.toInt(); +} \ No newline at end of file diff --git a/src/Upgrade.cpp b/src/Upgrade.cpp index e8982117..329588fd 100644 --- a/src/Upgrade.cpp +++ b/src/Upgrade.cpp @@ -1,125 +1,89 @@ #include "Global.h" -static const char* UPDATE_URL PROGMEM = "http://91.204.228.124:1100/update/%s/%s"; -static const char* FIRMWARE_FILE = "esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"; -#ifdef ESP32 -static const char* MCU = "esp32"; -#else -static const char* MCU = "esp8266"; -#endif - -const String createUrl(const char* qry) { - char buf[128]; - sprintf_P(buf, UPDATE_URL, MCU, qry); - return String(buf); -} - -const String getVersionUrl() { - return createUrl("version.txt"); -} - -const String getFirmwareUrl() { - return createUrl(FIRMWARE_FILE); -} - void initUpgrade() { - String last_version = WiFi.status() == WL_CONNECTED ? getURL(getVersionUrl()) : ""; - jsonWriteStr(configSetupJson, "last_version", last_version); - - Serial.printf("[i] Last firmware version: %s\n", last_version.c_str()); - - server.on("/check", HTTP_GET, [last_version](AsyncWebServerRequest* request) { - upgrade_url = true; - Serial.printf("[i] Last firmware version: %s\n", last_version.c_str()); - String tmp = "{}"; - if (WiFi.status() == WL_CONNECTED) { - if (mb_4_of_memory) { - if (last_version != "") { - if (last_version != "error") { - if (last_version == firmware_version) { - jsonWriteStr(tmp, "title", "Последняя версия прошивки уже установлена."); - jsonWriteStr(tmp, "class", "pop-up"); - } else { - jsonWriteStr(tmp, "title", "Имеется новая версия прошивки
Идет обновление прошивки, после обновления страница перезагрузится автоматически...')\">Установить"); - jsonWriteStr(tmp, "class", "pop-up"); - } - } else { - jsonWriteStr(tmp, "title", "Ошибка... Cервер не найден. Попробуйте позже..."); - jsonWriteStr(tmp, "class", "pop-up"); - } - } else { - jsonWriteStr(tmp, "title", "Нажмите на кнопку \"обновить прошивку\" повторно..."); - jsonWriteStr(tmp, "class", "pop-up"); - } - } else { - jsonWriteStr(tmp, "title", "Обновление по воздуху не поддерживается, модуль имеет меньше 4 мб памяти..."); - jsonWriteStr(tmp, "class", "pop-up"); - } - } else { - jsonWriteStr(tmp, "title", "Устройство не подключен к роутеру..."); - jsonWriteStr(tmp, "class", "pop-up"); - } - request->send(200, "text/text", tmp); - }); - - server.on("/upgrade", HTTP_GET, [](AsyncWebServerRequest* request) { - upgrade = true; - String tmp = "{}"; - request->send(200, "text/text", "ok"); - }); +#ifdef ESP8266 + if (WiFi.status() == WL_CONNECTED) last_version = getURL("http://91.204.228.124:1100/update/esp8266/version.txt"); +#endif +#ifdef ESP32 + if (WiFi.status() == WL_CONNECTED) last_version = getURL("http://91.204.228.124:1100/update/esp32/version.txt"); +#endif + jsonWriteStr(configSetupJson, "last_version", last_version); + Serial.print("[i] Last firmware version: "); + Serial.println(last_version); } void do_upgrade_url() { - if (upgrade_url) { - upgrade_url = false; - last_version = getURL(getVersionUrl()); - jsonWriteStr(configSetupJson, "last_version", last_version); - } + if (upgrade_url) { + upgrade_url = false; +#ifdef ESP32 + last_version = getURL("http://91.204.228.124:1100/update/esp32/version.txt"); +#endif +#ifdef ESP8266 + last_version = getURL("http://91.204.228.124:1100/update/esp8266/version.txt"); +#endif + jsonWriteStr(configSetupJson, "last_version", last_version); + } } void upgrade_firmware() { - String scenario_for_update; - String config_for_update; - String configSetupJson_for_update; - scenario_for_update = readFile("firmware.s.txt", 4000); - config_for_update = readFile("firmware.c.txt", 4000); - configSetupJson_for_update = configSetupJson; - Serial.println("Start upgrade SPIFFS, please wait..."); + String scenario_for_update; + String config_for_update; + String configSetup_for_update; + scenario_for_update = readFile("firmware.s.txt", 4000); + config_for_update = readFile("firmware.c.txt", 4000); + configSetup_for_update = configSetupJson; - WiFiClient client_for_upgrade; + Serial.println("Start upgrade SPIFFS, please wait..."); - httpUpdate.rebootOnUpdate(false); - t_httpUpdate_return ret = httpUpdate.updateSpiffs(client_for_upgrade, getFirmwareUrl()); + WiFiClient client_for_upgrade; + +#ifdef ESP32 + httpUpdate.rebootOnUpdate(false); + t_httpUpdate_return ret = httpUpdate.updateSpiffs(client_for_upgrade, "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"); +#endif +#ifdef ESP8266 + ESPhttpUpdate.rebootOnUpdate(false); + t_httpUpdate_return ret = ESPhttpUpdate.updateSpiffs(client_for_upgrade, "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"); +#endif + + if (ret == HTTP_UPDATE_OK) { + + writeFile("firmware.s.txt", scenario_for_update); + writeFile("firmware.c.txt", config_for_update); + writeFile("config.json", configSetup_for_update); + saveConfig(); + + Serial.println("SPIFFS upgrade done!"); + Serial.println("Start upgrade BUILD, please wait..."); + +#ifdef ESP32 + //httpUpdate.rebootOnUpdate(true); + t_httpUpdate_return ret = httpUpdate.update(client_for_upgrade, "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.ino.bin"); +#endif +#ifdef ESP8266 + //ESPhttpUpdate.rebootOnUpdate(true); + t_httpUpdate_return ret = ESPhttpUpdate.update(client_for_upgrade, "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.ino.bin"); +#endif if (ret == HTTP_UPDATE_OK) { - writeFile("firmware.s.txt", scenario_for_update); - writeFile("firmware.c.txt", config_for_update); - writeFile("config.json", configSetupJson_for_update); - saveConfig(); - Serial.println("SPIFFS upgrade done!"); - Serial.println("Start upgrade BUILD, please wait..."); - - t_httpUpdate_return ret = httpUpdate.update(client_for_upgrade, getFirmwareUrl()); - - if (ret == HTTP_UPDATE_OK) { - Serial.println("BUILD upgrade done!"); - Serial.println("Restart ESP...."); - ESP.restart(); - } else { - Serial.println("!!!!BUILD upgrade ERROR"); - } + Serial.println("BUILD upgrade done!"); + Serial.println("Restart ESP...."); + ESP.restart(); } else { - Serial.println("!!!!SPIFFS upgrade ERROR"); + Serial.println("!!!!BUILD upgrade ERROR"); } + } else { + Serial.println("!!!!SPIFFS upgrade ERROR"); + } } void do_upgrade() { - if (upgrade) { - upgrade = false; - upgrade_firmware(); - } + if (upgrade) { + upgrade = false; + upgrade_firmware(); + } } /* @@ -128,95 +92,12 @@ void do_upgrade() { case HTTP_UPDATE_FAILED: Serial.printf("UPDATE_FAILED Error (%d): %s", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str()); break; - case HTTP_UPDATE_NO_UPDATES: Serial.println("NO_UPDATES"); break; - case HTTP_UPDATE_OK: Serial.println("HTTP_UPDATE_OK"); break; } } -*/ - -/* - // ----------------------- Обновление с сайта - void webUpgrade() { - - #ifdef ESP8266 - String spiffsData = "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"; - String buildData = "http://91.204.228.124:1100/update/esp8266/esp32-esp8266_iot-manager_modules_firmware.ino.bin"; - #endif - - #ifdef ESP32 - String spiffsData = "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.spiffs.bin"; - String buildData = "http://91.204.228.124:1100/update/esp32/esp32-esp8266_iot-manager_modules_firmware.ino.bin"; - #endif - - if (spiffsData != "") { // Если нужно прошить FS - String scenario_for_update; - String config_for_update; - String configSetupJson_for_update; - Serial.println(spiffsData); - scenario_for_update = readFile("firmware.s.txt", 2048); - config_for_update = readFile("config.all.txt", 2048); - configSetupJson_for_update = configSetupJson; - ESPhttpUpdate.rebootOnUpdate(false); // Отключим перезагрузку после обновления - updateHTTP(spiffsData, true); - writeFile("firmware.s.txt", scenario_for_update); - writeFile("config.all.txt", config_for_update); - writeFile("config.json", configSetupJson_for_update); - saveConfig(); - } - - if (buildData != "") { // Если нужно прошить build - Serial.println(buildData); - ESPhttpUpdate.rebootOnUpdate(true); // Включим перезагрузку после обновления - updateHTTP(buildData, false); - } - } - // ------------------ Обновление по url - void updateHTTP(String url, boolean mode) { - if (url == "") return; - ESPhttpUpdate.setLedPin(LED_BUILTIN, LOW); - if (mode) { - Serial.println("Update Spiffs..."); - t_httpUpdate_return ret = ESPhttpUpdate.updateSpiffs(url); - UpdateStatus(ret , "Spiffs"); - } else { - Serial.println("Update Build..."); - t_httpUpdate_return ret = ESPhttpUpdate.update(url); - UpdateStatus(ret , "build"); - } - } - void UpdateStatus(t_httpUpdate_return set, String mode) { - - switch (set) { - - case HTTP_UPDATE_FAILED: - Serial.println(mode + "_FAILED"); - var = "{}"; - jsonWriteStr(var, "title", "_FAILED"); - jsonWriteStr(var, "class", "pop-up"); - //request->send(200, "text/text", var); - break; - - case HTTP_UPDATE_NO_UPDATES: - Serial.println(mode + "_NO_UPDATES"); - var = "{}"; - jsonWriteStr(var, "title", "_NO_UPDATES"); - jsonWriteStr(var, "class", "pop-up"); - //request->send(200, "text/text", var); - break; - - case HTTP_UPDATE_OK: - Serial.println(mode + "_UPDATE_OK"); - var = "{}"; - jsonWriteStr(var, "title", "_UPDATE_OK"); - jsonWriteStr(var, "class", "pop-up"); - //request->send(200, "text/text", var); - break; - } - } -*/ +*/ \ No newline at end of file diff --git a/src/Web.cpp b/src/Web.cpp new file mode 100644 index 00000000..4a3b0756 --- /dev/null +++ b/src/Web.cpp @@ -0,0 +1,356 @@ +#include "Global.h" + +String stateMQTT(); + +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)); + } + Device_init(); + Scenario_init(); + request->redirect("/?set.device"); + } + //-------------------------------------------------------------------------------- + if (request->hasArg("devinit")) { + Device_init(); + request->send(200, "text/text", "OK"); + } + //-------------------------------------------------------------------------------- + if (request->hasArg("scen")) { + value = request->getParam("scen")->value(); + if (value == "0") { + jsonWriteStr(configSetupJson, "scen", value); + saveConfig(); + Scenario_init(); + } + if (value == "1") { + jsonWriteStr(configSetupJson, "scen", value); + saveConfig(); + Scenario_init(); + } + request->send(200, "text/text", "OK"); + } + //-------------------------------------------------------------------------------- + if (request->hasArg("sceninit")) { + Scenario_init(); + request->send(200, "text/text", "OK"); + } + //-------------------------------------------------------------------------------- +#ifdef logging_enable + if (request->hasArg("cleanlog")) { + clean_log_date(); + request->send(200, "text/text", "OK"); + } +#endif + //==============================udp settings============================================= + if (request->hasArg("udponoff")) { + value = request->getParam("udponoff")->value(); + if (value == "0") { + jsonWriteStr(configSetupJson, "udponoff", value); + saveConfig(); + Scenario_init(); + } + if (value == "1") { + jsonWriteStr(configSetupJson, "udponoff", value); + saveConfig(); + Scenario_init(); + } + request->send(200, "text/text", "OK"); + } + //-------------------------------------------------------------------------------- + if (request->hasArg("updatelist")) { + SPIFFS.remove("/dev.csv"); + addFile("dev.csv", "device id;device name;ip address"); + request->redirect("/?set.udp"); + } + //-------------------------------------------------------------------------------- + if (request->hasArg("updatepage")) { + request->redirect("/?set.udp"); + } + //-------------------------------------------------------------------------------- + if (request->hasArg("devname")) { + jsonWriteStr(configSetupJson, "name", request->getParam("devname")->value()); + saveConfig(); + request->send(200, "text/text", "OK"); + } + //==============================wifi settings============================================= + if (request->hasArg("routerssid")) { + jsonWriteStr(configSetupJson, "routerssid", request->getParam("routerssid")->value()); + saveConfig(); + request->send(200, "text/text", "OK"); + } + if (request->hasArg("routerpass")) { + jsonWriteStr(configSetupJson, "routerpass", request->getParam("routerpass")->value()); + saveConfig(); + request->send(200, "text/text", "OK"); + } + //-------------------------------------------------------------------------------- + if (request->hasArg("apssid")) { + jsonWriteStr(configSetupJson, "apssid", request->getParam("apssid")->value()); + saveConfig(); + request->send(200, "text/text", "OK"); + } + if (request->hasArg("appass")) { + jsonWriteStr(configSetupJson, "appass", request->getParam("appass")->value()); + saveConfig(); + request->send(200, "text/text", "OK"); + } + //-------------------------------------------------------------------------------- + if (request->hasArg("weblogin")) { + jsonWriteStr(configSetupJson, "weblogin", request->getParam("weblogin")->value()); + saveConfig(); + request->send(200, "text/text", "OK"); + } + if (request->hasArg("webpass")) { + jsonWriteStr(configSetupJson, "webpass", request->getParam("webpass")->value()); + saveConfig(); + request->send(200, "text/text", "OK"); + } + //-------------------------------------------------------------------------------- + if (request->hasArg("timezone")) { + jsonWriteStr(configSetupJson, "timezone", request->getParam("timezone")->value()); + saveConfig(); + reconfigTime(); + request->send(200, "text/text", "OK"); + } + if (request->hasArg("ntp")) { + jsonWriteStr(configSetupJson, "ntp", request->getParam("ntp")->value()); + saveConfig(); + reconfigTime(); + request->send(200, "text/text", "OK"); + } + //-------------------------------------------------------------------------------- + if (request->hasArg("device")) { + if (request->getParam("device")->value() == "ok") ESP.restart(); + request->send(200, "text/text", "OK"); + } + //-------------------------------------------------------------------------------- + if (request->hasArg("blink")) { + value = request->getParam("blink")->value(); + if (value == "0") { + jsonWriteStr(configSetupJson, "blink", value); + saveConfig(); + } + if (value == "1") { + jsonWriteStr(configSetupJson, "blink", value); + saveConfig(); + } + request->send(200, "text/text", "OK"); + } + //==============================mqtt settings============================================= + if (request->hasArg("mqttServer")) { + jsonWriteStr(configSetupJson, "mqttServer", request->getParam("mqttServer")->value()); + saveConfig(); + mqtt_connection = 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; + request->send(200, "text/text", "ok"); + } + if (request->hasArg("mqttPrefix")) { + jsonWriteStr(configSetupJson, "mqttPrefix", request->getParam("mqttPrefix")->value()); + saveConfig(); + mqtt_connection = true; + request->send(200, "text/text", "ok"); + } + if (request->hasArg("mqttUser")) { + jsonWriteStr(configSetupJson, "mqttUser", request->getParam("mqttUser")->value()); + saveConfig(); + mqtt_connection = true; + request->send(200, "text/text", "ok"); + } + if (request->hasArg("mqttPass")) { + jsonWriteStr(configSetupJson, "mqttPass", request->getParam("mqttPass")->value()); + saveConfig(); + mqtt_connection = true; + request->send(200, "text/text", "ok"); + } + //-------------------------------------------------------------------------------- + if (request->hasArg("mqttsend")) { + mqtt_send_settings_to_udp = true; + 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); + } + //==============================push settings============================================= +#ifdef push_enable + if (request->hasArg("pushingboxid")) { + jsonWriteStr(configSetupJson, "pushingboxid", request->getParam("pushingboxid")->value()); + saveConfig(); + request->send(200, "text/text", "ok"); + } +#endif + //==============================utilities settings============================================= + if (request->hasArg("itoc")) { + i2c_scanning = true; + request->redirect("/?set.utilities"); + } + }); + //==============================upgrade settings============================================= + server.on("/check", HTTP_GET, [](AsyncWebServerRequest * request) { + upgrade_url = true; + Serial.print("[i] Last firmware version: "); + Serial.println(last_version); + String tmp = "{}"; + int case_of_update; + + if (WiFi.status() != WL_CONNECTED) last_version = "nowifi"; + if (!mb_4_of_memory) last_version = "less"; + + if (last_version == firmware_version) case_of_update = 1; + if (last_version != firmware_version) case_of_update = 2; + if (last_version == "error") case_of_update = 3; + if (last_version == "") case_of_update = 4; + if (last_version == "less") case_of_update = 5; + if (last_version == "nowifi") case_of_update = 6; + if (last_version == "notsupported") case_of_update = 7; + + switch (case_of_update) { + case 1: { + jsonWriteStr(tmp, "title", "Последняя версия прошивки уже установлена."); + jsonWriteStr(tmp, "class", "pop-up"); + } + break; + + case 2: { + jsonWriteStr(tmp, "title", "Имеется новая версия прошивкиИдет обновление прошивки, после обновления страница перезагрузится автоматически...')\">Установить"); + jsonWriteStr(tmp, "class", "pop-up"); + } + break; + + case 3: { + jsonWriteStr(tmp, "title", "Ошибка... Cервер не найден. Попробуйте позже..."); + jsonWriteStr(tmp, "class", "pop-up"); + } + break; + + case 4: { + jsonWriteStr(tmp, "title", "Нажмите на кнопку \"обновить прошивку\" повторно..."); + jsonWriteStr(tmp, "class", "pop-up"); + break; + } + + case 5: { + jsonWriteStr(tmp, "title", "Обновление по воздуху не поддерживается, модуль имеет меньше 4 мб памяти..."); + jsonWriteStr(tmp, "class", "pop-up"); + break; + } + + case 6: { + jsonWriteStr(tmp, "title", "Устройство не подключено к роутеру..."); + jsonWriteStr(tmp, "class", "pop-up"); + break; + } + + case 7: { + jsonWriteStr(tmp, "title", "Обновление на новую версию возможно только через usb..."); + jsonWriteStr(tmp, "class", "pop-up"); + break; + } + } + request->send(200, "text/text", tmp); + }); + + server.on("/upgrade", HTTP_GET, [](AsyncWebServerRequest * request) { + upgrade = true; + String tmp = "{}"; + request->send(200, "text/text", "ok"); + }); +} \ No newline at end of file diff --git a/src/Web_server.cpp b/src/Web_server.cpp index a2f8f602..50f83c1c 100644 --- a/src/Web_server.cpp +++ b/src/Web_server.cpp @@ -1,230 +1,234 @@ #include "Global.h" void Web_server_init() { + /********************************************************************************* + ***************************************OTA**************************************** + *********************************************************************************/ #ifdef OTA_enable - ArduinoOTA.onStart([]() { - events.send("Update Start", "ota"); - }); - ArduinoOTA.onEnd([]() { - events.send("Update End", "ota"); - }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - char p[32]; - sprintf(p, "Progress: %u%%\n", (progress / (total / 100))); - events.send(p, "ota"); - }); - ArduinoOTA.onError([](ota_error_t error) { - if (error == OTA_AUTH_ERROR) - events.send("Auth Failed", "ota"); - else if (error == OTA_BEGIN_ERROR) - events.send("Begin Failed", "ota"); - else if (error == OTA_CONNECT_ERROR) - events.send("Connect Failed", "ota"); - else if (error == OTA_RECEIVE_ERROR) - events.send("Recieve Failed", "ota"); - else if (error == OTA_END_ERROR) - events.send("End Failed", "ota"); - }); - ArduinoOTA.setHostname(hostName); - ArduinoOTA.begin(); + ArduinoOTA.onStart([]() { + events.send("Update Start", "ota"); + }); + ArduinoOTA.onEnd([]() { + events.send("Update End", "ota"); + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + char p[32]; + sprintf(p, "Progress: %u%%\n", (progress / (total / 100))); + events.send(p, "ota"); + }); + ArduinoOTA.onError([](ota_error_t error) { + if (error == OTA_AUTH_ERROR) events.send("Auth Failed", "ota"); + else if (error == OTA_BEGIN_ERROR) events.send("Begin Failed", "ota"); + else if (error == OTA_CONNECT_ERROR) events.send("Connect Failed", "ota"); + else if (error == OTA_RECEIVE_ERROR) events.send("Recieve Failed", "ota"); + else if (error == OTA_END_ERROR) events.send("End Failed", "ota"); + }); + ArduinoOTA.setHostname(hostName); + ArduinoOTA.begin(); #endif - /********************************************************************************* + /********************************************************************************* **************************************MDNS**************************************** *********************************************************************************/ #ifdef MDNS_enable - MDNS.addService("http", "tcp", 80); + MDNS.addService("http", "tcp", 80); #endif - //SPIFFS.begin(); - /********************************************************************************* + //SPIFFS.begin(); + /********************************************************************************* **************************************WS****************************************** *********************************************************************************/ #ifdef WS_enable - ws.onEvent(onWsEvent); - server.addHandler(&ws); + ws.onEvent(onWsEvent); + server.addHandler(&ws); - events.onConnect([](AsyncEventSourceClient *client) { - //!!!client->send("hello!", NULL, millis(), 1000); - }); + events.onConnect([](AsyncEventSourceClient * client) { + //!!!client->send("hello!", NULL, millis(), 1000); + }); - server.addHandler(&events); + server.addHandler(&events); #endif - + /********************************************************************************* + **************************************WEB**************************************** + *********************************************************************************/ #ifdef ESP32 - server.addHandler(new SPIFFSEditor(SPIFFS, jsonReadStr(configSetupJson, "web_login").c_str(), jsonReadStr(configSetupJson, "web_pass").c_str())); + server.addHandler(new SPIFFSEditor(SPIFFS, jsonReadStr(configSetupJson, "weblogin").c_str(), jsonReadStr(configSetupJson, "webpass").c_str())); #elif defined(ESP8266) - server.addHandler(new SPIFFSEditor(jsonReadStr(configSetupJson, "web_login").c_str(), jsonReadStr(configSetupJson, "web_pass").c_str())); + server.addHandler(new SPIFFSEditor(jsonReadStr(configSetupJson, "weblogin").c_str(), jsonReadStr(configSetupJson, "webpass").c_str())); #endif - /* server.on("/heap", HTTP_GET, [](AsyncWebServerRequest * request) { + /* server.on("/heap", HTTP_GET, [](AsyncWebServerRequest * request) { request->send(200, "text/plain", String(ESP.getFreeHeap())); });*/ - server.serveStatic("/css/", SPIFFS, "/css/").setCacheControl("max-age=31536000"); - server.serveStatic("/js/", SPIFFS, "/js/").setCacheControl("max-age=31536000"); - server.serveStatic("/favicon.ico", SPIFFS, "/favicon.ico").setCacheControl("max-age=31536000"); + server.serveStatic("/css/", SPIFFS, "/css/").setCacheControl("max-age=31536000"); + server.serveStatic("/js/", SPIFFS, "/js/").setCacheControl("max-age=31536000"); + server.serveStatic("/favicon.ico", SPIFFS, "/favicon.ico").setCacheControl("max-age=31536000"); + server.serveStatic("/icon.jpeg", SPIFFS, "/icon.jpeg").setCacheControl("max-age=31536000"); - server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm").setAuthentication(jsonReadStr(configSetupJson, "web_login").c_str(), jsonReadStr(configSetupJson, "web_pass").c_str()); + server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm") + .setAuthentication(jsonReadStr(configSetupJson, "weblogin").c_str(), jsonReadStr(configSetupJson, "webpass").c_str()); - server.onNotFound([](AsyncWebServerRequest *request) { - Serial.printf("NOT_FOUND: "); - if (request->method() == HTTP_GET) - Serial.printf("GET"); - else if (request->method() == HTTP_POST) - Serial.printf("POST"); - else if (request->method() == HTTP_DELETE) - Serial.printf("DELETE"); - else if (request->method() == HTTP_PUT) - Serial.printf("PUT"); - else if (request->method() == HTTP_PATCH) - Serial.printf("PATCH"); - else if (request->method() == HTTP_HEAD) - Serial.printf("HEAD"); - else if (request->method() == HTTP_OPTIONS) - Serial.printf("OPTIONS"); - else - Serial.printf("UNKNOWN"); - Serial.printf(" http://%s%s\n", request->host().c_str(), request->url().c_str()); + server.onNotFound([](AsyncWebServerRequest * request) { + Serial.printf("NOT_FOUND: "); + if (request->method() == HTTP_GET) + Serial.printf("GET"); + else if (request->method() == HTTP_POST) + Serial.printf("POST"); + else if (request->method() == HTTP_DELETE) + Serial.printf("DELETE"); + else if (request->method() == HTTP_PUT) + Serial.printf("PUT"); + else if (request->method() == HTTP_PATCH) + Serial.printf("PATCH"); + else if (request->method() == HTTP_HEAD) + Serial.printf("HEAD"); + else if (request->method() == HTTP_OPTIONS) + Serial.printf("OPTIONS"); + else + Serial.printf("UNKNOWN"); + Serial.printf(" http://%s%s\n", request->host().c_str(), request->url().c_str()); - if (request->contentLength()) { - Serial.printf("_CONTENT_TYPE: %s\n", request->contentType().c_str()); - Serial.printf("_CONTENT_LENGTH: %u\n", request->contentLength()); - } + if (request->contentLength()) { + Serial.printf("_CONTENT_TYPE: %s\n", request->contentType().c_str()); + Serial.printf("_CONTENT_LENGTH: %u\n", request->contentLength()); + } - int headers = request->headers(); - int i; - for (i = 0; i < headers; i++) { - AsyncWebHeader *h = request->getHeader(i); - Serial.printf("_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str()); - } + int headers = request->headers(); + int i; + for (i = 0; i < headers; i++) { + AsyncWebHeader* h = request->getHeader(i); + Serial.printf("_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str()); + } - int params = request->params(); - for (i = 0; i < params; i++) { - AsyncWebParameter *p = request->getParam(i); - if (p->isFile()) { - Serial.printf("_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size()); - } else if (p->isPost()) { - Serial.printf("_POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); - } else { - Serial.printf("_GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); - } - } + int params = request->params(); + for (i = 0; i < params; i++) { + AsyncWebParameter* p = request->getParam(i); + if (p->isFile()) { + Serial.printf("_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size()); + } else if (p->isPost()) { + Serial.printf("_POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); + } else { + Serial.printf("_GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); + } + } - request->send(404); - }); + request->send(404); + }); - server.onFileUpload([](AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) { - if (!index) - Serial.printf("UploadStart: %s\n", filename.c_str()); - Serial.printf("%s", (const char *)data); - if (final) - Serial.printf("UploadEnd: %s (%u)\n", filename.c_str(), index + len); - }); - server.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) { - if (!index) - Serial.printf("BodyStart: %u\n", total); - Serial.printf("%s", (const char *)data); - if (index + len == total) - Serial.printf("BodyEnd: %u\n", total); - }); + server.onFileUpload([](AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t *data, size_t len, bool final) { + if (!index) + Serial.printf("UploadStart: %s\n", filename.c_str()); + Serial.printf("%s", (const char*)data); + if (final) + Serial.printf("UploadEnd: %s (%u)\n", filename.c_str(), index + len); + }); - server.begin(); - // --------------------Выдаем данные configLiveJson //config.live.json - динамические данные - server.on("/config.live.json", HTTP_GET, [](AsyncWebServerRequest *request) { - request->send(200, "application/json", configLiveJson); - }); - // --------------------Выдаем данные configOptionJson //config.option.json - данные не являющиеся событиями - server.on("/config.option.json", HTTP_GET, [](AsyncWebServerRequest *request) { - request->send(200, "application/json", configOptionJson); - }); - // -------------------Выдаем данные configSetupJson //config.setup.json - для хранения постоянных данных - server.on("/config.setup.json", HTTP_GET, [](AsyncWebServerRequest *request) { - request->send(200, "application/json", configSetupJson); - }); + server.onRequestBody([](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) { + if (!index) + Serial.printf("BodyStart: %u\n", total); + Serial.printf("%s", (const char*)data); + if (index + len == total) + Serial.printf("BodyEnd: %u\n", total); + }); - // ------------------Выполнение команды из запроса - //http://192.168.88.45/cmd?command=rel%201%201 - server.on("/cmd", HTTP_GET, [](AsyncWebServerRequest *request) { - String com = request->getParam("command")->value(); - Serial.println(com); - order_loop += com + ","; - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении - }); + server.begin(); + + // --------------------Выдаем данные configJson //config.live.json - динамические данные + server.on("/config.live.json", HTTP_GET, [](AsyncWebServerRequest * request) { + request->send(200, "application/json", configLiveJson); + }); + // --------------------Выдаем данные optionJson //config.option.json - данные не являющиеся событиями + server.on("/config.option.json", HTTP_GET, [](AsyncWebServerRequest * request) { + request->send(200, "application/json", configOptionJson); + }); + // -------------------Выдаем данные configSetup //config.setup.json - для хранения постоянных данных + server.on("/config.setup.json", HTTP_GET, [](AsyncWebServerRequest * request) { + request->send(200, "application/json", configSetupJson); + }); + + // ------------------Выполнение команды из запроса + //http://192.168.88.45/cmd?command=rel%201%201 + server.on("/cmd", HTTP_GET, [](AsyncWebServerRequest * request) { + String com = request->getParam("command")->value(); + Serial.println(com); + order_loop += com + ","; + request->send(200, "text/text", "OK"); // отправляем ответ о выполнении + }); } /********************************************************************************************************************************* *********************************************************WS********************************************************************** ********************************************************************************************************************************/ #ifdef WS_enable -void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { - if (type == WS_EVT_CONNECT) { - Serial.printf("ws[%s][%u] connect\n", server->url(), client->id()); - client->printf(json.c_str(), client->id()); - //client->ping(); - } else if (type == WS_EVT_DISCONNECT) { - Serial.printf("ws[%s][%u] disconnect\n", server->url(), client->id()); - } else if (type == WS_EVT_ERROR) { - Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t *)arg), (char *)data); - } else if (type == WS_EVT_PONG) { - Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len) ? (char *)data : ""); - } else if (type == WS_EVT_DATA) { - AwsFrameInfo *info = (AwsFrameInfo *)arg; - String msg = ""; - if (info->final && info->index == 0 && info->len == len) { - //the whole message is in a single frame and we got all of it's data - Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT) ? "text" : "binary", info->len); +void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) { + if (type == WS_EVT_CONNECT) { + Serial.printf("ws[%s][%u] connect\n", server->url(), client->id()); + client->printf(json.c_str(), client->id()); + //client->ping(); + } else if (type == WS_EVT_DISCONNECT) { + Serial.printf("ws[%s][%u] disconnect\n", server->url(), client->id()); + } else if (type == WS_EVT_ERROR) { + Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data); + } else if (type == WS_EVT_PONG) { + Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len) ? (char*)data : ""); + } else if (type == WS_EVT_DATA) { + AwsFrameInfo * info = (AwsFrameInfo*)arg; + String msg = ""; + if (info->final && info->index == 0 && info->len == len) { + //the whole message is in a single frame and we got all of it's data + Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT) ? "text" : "binary", info->len); - if (info->opcode == WS_TEXT) { - for (size_t i = 0; i < info->len; i++) { - msg += (char)data[i]; - } - } else { - char buff[3]; - for (size_t i = 0; i < info->len; i++) { - sprintf(buff, "%02x ", (uint8_t)data[i]); - msg += buff; - } - } - Serial.printf("%s\n", msg.c_str()); - - if (info->opcode == WS_TEXT) - client->text("{}"); - else - client->binary("{}"); - } else { - //message is comprised of multiple frames or the frame is split into multiple packets - if (info->index == 0) { - if (info->num == 0) - Serial.printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT) ? "text" : "binary"); - Serial.printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len); - } - - Serial.printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT) ? "text" : "binary", info->index, info->index + len); - - if (info->opcode == WS_TEXT) { - for (size_t i = 0; i < len; i++) { - msg += (char)data[i]; - } - } else { - char buff[3]; - for (size_t i = 0; i < len; i++) { - sprintf(buff, "%02x ", (uint8_t)data[i]); - msg += buff; - } - } - Serial.printf("%s\n", msg.c_str()); - - if ((info->index + len) == info->len) { - Serial.printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len); - if (info->final) { - Serial.printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT) ? "text" : "binary"); - if (info->message_opcode == WS_TEXT) - client->text("I got your text message"); - else - client->binary("I got your binary message"); - } - } + if (info->opcode == WS_TEXT) { + for (size_t i = 0; i < info->len; i++) { + msg += (char) data[i]; } + } else { + char buff[3]; + for (size_t i = 0; i < info->len; i++) { + sprintf(buff, "%02x ", (uint8_t) data[i]); + msg += buff ; + } + } + Serial.printf("%s\n", msg.c_str()); + + if (info->opcode == WS_TEXT) + client->text("{}"); + else + client->binary("{}"); + } else { + //message is comprised of multiple frames or the frame is split into multiple packets + if (info->index == 0) { + if (info->num == 0) + Serial.printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT) ? "text" : "binary"); + Serial.printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len); + } + + Serial.printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT) ? "text" : "binary", info->index, info->index + len); + + if (info->opcode == WS_TEXT) { + for (size_t i = 0; i < len; i++) { + msg += (char) data[i]; + } + } else { + char buff[3]; + for (size_t i = 0; i < len; i++) { + sprintf(buff, "%02x ", (uint8_t) data[i]); + msg += buff ; + } + } + Serial.printf("%s\n", msg.c_str()); + + if ((info->index + len) == info->len) { + Serial.printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len); + if (info->final) { + Serial.printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT) ? "text" : "binary"); + if (info->message_opcode == WS_TEXT) + client->text("I got your text message"); + else + client->binary("I got your binary message"); + } + } } + } } -#endif +#endif \ No newline at end of file diff --git a/src/WiFiUtils.cpp b/src/WiFiUtils.cpp index 18b55510..30c33f63 100644 --- a/src/WiFiUtils.cpp +++ b/src/WiFiUtils.cpp @@ -2,146 +2,88 @@ boolean RouterFind(String ssid); -void WIFI_init() -{ - // --------------------Получаем ssid password со страницы - server.on("/ssid", HTTP_GET, [](AsyncWebServerRequest *request) { - if (request->hasArg("ssid")) - { - jsonWriteStr(configSetupJson, "ssid", request->getParam("ssid")->value()); - } - if (request->hasArg("password")) - { - jsonWriteStr(configSetupJson, "password", request->getParam("password")->value()); - } - saveConfig(); // Функция сохранения данных во Flash - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении - }); - // --------------------Получаем ssidAP passwordAP со страницы - server.on("/ssidap", HTTP_GET, [](AsyncWebServerRequest *request) { - if (request->hasArg("ssidAP")) - { - jsonWriteStr(configSetupJson, "ssidAP", request->getParam("ssidAP")->value()); - } - if (request->hasArg("passwordAP")) - { - jsonWriteStr(configSetupJson, "passwordAP", request->getParam("passwordAP")->value()); - } - saveConfig(); // Функция сохранения данных во Flash - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении - }); +void ROUTER_Connecting() { + + led_blink("slow"); - // --------------------Получаем логин и пароль для web со страницы - server.on("/web", HTTP_GET, [](AsyncWebServerRequest *request) { - if (request->hasArg("web_login")) - { - jsonWriteStr(configSetupJson, "web_login", request->getParam("web_login")->value()); - } - if (request->hasArg("web_pass")) - { - jsonWriteStr(configSetupJson, "web_pass", request->getParam("web_pass")->value()); - } - saveConfig(); // Функция сохранения данных во Flash - //Web_server_init(); - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении - }); + WiFi.mode(WIFI_STA); - server.on("/restart", HTTP_GET, [](AsyncWebServerRequest *request) { - if (request->hasArg("device")) - { - if (request->getParam("device")->value() == "ok") - ESP.restart(); - } - request->send(200, "text/text", "OK"); // отправляем ответ о выполнении - }); - ROUTER_Connecting(); + byte tries = 20; + String _ssid = jsonReadStr(configSetupJson, "routerssid"); + String _password = jsonReadStr(configSetupJson, "routerpass"); + //WiFi.persistent(false); + + if (_ssid == "" && _password == "") { + WiFi.begin(); + } + else { + WiFi.begin(_ssid.c_str(), _password.c_str()); + Serial.print("ssid: "); + Serial.println(_ssid); + } + // Делаем проверку подключения до тех пор пока счетчик tries + // не станет равен нулю или не получим подключение + while (--tries && WiFi.status() != WL_CONNECTED) { + if (WiFi.status() == WL_CONNECT_FAILED) { + Serial.println("[E] password is not correct"); + tries = 1; + jsonWriteInt(configOptionJson, "pass_status", 1); + } + Serial.print("."); + delay(1000); + } + + if (WiFi.status() != WL_CONNECTED) + { + // Если не удалось подключиться запускаем в режиме AP + Serial.println(""); + // WiFi.disconnect(true); + StartAPMode(); + + } + else { + // Иначе удалось подключиться отправляем сообщение + // о подключении и выводим адрес IP + Serial.println(""); + Serial.println("[V] WiFi connected"); + Serial.print("[V] IP address: http://"); + Serial.print(WiFi.localIP()); + Serial.println(""); + jsonWriteStr(configSetupJson, "ip", WiFi.localIP().toString()); + led_blink("off"); + //add_dev_in_list("dev.txt", chipID, WiFi.localIP().toString()); + MQTT_init(); + } } -void ROUTER_Connecting() -{ - led_blink("slow"); +bool StartAPMode() { + Serial.println("WiFi up AP"); + WiFi.disconnect(); - WiFi.mode(WIFI_STA); + WiFi.mode(WIFI_AP); - byte tries = 20; - String _ssid = jsonReadStr(configSetupJson, "ssid"); - String _password = jsonReadStr(configSetupJson, "password"); - //WiFi.persistent(false); + String _ssidAP = jsonReadStr(configSetupJson, "apssid"); + String _passwordAP = jsonReadStr(configSetupJson, "appass"); + WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str()); + IPAddress myIP = WiFi.softAPIP(); + led_blink("on"); + Serial.print("AP IP address: "); + Serial.println(myIP); + jsonWriteStr(configSetupJson, "ip", myIP.toString()); - if (_ssid == "" && _password == "") - { - WiFi.begin(); - } - else - { - WiFi.begin(_ssid.c_str(), _password.c_str()); - Serial.print("ssid: "); - Serial.println(_ssid); - } - // Делаем проверку подключения до тех пор пока счетчик tries - // не станет равен нулю или не получим подключение - while (--tries && WiFi.status() != WL_CONNECTED) - { - if (WiFi.status() == WL_CONNECT_FAILED) - { - Serial.println("[E] password is not correct"); - tries = 1; - jsonWriteInt(configOptionJson, "pass_status", 1); - } - Serial.print("."); - delay(1000); - } - - Serial.println(); - if (WiFi.status() != WL_CONNECTED) - { - StartAPMode(); - } - else - { - Serial.println("[V] WiFi connected"); - Serial.print("[V] IP address: http://"); - Serial.print(WiFi.localIP()); - Serial.println(); - - jsonWriteStr(configLiveJson, "ip", WiFi.localIP().toString()); - led_blink("off"); - } + //if (jsonReadInt(configOptionJson, "pass_status") != 1) { + ts.add(ROUTER_SEARCHING, 10 * 1000, [&](void*) { + Serial.println("->try find router"); + if (RouterFind(jsonReadStr(configSetupJson, "routerssid"))) { + ts.remove(ROUTER_SEARCHING); + WiFi.scanDelete(); + ROUTER_Connecting(); + } + }, nullptr, true); + //} + return true; } -bool StartAPMode() -{ - Serial.println("WiFi up AP"); - WiFi.disconnect(); - - WiFi.mode(WIFI_AP); - - String _ssidAP = jsonReadStr(configSetupJson, "ssidAP"); - String _passwordAP = jsonReadStr(configSetupJson, "passwordAP"); - WiFi.softAP(_ssidAP.c_str(), _passwordAP.c_str()); - IPAddress myIP = WiFi.softAPIP(); - led_blink("on"); - Serial.print("AP IP address: "); - Serial.println(myIP); - jsonWriteStr(configLiveJson, "ip", myIP.toString()); - - if (jsonReadInt(configOptionJson, "pass_status") != 1) - { - ts.add( - ROUTER_SEARCHING, 10 * 1000, [&](void *) { - Serial.println("->try find router"); - if (RouterFind(jsonReadStr(configSetupJson, "ssid"))) - { - ts.remove(ROUTER_SEARCHING); - WiFi.scanDelete(); - ROUTER_Connecting(); - MQTT_init(); - } - }, - nullptr, true); - } - return true; -} boolean RouterFind(String ssid) { @@ -191,4 +133,4 @@ boolean RouterFind(String ssid) WiFi.scanDelete(); } return res; -} +} \ No newline at end of file diff --git a/src/Widgets.cpp b/src/Widgets.cpp index b7d841aa..62ae8edf 100644 --- a/src/Widgets.cpp +++ b/src/Widgets.cpp @@ -1,79 +1,90 @@ #include "Global.h" -void createWidget(String widget_name, String page_name, String page_number, String file, String topic) { - String widget; - widget = readFile(file, 1024); - if (widget == "Failed") return; - if (widget == "Large") return; - widget_name.replace("#", " "); - page_name.replace("#", " "); - jsonWriteStr(widget, "page", page_name); - jsonWriteStr(widget, "order", page_number); - jsonWriteStr(widget, "descr", widget_name); - jsonWriteStr(widget, "topic", prex + "/" + topic); +//====================================================================================================================== +//===============================================Создание виджетов======================================================= +void createWidget (String widget_name, String page_name, String page_number, String file, String topic) { + + String widget; + widget = readFile(file, 1024); + + if (widget == "Failed") return; + if (widget == "Large") return; + + widget_name.replace("#", " "); + page_name.replace("#", " "); + + jsonWriteStr(widget, "page", page_name); + jsonWriteStr(widget, "order", page_number); + jsonWriteStr(widget, "descr", widget_name); + jsonWriteStr(widget, "topic", prex + "/" + topic); + #ifdef layout_in_ram - all_widgets += widget + "\r\n"; + all_widgets += widget + "\r\n"; #else - addFile("layout.txt", widget); + addFile("layout.txt", widget); #endif - widget = ""; + widget = ""; } -void createWidgetParam(String widget_name, String page_name, String page_number, String file, String topic, String name1, String param1, String name2, String param2, String name3, String param3) { - String widget; - widget = readFile(file, 1024); +void createWidgetParam (String widget_name, String page_name, String page_number, String file, String topic, String name1, String param1, String name2, String param2, String name3, String param3) { - if (widget == "Failed") return; - if (widget == "Large") return; + String widget; + widget = readFile(file, 1024); - widget_name.replace("#", " "); - page_name.replace("#", " "); + if (widget == "Failed") return; + if (widget == "Large") return; - jsonWriteStr(widget, "page", page_name); - jsonWriteStr(widget, "order", page_number); - jsonWriteStr(widget, "descr", widget_name); - jsonWriteStr(widget, "topic", prex + "/" + topic); + widget_name.replace("#", " "); + page_name.replace("#", " "); - if (name1 != "") jsonWriteStr(widget, name1, param1); - if (name2 != "") jsonWriteStr(widget, name2, param2); - if (name3 != "") jsonWriteStr(widget, name3, param3); + jsonWriteStr(widget, "page", page_name); + jsonWriteStr(widget, "order", page_number); + jsonWriteStr(widget, "descr", widget_name); + jsonWriteStr(widget, "topic", prex + "/" + topic); + + if (name1 != "") jsonWriteStr(widget, name1, param1); + if (name2 != "") jsonWriteStr(widget, name2, param2); + if (name3 != "") jsonWriteStr(widget, name3, param3); #ifdef layout_in_ram - all_widgets += widget + "\r\n"; + all_widgets += widget + "\r\n"; #else - addFile("layout.txt", widget); + addFile("layout.txt", widget); #endif - widget = ""; + widget = ""; } -void createChart(String widget_name, String page_name, String page_number, String file, String topic, String maxCount) { - String widget; - widget = readFile(file, 1024); +void createChart (String widget_name, String page_name, String page_number, String file, String topic, String maxCount) { - if (widget == "Failed") return; - if (widget == "Large") return; + String widget; + widget = readFile(file, 1024); - widget_name.replace("#", " "); - page_name.replace("#", " "); + if (widget == "Failed") return; + if (widget == "Large") return; - jsonWriteStr(widget, "page", page_name); - jsonWriteStr(widget, "order", page_number); - //jsonWriteStr(widget, "descr", widget_name); - jsonWriteStr(widget, "series", widget_name); - jsonWriteStr(widget, "maxCount", maxCount); - jsonWriteStr(widget, "topic", prex + "/" + topic); + widget_name.replace("#", " "); + page_name.replace("#", " "); + + jsonWriteStr(widget, "page", page_name); + jsonWriteStr(widget, "order", page_number); + //jsonWriteStr(widget, "descr", widget_name); + jsonWriteStr(widget, "series", widget_name); + jsonWriteStr(widget, "maxCount", maxCount); + jsonWriteStr(widget, "topic", prex + "/" + topic); #ifdef layout_in_ram - all_widgets += widget + "\r\n"; + all_widgets += widget + "\r\n"; #else - addFile("layout.txt", widget); + addFile("layout.txt", widget); #endif - widget = ""; + widget = ""; } void choose_widget_and_create(String widget_name, String page_name, String page_number, String type, String topik) { - if (type == "any-data") createWidget(widget_name, page_name, page_number, "widgets/widget.anyData.json", topik); - if (type == "progress-line") createWidget(widget_name, page_name, page_number, "widgets/widget.progLine.json", topik); - if (type == "progress-round") createWidget(widget_name, page_name, page_number, "widgets/widget.progRound.json", topik); - if (type == "fill-gauge") createWidget(widget_name, page_name, page_number, "widgets/widget.fillGauge.json", topik); -} + + if (type == "any-data") createWidget (widget_name, page_name, page_number, "widgets/widget.anyData.json", topik); + if (type == "progress-line") createWidget (widget_name, page_name, page_number, "widgets/widget.progLine.json", topik); + if (type == "progress-round") createWidget (widget_name, page_name, page_number, "widgets/widget.progRound.json", topik); + if (type == "fill-gauge") createWidget (widget_name, page_name, page_number, "widgets/widget.fillGauge.json", topik); + +} \ No newline at end of file diff --git a/src/i2c_bus.cpp b/src/i2c_bus.cpp index abf28a9a..bbcd8b29 100644 --- a/src/i2c_bus.cpp +++ b/src/i2c_bus.cpp @@ -1,35 +1,35 @@ #include "Global.h" void do_i2c_scanning() { - if (i2c_scanning) { - i2c_scanning = false; - String tmp = i2c_scan(); - if (tmp == "error") { - tmp = i2c_scan(); - Serial.println(tmp); - jsonWriteStr(configLiveJson, "i2c", tmp); - } else { - Serial.println(tmp); - jsonWriteStr(configLiveJson, "i2c", tmp); - } + if (i2c_scanning) { + i2c_scanning = false; + String tmp = i2c_scan(); + if (tmp == "error") { + tmp = i2c_scan(); + Serial.println(tmp); + jsonWriteStr(configLiveJson, "i2c", tmp); + } else { + Serial.println(tmp); + jsonWriteStr(configLiveJson, "i2c", tmp); } + } } String i2c_scan() { - String out; - byte count = 0; - Wire.begin(); - for (byte i = 8; i < 120; i++) { - Wire.beginTransmission(i); - if (Wire.endTransmission() == 0) { - count++; - out += String(count) + ". 0x" + String(i, HEX) + "; "; - delay(1); - } + String out; + byte count = 0; + Wire.begin(); + for (byte i = 8; i < 120; i++) { + Wire.beginTransmission(i); + if (Wire.endTransmission() == 0) { + count++; + out += String(count) + ". 0x" + String(i, HEX) + "; "; + delay(1); } - if (count == 0) { - return "error"; - } else { - return out; - } -} + } + if (count == 0) { + return "error"; + } else { + return out; + } +} \ No newline at end of file diff --git a/src/iot_firmware.cpp b/src/iot_firmware.cpp index b13f4b00..84534bda 100644 --- a/src/iot_firmware.cpp +++ b/src/iot_firmware.cpp @@ -1,85 +1,84 @@ #include "Global.h" void setup() { - File_system_init(); - Serial.println("SPIFFS_init"); - - CMD_init(); - Serial.println("[V] CMD_init"); - - sensors_init(); - Serial.println("[V] sensors_init"); - - All_init(); - Serial.println("[V] All_init"); - //-------------------------------------------------------------- - WIFI_init(); - Serial.println("[V] WIFI_init"); - //-------------------------------------------------------------- - statistics_init(); - Serial.println("[V] statistics_init"); - //-------------------------------------------------------------- - initUpgrade(); - Serial.println("[V] initUpgrade"); - //-------------------------------------------------------------- - Web_server_init(); - Serial.println("[V] Web_server_init"); - //-------------------------------------------------------------- - MQTT_init(); - Serial.println("[V] MQTT_init"); - //-------------------------------------------------------------- - Time_Init(); - Serial.println("[V] Time_Init"); - //-------------------------------------------------------------- -#ifdef push_enable - Push_init(); - Serial.println("[V] Push_init"); -#endif - //-------------------------------------------------------------- + //-------------------------------------------------------------- + File_system_init(); + Serial.println("SPIFFS_init"); + //-------------------------------------------------------------- + CMD_init(); + Serial.println("[V] CMD_init"); + //-------------------------------------------------------------- + sensors_init(); + Serial.println("[V] sensors_init"); + //-------------------------------------------------------------- + All_init(); + Serial.println("[V] All_init"); + //-------------------------------------------------------------- + ROUTER_Connecting(); + Serial.println("[V] ROUTER_Connecting"); + //-------------------------------------------------------------- + uptime_init(); + Serial.println("[V] statistics_init"); + //-------------------------------------------------------------- + initUpgrade(); + Serial.println("[V] initUpgrade"); + //-------------------------------------------------------------- + Web_server_init(); + Serial.println("[V] Web_server_init"); + //-------------------------------------------------------------- + web_init(); + Serial.println("[V] web_init"); + //-------------------------------------------------------------- + Time_Init(); + Serial.println("[V] Time_Init"); + //-------------------------------------------------------------- #ifdef UDP_enable - UDP_init(); - Serial.println("[V] UDP_init"); + UDP_init(); + Serial.println("[V] UDP_init"); #endif - //-------------------------------------------------------------- + //-------------------------------------------------------------- - ts.add( - TEST, 10000, [&](void*) { - getMemoryLoad("[i] periodic check of"); - //ws.textAll(json); - }, - nullptr, true); - just_load = false; + + ts.add(TEST, 10000, [&](void*) { + getMemoryLoad("[i] periodic check of"); + //ws.textAll(json); + }, nullptr, true); + + + just_load = false; } + void loop() { + #ifdef OTA_enable - ArduinoOTA.handle(); + ArduinoOTA.handle(); #endif #ifdef WS_enable - ws.cleanupClients(); + ws.cleanupClients(); #endif - not_async_actions(); + not_async_actions(); - handleMQTT(); - handleCMD_loop(); - handleButton(); - handleScenario(); + handleMQTT(); + handleCMD_loop(); + handleButton(); + handleScenario(); #ifdef UDP_enable - handleUdp(); + handleUdp(); #endif - ts.update(); + ts.update(); } void not_async_actions() { - do_mqtt_connection(); - do_upgrade_url(); - do_upgrade(); + do_mqtt_connection(); + do_upgrade_url(); + do_upgrade(); #ifdef UDP_enable - do_udp_data_parse(); - do_mqtt_send_settings_to_udp(); + do_udp_data_parse(); + do_mqtt_send_settings_to_udp(); #endif - do_i2c_scanning(); -} + do_i2c_scanning(); +} \ No newline at end of file diff --git a/src/udp.cpp b/src/udp.cpp index 5832fe22..3f88a099 100644 --- a/src/udp.cpp +++ b/src/udp.cpp @@ -5,41 +5,7 @@ void add_dev_in_list(String fileName, String id, String dev_name, String ip); #ifdef UDP_enable void UDP_init() { - server.on("/udp", HTTP_GET, [](AsyncWebServerRequest * request) { - String value; - if (request->hasArg("arg")) { - value = request->getParam("arg")->value(); - } - if (value == "0") { - jsonWriteStr(configSetupJson, "udponoff", value); - request->send(200, "text/text", "ok"); - } - if (value == "1") { - jsonWriteStr(configSetupJson, "udponoff", value); - request->send(200, "text/text", "ok"); - } - if (value == "2") { - mqtt_send_settings_to_udp = true; - request->send(200, "text/text", "ok"); - } - if (value == "3") { - SPIFFS.remove("/dev.csv"); - addFile("dev.csv", "device id;device name;ip address"); - request->redirect("/?dev"); - } - if (value == "4") { - request->redirect("/?dev"); - } - }); - server.on("/name", HTTP_GET, [](AsyncWebServerRequest * request) { - if (request->hasArg("arg")) { - jsonWriteStr(configSetupJson, "name", request->getParam("arg")->value()); - jsonWriteStr(configLiveJson, "name", request->getParam("arg")->value()); - saveConfig(); - } - request->send(200, "text/text", "OK"); - }); - + SPIFFS.remove("/dev.csv"); addFile("dev.csv", "device id;device name;ip address"); @@ -180,4 +146,4 @@ void do_mqtt_send_settings_to_udp() { send_mqtt_to_udp(); } } -#endif +#endif \ No newline at end of file From b044497c8e74c45230603823f7f57678a7549e4b Mon Sep 17 00:00:00 2001 From: Yuri Trikoz Date: Fri, 19 Jun 2020 23:34:30 +0300 Subject: [PATCH 13/17] fix --- include/Global.h | 60 +++++++++++++++++++++++++++++------------------- src/Global.cpp | 14 ++++------- 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/include/Global.h b/include/Global.h index 5bf3e39c..c06a84cc 100644 --- a/include/Global.h +++ b/include/Global.h @@ -6,21 +6,22 @@ #include #include extern AsyncWebServer server; +#include +#include +#include +#include #include +#include #include #include #include #include -#include -#include "Consts.h" #include -#include "GyverFilters.h" -#include -#include -#include #include -#include -#include +#include + +#include "Consts.h" +#include "GyverFilters.h" //==============ESP8266 БИБЛИОТЕКИ=============== #ifdef ESP8266 #include @@ -39,26 +40,24 @@ WiFiUDP Udp; #ifdef ESP32 #include #include +#include #include #include #include #include #include extern AsyncUDP udp; -#include #ifdef MDNS_enable #include #endif #endif -extern Servo myServo1; -extern Servo myServo2; - #ifdef OTA_enable #include #endif - +extern Servo myServo1; +extern Servo myServo2; //==============================Objects.h(без данных)================================== @@ -69,7 +68,25 @@ extern AsyncWebSocket ws; //extern AsyncEventSource events; extern TickerScheduler ts; -enum {ROUTER_SEARCHING, WIFI_MQTT_CONNECTION_CHECK, SENSORS, STEPPER1, STEPPER2, LOG1, LOG2, LOG3, LOG4, LOG5, TIMER_COUNTDOWN, TIME, TIME_SYNC, STATISTICS, UPTIME, UDP, UDP_DB, TEST }; + +enum { ROUTER_SEARCHING, + WIFI_MQTT_CONNECTION_CHECK, + SENSORS, + STEPPER1, + STEPPER2, + LOG1, + LOG2, + LOG3, + LOG4, + LOG5, + TIMER_COUNTDOWN, + TIME, + TIME_SYNC, + STATISTICS, + UPTIME, + UDP, + UDP_DB, + TEST }; extern WiFiClient espClient; @@ -83,9 +100,9 @@ extern AsyncWebServer server; //AsyncEventSource events; -#define NUM_BUTTONS +#define NUM_BUTTONS 6 extern boolean but[NUM_BUTTONS]; -extern Bounce * buttons; +extern Bounce *buttons; extern GMedian<10, int> medianFilter; @@ -103,7 +120,7 @@ extern Adafruit_Sensor *bme_temp; extern Adafruit_Sensor *bme_pressure; extern Adafruit_Sensor *bme_humidity; -uptime_interval myUpTime; +extern uptime_interval myUpTime; ///////////////////////////////////// Global vars //////////////////////////////////////////////////////////////////// @@ -114,13 +131,12 @@ extern String received_ip; extern String received_udp_line; extern int udp_period; - extern boolean just_load; extern const char *hostName; -extern String configSetupJson; //все настройки -extern String configLiveJson; //все данные с датчиков (связан с mqtt) -extern String configOptionJson; //для трансфера +extern String configSetupJson; //все настройки +extern String configLiveJson; //все данные с датчиков (связан с mqtt) +extern String configOptionJson; //для трансфера extern String chipID; extern String prex; @@ -166,7 +182,6 @@ extern boolean i2c_scanning; extern int sensors_reading_map[15]; - ///////////////////////////////////// Functions//////////////////////////////////////////////////////////////////// // StringUtils @@ -284,7 +299,6 @@ extern void levelPr(); extern void ultrasonicCm(); extern void ultrasonic_reading(); - extern void analog(); extern void analog_reading1(); extern void analog_reading2(); diff --git a/src/Global.cpp b/src/Global.cpp index 158c2b27..0df8a01a 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -1,4 +1,5 @@ #include "Global.h" + #include "JsonUtils.h" //==============================Objects.cpp(с данными)================================== @@ -23,9 +24,8 @@ AsyncWebServer server(80); //AsyncEventSource events("/events"); -#define NUM_BUTTONS 6 boolean but[NUM_BUTTONS]; -Bounce * buttons = new Bounce[NUM_BUTTONS]; +Bounce *buttons = new Bounce[NUM_BUTTONS]; GMedian<10, int> medianFilter; @@ -34,6 +34,9 @@ DallasTemperature sensors; DHTesp dht; +Servo myServo1; +Servo myServo2; + Adafruit_BMP280 bmp; Adafruit_Sensor *bmp_temp; Adafruit_Sensor *bmp_pressure; @@ -106,12 +109,9 @@ boolean udp_data_parse = false; boolean mqtt_send_settings_to_udp = false; boolean i2c_scanning = false; - - //Buttons //boolean but[6]; - // Udp boolean udp_busy = false; unsigned int udp_port = 4210; @@ -128,7 +128,3 @@ int udp_period; // i2c String i2c_list; - - - - From 8ec105d0b26124ddedc372a5cbcbd104ca9c024a Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Sat, 20 Jun 2020 00:46:25 +0200 Subject: [PATCH 14/17] Change Version --- include/Consts.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Consts.h b/include/Consts.h index 30c750ae..b5ff4192 100644 --- a/include/Consts.h +++ b/include/Consts.h @@ -1,7 +1,7 @@ #pragma once //Здесь хранятся все настройки прошивки -#define firmware_version "2.3.3" +#define firmware_version "2.3.4" /* * Firmware settings From 734edf522dde4583c8c20a1cb001159c82362c5a Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Sat, 20 Jun 2020 00:56:50 +0200 Subject: [PATCH 15/17] version changed --- include/Consts.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Consts.h b/include/Consts.h index 30c750ae..b582eb36 100644 --- a/include/Consts.h +++ b/include/Consts.h @@ -1,7 +1,7 @@ #pragma once //Здесь хранятся все настройки прошивки -#define firmware_version "2.3.3" +#define firmware_version "2.3.4p" /* * Firmware settings From 66d3754cc496aef9f0127e2de3e533d26ea450c3 Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Sat, 20 Jun 2020 01:06:39 +0200 Subject: [PATCH 16/17] Some Changes test --- include/Consts.h | 2 +- src/Sensors.cpp | 4 ++-- src/Upgrade.cpp | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/include/Consts.h b/include/Consts.h index b582eb36..b5ff4192 100644 --- a/include/Consts.h +++ b/include/Consts.h @@ -1,7 +1,7 @@ #pragma once //Здесь хранятся все настройки прошивки -#define firmware_version "2.3.4p" +#define firmware_version "2.3.4" /* * Firmware settings diff --git a/src/Sensors.cpp b/src/Sensors.cpp index badfc9a2..14e1801e 100644 --- a/src/Sensors.cpp +++ b/src/Sensors.cpp @@ -216,9 +216,9 @@ void analog_reading2() { //=========================================Модуль температурного сенсора ds18b20=========================================================== #ifdef dallas_enable void dallas() { - String value_name = sCmd.next(); + //String value_name = sCmd.next(); String pin = sCmd.next(); - String address = sCmd.next(); + //String address = sCmd.next(); String widget_name = sCmd.next(); String page_name = sCmd.next(); String type = sCmd.next(); diff --git a/src/Upgrade.cpp b/src/Upgrade.cpp index 329588fd..39183cb4 100644 --- a/src/Upgrade.cpp +++ b/src/Upgrade.cpp @@ -1,5 +1,4 @@ #include "Global.h" - void initUpgrade() { #ifdef ESP8266 if (WiFi.status() == WL_CONNECTED) last_version = getURL("http://91.204.228.124:1100/update/esp8266/version.txt"); From 465c393db4979ab965a723b68a181b5cbdb4a0fa Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Sat, 20 Jun 2020 02:00:56 +0200 Subject: [PATCH 17/17] Problems with unused vars fixed --- src/Cmd.cpp | 6 +++--- src/Mqtt.cpp | 4 ++-- src/Sensors.cpp | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Cmd.cpp b/src/Cmd.cpp index 8a792241..13bee85e 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -198,7 +198,7 @@ void pinChange() { //==========================================Модуль управления ШИМ=================================================== void pwm() { - static boolean flag = true; + //static boolean flag = true; String pwm_number = sCmd.next(); String pwm_pin = sCmd.next(); String widget_name = sCmd.next(); @@ -469,7 +469,7 @@ void servoSet() { String servo_state = sCmd.next(); int servo_state_int = servo_state.toInt(); - int pin = jsonReadInt(configOptionJson, "servo_pin" + servo_number); + //int pin = jsonReadInt(configOptionJson, "servo_pin" + servo_number); servo_state_int = map(servo_state_int, jsonReadInt(configOptionJson, "s_min_val" + servo_number), @@ -531,7 +531,7 @@ void mqttOrderSend() { //Serial.print(all_line); //Serial.print("->"); //Serial.println(order); - int send_status = client_mqtt.publish (all_line.c_str(), order.c_str(), false); + client_mqtt.publish (all_line.c_str(), order.c_str(), false); } void httpOrderSend() { diff --git a/src/Mqtt.cpp b/src/Mqtt.cpp index bdf03cf3..f16c0a89 100644 --- a/src/Mqtt.cpp +++ b/src/Mqtt.cpp @@ -166,13 +166,13 @@ void sendSTATUS(String topik, String state) { topik = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipID + "/" + topik + "/" + "status"; String json_ = "{}"; jsonWriteStr(json_, "status", state); - int send_status = client_mqtt.publish (topik.c_str(), json_.c_str(), false); + 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"; - int send_status = client_mqtt.publish (all_line.c_str(), state.c_str(), false); + client_mqtt.publish (all_line.c_str(), state.c_str(), false); } //=====================================================ОТПРАВЛЯЕМ ВИДЖЕТЫ======================================================== diff --git a/src/Sensors.cpp b/src/Sensors.cpp index 14e1801e..8e7deaf5 100644 --- a/src/Sensors.cpp +++ b/src/Sensors.cpp @@ -392,7 +392,7 @@ void dhtC_reading() { if (dht.getStatus() != 0) { sendSTATUS("dhtComfort", String(dht.getStatusString())); } else { - float value = dht.getComfortRatio(cf, jsonReadStr(configLiveJson, dhtT_value_name).toFloat(), jsonReadStr(configLiveJson, dhtH_value_name).toFloat(), false); + 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", ""); @@ -486,7 +486,7 @@ void bmp280T() { void bmp280T_reading() { float value = 0; - sensors_event_t temp_event, pressure_event; + sensors_event_t temp_event; bmp_temp->getEvent(&temp_event); value = temp_event.temperature; jsonWriteStr(configLiveJson, bmp280T_value_name, String(value)); @@ -517,7 +517,7 @@ void bmp280P() { void bmp280P_reading() { float value = 0; - sensors_event_t temp_event, pressure_event; + sensors_event_t pressure_event; bmp_pressure->getEvent(&pressure_event); value = pressure_event.pressure; value = value / 1.333224;