From 11265758220be08a7854c765f3874a03ac23c94b Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Sun, 1 Nov 2020 02:52:57 +0300 Subject: [PATCH] logging and udp --- data/config.json | 3 +- data/items/logging.txt | 1 + data/js/function.js.gz | Bin 19968 -> 19600 bytes data/set.dev.json | 46 ++++++++++++ data/set.device.json | 8 +- data/widgets/chart.json | 1 - include/Class/LineParsing.h | 34 ++++++++- include/Consts.h | 9 +-- include/ItemsCmd.h | 2 + include/RemoteOrdersUdp.h | 14 ++-- src/Global.cpp | 2 +- src/Init.cpp | 2 + src/ItemsCmd.cpp | 2 + src/Logging.cpp | 8 +- src/RemoteOrdersUdp.cpp | 141 ++++++++++++++++++------------------ src/Web.cpp | 8 ++ src/items/LoggingClass.cpp | 46 ++++++++---- src/main.cpp | 14 ++-- 18 files changed, 223 insertions(+), 118 deletions(-) create mode 100644 data/items/logging.txt create mode 100644 data/set.dev.json diff --git a/data/config.json b/data/config.json index b00e72d2..8c8b402a 100644 --- a/data/config.json +++ b/data/config.json @@ -18,5 +18,6 @@ "webpass": "admin", "udponoff": "1", "blink": "0", - "oneWirePin": "2" + "oneWirePin": "2", + "serverip": "http://206.189.49.244" } \ No newline at end of file diff --git a/data/items/logging.txt b/data/items/logging.txt new file mode 100644 index 00000000..8253774f --- /dev/null +++ b/data/items/logging.txt @@ -0,0 +1 @@ +0;logging;id;chart;Графики;История;order;val[any];int[60];cnt[100] \ No newline at end of file diff --git a/data/js/function.js.gz b/data/js/function.js.gz index 10c9953a47611e6b2c069ab310523899a333426b..b3e5ea5658d55bfba215fecefda2a81e34ffcc98 100644 GIT binary patch literal 19600 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 LkbhLfBwPUi)kAo- literal 19968 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 PF3kT2-j(9{2V4OF<@%y0 diff --git a/data/set.dev.json b/data/set.dev.json new file mode 100644 index 00000000..fb697b50 --- /dev/null +++ b/data/set.dev.json @@ -0,0 +1,46 @@ +{ + "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": "Адрес сервера обновлений" + }, + { + "type": "input", + "title": "ip address", + "name": "serverip-arg", + "state": "{{serverip}}" + }, + { + "type": "button", + "title": "{{ButSave}}", + "action": "set?serverip=[[serverip-arg]]", + "class": "btn btn-block btn-default" + }, + { + "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/set.device.json b/data/set.device.json index e6d6698e..e504dd19 100644 --- a/data/set.device.json +++ b/data/set.device.json @@ -75,7 +75,8 @@ "/set?addItem=bmp280-temp": "18.Датчик температуры bmp280", "/set?addItem=bmp280-press": "19.Датчик давления bmp280", "/set?addItem=modbus": "20.Прочитать регистр modbus устройства", - "/set?addItem=uptime": "a.Отобразить время работы устройства" + "/set?addItem=logging": "a.Логгирование и вывод в график любой величины", + "/set?addItem=uptime": "b.Отобразить время работы устройства" } }, @@ -98,6 +99,9 @@ "action": "/set?saveItems", "class": "btn btn-block btn-default" }, + { + "type": "hr" + }, { "type": "link", "title": "Удалить выбранные элементы", @@ -112,7 +116,7 @@ }, { "type": "text", - "title": "

После любого изменения таблицы элементов, включая удаление/добавление строк, необходимо нажать кнопку Save

" + "title": "

После любого изменения таблицы элементов, включая удаление/добавление строк, необходимо нажать кнопку Сохранить таблицу

" }, { "type": "h2", diff --git a/data/widgets/chart.json b/data/widgets/chart.json index 47c6473b..9ecc61e3 100644 --- a/data/widgets/chart.json +++ b/data/widgets/chart.json @@ -1,5 +1,4 @@ { "widget": "chart", - "series": "Temperature, °C", "dateFormat": "HH:mm" } \ No newline at end of file diff --git a/include/Class/LineParsing.h b/include/Class/LineParsing.h index fa117948..faa4848e 100644 --- a/include/Class/LineParsing.h +++ b/include/Class/LineParsing.h @@ -12,7 +12,6 @@ class LineParsing { String _page; String _descr; String _order; - String _addr; String _reg; String _pin; @@ -22,6 +21,9 @@ class LineParsing { String _state; String _db; String _type; + String _int; + String _cnt; + String _val; public: LineParsing() : @@ -39,7 +41,10 @@ class LineParsing { _inv{""}, _state{""}, _db{""}, - _type{""} + _type{""}, + _int{""}, + _cnt{""}, + _val{""} {}; @@ -84,6 +89,15 @@ class LineParsing { if (arg.indexOf("reg[") != -1) { _reg = extractInner(arg); } + if (arg.indexOf("int[") != -1) { + _int = extractInner(arg); + } + if (arg.indexOf("cnt[") != -1) { + _cnt = extractInner(arg); + } + if (arg.indexOf("val[") != -1) { + _val = extractInner(arg); + } } } @@ -115,10 +129,10 @@ class LineParsing { return _order; } String gpin() { - return _pin; // + return _pin; } String ginv() { - return _inv; // + return _inv; } String gstate() { return _state; @@ -138,6 +152,15 @@ class LineParsing { String gregaddr() { return _reg; } + String gint() { + return _int; + } + String gmaxcnt() { + return _cnt; + } + String gvalue() { + return _val; + } void clear() { _key = ""; @@ -154,6 +177,9 @@ class LineParsing { _state = ""; _db = ""; _type = ""; + _int = ""; + _cnt = ""; + _val = ""; } String extractInnerDigit(String str) { diff --git a/include/Consts.h b/include/Consts.h index 8379bf8d..fcda15c4 100644 --- a/include/Consts.h +++ b/include/Consts.h @@ -44,7 +44,7 @@ //#define MDNS_ENABLED //#define WEBSOCKET_ENABLED //#define LAYOUT_IN_RAM -//#define UDP_ENABLED +#define UDP_ENABLED #define SSDP_ENABLED // @@ -88,13 +88,6 @@ enum TimerTask_t { WIFI_SCAN, WIFI_MQTT_CONNECTION_CHECK, SENSORS10SEC, SENSORS30SEC, - STEPPER1, - STEPPER2, - LOG1, - LOG2, - LOG3, - LOG4, - LOG5, TIMER_COUNTDOWN, TIME, TIME_SYNC, diff --git a/include/ItemsCmd.h b/include/ItemsCmd.h index 4330993f..24d04b67 100644 --- a/include/ItemsCmd.h +++ b/include/ItemsCmd.h @@ -49,3 +49,5 @@ extern void bmp280ReadingPress(); extern void sysUptime(); extern void uptimeReading(); + +extern void logging(); diff --git a/include/RemoteOrdersUdp.h b/include/RemoteOrdersUdp.h index 5aff5be4..a8c2d8e0 100644 --- a/include/RemoteOrdersUdp.h +++ b/include/RemoteOrdersUdp.h @@ -1,7 +1,7 @@ -//#pragma once -//#include "ESPAsyncUDP.h" -//extern AsyncUDP asyncUdp; -//extern void asyncUdpInit(); -//extern String uint8tToString(uint8_t* data, size_t len); -//extern bool udpPacketValidation(String& data); -//extern void udpPacketParse(String& data); \ No newline at end of file +#pragma once +#include "ESPAsyncUDP.h" +extern AsyncUDP asyncUdp; +extern void asyncUdpInit(); +extern String uint8tToString(uint8_t* data, size_t len); +extern bool udpPacketValidation(String& data); +extern void udpPacketParse(String& data); \ No newline at end of file diff --git a/src/Global.cpp b/src/Global.cpp index 4de7df8c..c47fe17e 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -47,7 +47,7 @@ String logging_value_names_list; int enter_to_logging_counter; // Upgrade -String serverIP = "http://206.189.49.244"; +String serverIP; // 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}; diff --git a/src/Init.cpp b/src/Init.cpp index f2e5c82e..8fc8f6aa 100644 --- a/src/Init.cpp +++ b/src/Init.cpp @@ -14,6 +14,8 @@ void loadConfig() { prex = jsonReadStr(configSetupJson, "mqttPrefix") + "/" + chipId; Serial.println(configSetupJson); + + serverIP = jsonReadStr(configSetupJson, "serverip"); } void all_init() { diff --git a/src/ItemsCmd.cpp b/src/ItemsCmd.cpp index 678aa11c..2a949050 100644 --- a/src/ItemsCmd.cpp +++ b/src/ItemsCmd.cpp @@ -47,6 +47,8 @@ void cmd_init() { sCmd.addCommand("uptime", sysUptime); + sCmd.addCommand("logging", logging); + handle_time_init(); } diff --git a/src/Logging.cpp b/src/Logging.cpp index 44b323a4..41f04790 100644 --- a/src/Logging.cpp +++ b/src/Logging.cpp @@ -7,7 +7,7 @@ void sendLogData(String file, String topic); #ifdef LOGGING_ENABLED //===============================================Логирование============================================================ //logging temp1 1 10 Температура Датчики 2 -void logging() { +/*void logging2() { String value_name = sCmd.next(); String period_min = sCmd.next(); String maxCount = sCmd.next(); @@ -67,12 +67,12 @@ void logging() { }, nullptr, false); } -} +}*/ /* * Удаление стрых данных и запись новых */ -void deleteOldDate(const String filename, size_t max_lines_cnt, String payload) { +/*void deleteOldDate(const String filename, size_t max_lines_cnt, String payload) { String log_date = readFile(filename, 5120); size_t lines_cnt = itemsCount(log_date, "\r\n"); @@ -94,7 +94,7 @@ void deleteOldDate(const String filename, size_t max_lines_cnt, String payload) addFileLn(filename, timeNow->getTimeUnix() + " " + payload); } } -} +}*/ //=========================================Выбор какие данные отправлять================================================================== void choose_log_date_and_send() { diff --git a/src/RemoteOrdersUdp.cpp b/src/RemoteOrdersUdp.cpp index e09693b0..6187d0bd 100644 --- a/src/RemoteOrdersUdp.cpp +++ b/src/RemoteOrdersUdp.cpp @@ -1,71 +1,70 @@ -//#include "RemoteOrdersUdp.h" -// -//#include -// -//#include "Global.h" -// -//AsyncUDP asyncUdp; -// -//void asyncUdpInit() { -// //if (asyncUdp.listen(1234)) { -// if (asyncUdp.listenMulticast(IPAddress(239, 255, 255, 255), 1234)) { -// asyncUdp.onPacket([](AsyncUDPPacket packet) { -// -// //Serial.print("UDP Packet Type: "); -// //Serial.print(packet.isBroadcast() ? "Broadcast" : packet.isMulticast() ? "Multicast" : "Unicast"); -// // -// //Serial.print(", From: "); -// //Serial.print(packet.remoteIP()); -// //Serial.print(":"); -// //Serial.print(packet.remotePort()); -// // -// //Serial.print(", To: "); -// //Serial.print(packet.localIP()); -// //Serial.print(":"); -// //Serial.print(packet.localPort()); -// // -// //Serial.print(", Length: "); -// //Serial.print(packet.length()); -// // -// //Serial.print(", Data: "); -// //Serial.write(packet.data(), packet.length()); -// -// String data = uint8tToString(packet.data(), packet.length()); -// Serial.print("[i] [udp] Packet received: '"); -// Serial.print(data); -// if (udpPacketValidation(data)) { -// udpPacketParse(data); -// //Serial.println("', Packet valid"); -// } else { -// //Serial.println("', Packet invalid"); -// } -// -// //reply to the client -// -// packet.printf("Got %u bytes of data", packet.length()); -// }); -// } -//} -// -//String uint8tToString(uint8_t* data, size_t len) { -// String ret; -// while (len--) { -// ret += (char)*data++; -// } -// return ret; -//} -// -//bool udpPacketValidation(String& data) { -// if (data.indexOf("iotm;") != -1 && data.indexOf(getChipId()) != -1) { -// return true; -// } else { -// return false; -// } -//} -// -////iotm;chipid;button-out-1_1 -//void udpPacketParse(String& data) { -// data = selectFromMarkerToMarker(data, ";", 2); -// data.replace("_", " "); -// orderBuf += data + ","; -//} \ No newline at end of file +#include "RemoteOrdersUdp.h" +#include +#include "Global.h" + +#ifdef UDP_ENABLED +AsyncUDP asyncUdp; + +void asyncUdpInit() { + //if (asyncUdp.listen(1234)) { + if (asyncUdp.listenMulticast(IPAddress(239, 255, 255, 255), 1234)) { + asyncUdp.onPacket([](AsyncUDPPacket packet) { + //Serial.print("UDP Packet Type: "); + //Serial.print(packet.isBroadcast() ? "Broadcast" : packet.isMulticast() ? "Multicast" : "Unicast"); + // + //Serial.print(", From: "); + //Serial.print(packet.remoteIP()); + //Serial.print(":"); + //Serial.print(packet.remotePort()); + // + //Serial.print(", To: "); + //Serial.print(packet.localIP()); + //Serial.print(":"); + //Serial.print(packet.localPort()); + // + //Serial.print(", Length: "); + //Serial.print(packet.length()); + // + //Serial.print(", Data: "); + //Serial.write(packet.data(), packet.length()); + + String data = uint8tToString(packet.data(), packet.length()); + Serial.print("[i] [udp] Packet received: '"); + Serial.print(data); + if (udpPacketValidation(data)) { + udpPacketParse(data); + //Serial.println("', Packet valid"); + } else { + //Serial.println("', Packet invalid"); + } + + //reply to the client + + packet.printf("Got %u bytes of data", packet.length()); + }); + } +} + +String uint8tToString(uint8_t* data, size_t len) { + String ret; + while (len--) { + ret += (char)*data++; + } + return ret; +} + +bool udpPacketValidation(String& data) { + if (data.indexOf("iotm;") != -1 && data.indexOf(getChipId()) != -1) { + return true; + } else { + return false; + } +} + +//iotm;chipid;button-out-1_1 +void udpPacketParse(String& data) { + data = selectFromMarkerToMarker(data, ";", 2); + data.replace("_", " "); + orderBuf += data + ","; +} +#endif \ No newline at end of file diff --git a/src/Web.cpp b/src/Web.cpp index 409f9836..fe1a1a02 100644 --- a/src/Web.cpp +++ b/src/Web.cpp @@ -200,6 +200,14 @@ void web_init() { myNotAsyncActions->make(do_BUSSCAN); request->redirect("/?set.utilities"); } + + //==============================developer settings============================================= + if (request->hasArg("serverip")) { + jsonWriteStr(configSetupJson, "serverip", request->getParam("serverip")->value()); + saveConfig(); + serverIP = jsonReadStr(configSetupJson, "serverip"); + request->send(200); + } }); //==============================list of items===================================================== diff --git a/src/items/LoggingClass.cpp b/src/items/LoggingClass.cpp index 8fffec28..0b809781 100644 --- a/src/items/LoggingClass.cpp +++ b/src/items/LoggingClass.cpp @@ -1,7 +1,13 @@ #include "items/LoggingClass.h" +#include + +#include "Class/LineParsing.h" +#include "Global.h" +#include "ItemsCmd.h" + LoggingClass::LoggingClass(unsigned long period, unsigned int maxPoints, String key) { - _period = period; + _period = period * 1000; _maxPoints = maxPoints; _key = key; } @@ -17,7 +23,6 @@ void LoggingClass::loop() { } } - void LoggingClass::addNewDelOldData(const String filename, size_t maxPoints, String payload) { String logData = readFile(filename, 5120); size_t lines_cnt = itemsCount(logData, "\r\n"); @@ -28,18 +33,33 @@ void LoggingClass::addNewDelOldData(const String filename, size_t maxPoints, Str removeFile(filename); lines_cnt = 0; } - - if (lines_cnt > maxPoints) { - logData = deleteBeforeDelimiter(logData, "\r\n"); - if (timeNow->hasTimeSynced()) { - logData += timeNow->getTimeUnix() + " " + payload + "\r\n"; - writeFile(filename, logData); - } - } else { - if (timeNow->hasTimeSynced()) { - addFileLn(filename, timeNow->getTimeUnix() + " " + payload); + + if (payload != "") { + if (lines_cnt > maxPoints) { + logData = deleteBeforeDelimiter(logData, "\r\n"); + if (timeNow->hasTimeSynced()) { + logData += timeNow->getTimeUnix() + " " + payload + "\r\n"; + writeFile(filename, logData); + } + } else { + if (timeNow->hasTimeSynced()) { + addFileLn(filename, timeNow->getTimeUnix() + " " + payload); + } } } } -MyLoggingVector* myLogging = nullptr; \ No newline at end of file +MyLoggingVector* myLogging = nullptr; + +void logging() { + myLineParsing.update(); + String value = myLineParsing.gvalue(); + String interv = myLineParsing.gint(); + String maxcnt = myLineParsing.gmaxcnt(); + myLineParsing.clear(); + + static bool firstTime = true; + if (firstTime) myLogging = new MyLoggingVector(); + firstTime = false; + myLogging->push_back(LoggingClass(interv.toInt(), maxcnt.toInt(), value)); +} diff --git a/src/main.cpp b/src/main.cpp index 8bd9b7ca..287e340f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,7 +14,7 @@ #include "Utils/WebUtils.h" #include "items/ButtonInClass.h" #include "items/LoggingClass.h" -//#include "RemoteOrdersUdp.h" +#include "RemoteOrdersUdp.h" #include "Bus.h" void not_async_actions(); @@ -74,9 +74,11 @@ void setup() { SerialPrint("I", "Stat", "Stat Init"); initSt(); - - //SerialPrint("I","UDP","Udp Init"); - //asyncUdpInit(); + + #ifdef UDP_ENABLED + SerialPrint("I","UDP","Udp Init"); + asyncUdpInit(); + #endif SerialPrint("I", "Bus", "Bus Init"); busInit(); @@ -97,8 +99,8 @@ void setup() { just_load = false; initialized = true; //this second POST makes the data to be processed (you don't need to connect as "keep-alive" for that to work) - myLogging = new MyLoggingVector(); - myLogging->push_back(LoggingClass(30000, 10, "analog-adc-1")); + //myLogging = new MyLoggingVector(); + //myLogging->push_back(LoggingClass(30000, 10, "analog-adc-1")); //myLogging->push_back(LoggingClass(10000, 1, "10 sec")); }