Мега в качестве агрегатора с разных серверов
- Войдите на сайт для отправки комментариев
Пт, 30/11/2018 - 01:28
Здравствуйте уважаемые коллеги.
ввиду невозможности редактирования стартового сообщения продолжу далее
Здравствуйте уважаемые коллеги.
ввиду невозможности редактирования стартового сообщения продолжу далее
У меня есть 1-2-3-много серверов , поднятых на esp8266, которые отдают состояние датчиков в csv строке каждый.
Неужели для каждого из них надо поднимать
charserver1[] ="192.168.35.1";charserver2[] ="192.168.35.2";charserver3[] ="192.168.35.3";if(client1.connect(server1, 80)).....if(client2.connect(server2, 80)).....if(client3.connect(server3, 80)).....if(client1.available()) .....if(client2.available()) .....if(client3.available()) .....#include <SPI.h> #include <Ethernet.h> #define W5100_RESET_PIN 3 // порт аппаратного сбоса сетевой платы #define W5100_CS 10 // порт управления сетевой платой #define SD_CS 4 // порт управления SD картой //***************************var for ethernet************************** byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address //****************************настройки для дома************************ byte ip[] = { 192, 168, 88, 233 }; // fixed IP addr in LAN byte gateway[] = { 192, 168, 88, 254 }; // internet access via router byte subnet[] = { 255, 255, 248, 0 }; //subnet mask byte dnServer[] = {77,37,255,30}; char server1[] = "192.168.88.244"; // name address for Google (using DNS) char server2[] = "192.168.88.245"; // name address for Google (using DNS) // Initialize the Ethernet client library // with the IP address and port of the server // that you want to connect to (port 80 is default for HTTP): EthernetClient client1; EthernetClient client2; void resetLAN(); //сброс и инициализация сетевой платы unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds const unsigned long postingInterval = 10L * 1000L; // delay between updates, in milliseconds // the "L" is needed to use long type numbers void setup() { // start serial port: Serial.begin(115200); // give the ethernet module time to boot up: delay(1000); Serial.println("MyAjax_chiller_4_2"); // ********************** инициализация портов сетевой платы и SD карты ************** pinMode(W5100_CS, OUTPUT); digitalWrite(W5100_CS,HIGH); pinMode(W5100_RESET_PIN, OUTPUT);digitalWrite(W5100_RESET_PIN,LOW); pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS,HIGH); //********************* запуск сетевых устройств и сервисов ************************** resetLAN(); } void loop() { if (client1.available()) { char c = client1.read(); Serial.write(c); } if (client2.available()) { char d = client2.read(); Serial.write(d); } if (millis() - lastConnectionTime > postingInterval) { httpRequest(); } } // this method makes a HTTP connection to the server: void httpRequest() { // close any connection before send a new request. // This will free the socket on the WiFi shield client1.stop(); client2.stop(); // if there's a successful connection: if (client1.connect(server1, 80)) { Serial.println(); Serial.println("connecting..."); // send the HTTP PUT request: client1.println("GET /csv HTTP/1.1"); client1.println("Connection: close"); client1.println(); // note the time that the connection was made: lastConnectionTime = millis(); } else { // if you couldn't make a connection: Serial.println(); Serial.println("connection client 1 failed"); } if (client2.connect(server2, 80)) { Serial.println(); Serial.println("connecting..."); // send the HTTP PUT request: client2.println("GET /csv HTTP/1.1"); client2.println("Connection: close"); client2.println(); // note the time that the connection was made: lastConnectionTime = millis(); } else { // if you couldn't make a connection: Serial.println(); Serial.println("connection client 2 failed"); } } ///////////////////////сброс и инициализация сетевой платы//////////////////////////////////// void resetLAN() { digitalWrite(W5100_RESET_PIN, LOW); Serial.println("reset lock"); delay(100); digitalWrite(W5100_RESET_PIN, HIGH);Serial.println("reset release"); delay(1000); Ethernet.begin(mac,ip,dnServer,gateway,subnet); delay(500); Serial.print("My IP adress: "); Serial.println(Ethernet.localIP()); Serial.print("My gateway: "); Serial.println(Ethernet.gatewayIP()); Serial.print("My subnet mask: "); Serial.println(Ethernet.subnetMask()); Serial.print("My dns Server: "); Serial.println(Ethernet.dnsServerIP()); }Плодить объекты client не надо. Достаточно одному подсовывать в connect() разные адреса.
два ключевых слова - массивы и циклв
А почему не наоборот? ESP собрала данные и скидывает на один единственный сервер, как в народном мониторинге например
А у Вас нет ли примера , как подсовывать?
я конечно же попробовал по-очереди кидать запрос в один объект. Отрабатывает только первый, что закономерно, так как закинутый запрос потом некоторое время ждет отклика.
Поразмышлял не у копьютера, получилась такая вот логика...
Видимо надо кидать запрос к певому серверу , выставлять флаг и ждать ответа от него, крутясь в луупе, по приходу обрабатывать и сбрасывать флаг. Так как у меня все запускается псевдопроцессами изитаймера, то раз в секунду например в псевдопроцессе анализировать, был ли обработан отклик и соответственно запрашивать следующий или перезапрашивать текущий.
ua6em- мне нужна возможность посмотреть каждую ESP по-отдельности.
ua6em- мне нужна возможность посмотреть каждую ESP по-отдельности.
всё равно не понял, каждая ESP имеет свой ID в базе, по нему и смотреть можно
Возможность зайти на нее браузером напрямую, без агрегатора необходима.
Возможность зайти на нее браузером напрямую, без агрегатора необходима.
и в чем противоречие?
Если вам нужны одновременные коннекты, то, конечно, без массива объектов client не обойтись - это так. Только можно поизящней их загнать в массив и при открытии нового соединения смотреть, какой из них свободен. Но тут уже не 10 строчек - более замороченная логика выходить.
нуууу... пока как то так, пока без обработки таймаутов, но уже с перебором серверов
наверно надо городить очередь статусов с учетом таймаутов в массиве структур.
#include <SPI.h> #include <Ethernet.h> #define W5100_RESET_PIN 3 // порт аппаратного сбоса сетевой платы #define W5100_CS 10 // порт управления сетевой платой #define SD_CS 4 // порт управления SD картой //***************************var for ethernet************************** byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address //****************************настройки для дома************************ byte ip[] = { 192, 168, 88, 233 }; // fixed IP addr in LAN byte gateway[] = { 192, 168, 88, 254 }; // internet access via router byte subnet[] = { 255, 255, 248, 0 }; //subnet mask byte dnServer[] = {77,37,255,30}; char* server[2] = {"192.168.88.244","192.168.88.245"}; EthernetClient client; struct condition { uint32_t counter; float duration; float average; }; condition tpa_status[54]; boolean flag_serv = LOW; byte line_counter = 0; unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds const unsigned long postingInterval = 4000; // delay between updates, in milliseconds //********************предОбъявление функций******************* void resetLAN(); //сброс и инициализация сетевой платы void httpRequest(); // создание коннекта к серверу //--------------------------------------------------------------------------------------------------------------------------------------------------------------------- void setup() { Serial.begin(115200); delay(1000); Serial.println("AGregator multi client"); // ********************** инициализация портов сетевой платы и SD карты ************** pinMode(W5100_CS, OUTPUT); digitalWrite(W5100_CS,HIGH); pinMode(W5100_RESET_PIN, OUTPUT);digitalWrite(W5100_RESET_PIN,LOW); pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS,HIGH); //********************* запуск сетевых устройств и сервисов ************************** resetLAN(); //********************очистка таблицы статусов *********************************************** for (int i =0; i<54; i++){ tpa_status[i].counter = 0; tpa_status[i].duration = 0; tpa_status[i].average = 0; } httpRequest(); } //--------------------------------------------------------------------------------------------------------------------------------------------------------------------- void loop() { if (client.available()) { Serial.print("available ");Serial.println(server[line_counter]); flag_serv = LOW; while (client.available()){ char c = client.read(); Serial.write(c); } } if (!flag_serv) { if (millis() - lastConnectionTime > postingInterval) { client.stop(); ++line_counter; if (line_counter==2) line_counter=0; httpRequest(); } } } ///////////////////////посылка запроса к очередному серверу//////////////////////////////////// void httpRequest() { if (client.connect(server[line_counter], 80)) { Serial.println(); Serial.println("connecting..."); // send the HTTP PUT request: client.println("GET /csv HTTP/1.1"); client.println("Connection: close"); client.println(); flag_serv = HIGH; // note the time that the connection was made: lastConnectionTime = millis(); } else { // if you couldn't make a connection: Serial.println(); Serial.print("Connection ");Serial.print(server[line_counter]);Serial.println(" not available :("); } } ///////////////////////сброс и инициализация сетевой платы//////////////////////////////////// void resetLAN() { digitalWrite(W5100_RESET_PIN, LOW); Serial.println("reset lock"); delay(100); digitalWrite(W5100_RESET_PIN, HIGH);Serial.println("reset release"); delay(1000); Ethernet.begin(mac,ip,dnServer,gateway,subnet); delay(500); Serial.print("My IP adress: "); Serial.println(Ethernet.localIP()); Serial.print("My gateway: "); Serial.println(Ethernet.gatewayIP()); Serial.print("My subnet mask: "); Serial.println(Ethernet.subnetMask()); Serial.print("My dns Server: "); Serial.println(Ethernet.dnsServerIP()); }Можно так. Или сразу массив IPAddress завести. println() его умеет печатать. Али в массиве структур держать с дополнительными параметрами соединения - портом, логином, паролем...
const uint8_t servers[][4] = { {192, 168, 88, 244}, {192, 168, 88, 245} }; void loop() { IPAddress server; .... for (uint8_t = 0; i< 2; i++) { server = IPAddress(server[i]); if (client.connect(server, 80)) { .... } } ... }Да, можно. Спасибо. Еоот массив ip пока для пробы. Но там вся подсетка моя и последняя триада совпадает с номером машины и счетчиком вызова. Потому массива дя ip не будет. Он станет вычисляться в порядке очередности вызовов. Пока придумываю кольцевой массив статусов и способы его перебора, обновления и использования. И для полноценного тестирования (раскопал еще две esp8266-12) спаяю еще два модуля. Четыре это уже можно отлаживать.
Кстати вопрос немного не по теме, но рядом. Глюк кодировки передаваемой иде при компилляции.
Слетает кодировка вывода в браузер. В преамбуле html стоит utf-8. Однако после открытия программы и компилляции прут крякозябры. Но, если всю программу закинуть в notepad++ и прогнать в другую кодировки и обратнов utf, копипастнуть обратно в иде, то до следующего открытия в иде любой программы все отображается правильно.
может быть это где то в настройках лечится?
Уважаемые коллеги! Извитеее что к Вам абращаюсь. Отзовитесь плз по кодировкам. Оно конечно криво-обходится, но может быть это только я такой "криворуко-косоглазый" ?
Лабел 1: Еще раз... загружаю исходник
компиллирую
сервер отдает в веб крякозябры. преамбула такая между start и end впихивую что то непринципиальное
const String header_start = "<!DOCTYPE html>" "<html lang=\"ru\">" "<head><title>HEGEL AGregator 1.0.2</title>" "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"; const String header_end = "</head><body>"; const String footer = "</body></html>\n";копипастю весь код в нотепад ++ там перекодирую в анси и снова в ютф
копипастю в иде
работаю нормально с правильным отображением в (как мимнимум) в хроме, компиллирую много раз ...
новая загрузка любого кода из файла в новое окно и снова на Лабел 1 :(
Я бы ответил, но русские символы не сую в прошивки, так что не в курсе.
Лабел 1: Еще раз... загружаю исходник
компиллирую
сервер отдает в веб крякозябры. преамбула такая между start и end впихивую что то непринципиальное
копипастю весь код в нотепад ++ там перекодирую в анси и снова в ютф
копипастю в иде
работаю нормально с правильным отображением в (как мимнимум) в хроме, компиллирую много раз ...
в общем опрос как минимум 4-х модулей происходит стабильно.
данные с модулей отдаются в csv из трех показателей, на агрегаторе пасятся и распихиваются в массив структур.
#include <SPI.h> #include <Ethernet.h> #define W5100_RESET_PIN 3 // порт аппаратного сбоса сетевой платы #define W5100_CS 10 // порт управления сетевой платой #define SD_CS 4 // порт управления SD картой #define REQ_BUF_SZ 80 //***************************var for ethernet************************** byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address //****************************настройки для дома************************ byte ip[] = { 192, 168, 88, 233 }; // fixed IP addr in LAN byte gateway[] = { 192, 168, 88, 254 }; // internet access via router byte subnet[] = { 255, 255, 248, 0 }; //subnet mask byte dnServer[] = {78,55,256,38}; //***************************настройки для клиента********************** char* server[4] = {"192.168.88.244","192.168.88.245","192.168.88.246","192.168.88.247"}; char req_index = 0; char HTTP_req[REQ_BUF_SZ] = {0}; String req; EthernetClient client; struct condition { uint32_t counter; float duration; float average; uint16_t avail; }; condition tpa_status[54]; boolean flag_serv = LOW; byte line_counter = 0; byte commaIndex =0; byte secondCommaIndex = 0; String firstValue; String secondValue; String thirdValue; unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds const unsigned long postingInterval = 3500; // delay between updates, in milliseconds //********************предОбъявление функций******************* void resetLAN(); //сброс и инициализация сетевой платы void httpRequest(); // создание коннекта к серверу void StrClear(char *str, char length); char StrContains(char *str, char *sfind); //--------------------------------------------------------------------------------------------------------------------------------------------------------------------- void setup() { Serial.begin(115200); delay(1000); Serial.println("AGregator multi client"); // ********************** инициализация портов сетевой платы и SD карты ************** pinMode(W5100_CS, OUTPUT); digitalWrite(W5100_CS,HIGH); pinMode(W5100_RESET_PIN, OUTPUT);digitalWrite(W5100_RESET_PIN,LOW); pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS,HIGH); //********************* запуск сетевых устройств и сервисов ************************** resetLAN(); //********************очистка таблицы статусов *********************************************** for (int i =0; i<54; i++){ tpa_status[i].counter = 0; tpa_status[i].duration = 0; tpa_status[i].average = 0; tpa_status[i].avail = 0; } httpRequest(); } //--------------------------------------------------------------------------------------------------------------------------------------------------------------------- void loop() { if (client.available()) { flag_serv = LOW; while (client.available()){ char c = client.read(); if (req_index < (REQ_BUF_SZ - 1)) { HTTP_req[req_index] = c; req_index++; } } if (StrContains(HTTP_req, "Content-Type")) { req_index = 0; StrClear(HTTP_req, REQ_BUF_SZ); } else { req = String(HTTP_req); commaIndex = req.indexOf(','); secondCommaIndex = req.indexOf(',', commaIndex+1); firstValue = req.substring(0,commaIndex); secondValue = req.substring(commaIndex+1 ,secondCommaIndex ); thirdValue = req.substring(secondCommaIndex+1 ); tpa_status[line_counter].counter = firstValue.toInt(); tpa_status[line_counter].duration = secondValue.toFloat(); tpa_status[line_counter].average = thirdValue.toFloat(); Serial.print(server[line_counter]);Serial.print(" "); Serial.print(tpa_status[line_counter].counter);Serial.print(" "); Serial.print(tpa_status[line_counter].duration);Serial.print(" "); Serial.print(tpa_status[line_counter].average);Serial.print(" "); Serial.print(tpa_status[line_counter].avail);Serial.println(); req_index = 0; StrClear(HTTP_req, REQ_BUF_SZ); } } if (!flag_serv) { if (millis() - lastConnectionTime > postingInterval) { ++line_counter; if (line_counter==4) line_counter=0; client.stop(); httpRequest(); } } } ///////////////////////посылка запроса к очередному серверу//////////////////////////////////// void httpRequest() { if (client.connect(server[line_counter], 80)) { Serial.println(); // Serial.println("connecting..."); // send the HTTP PUT request: client.println("GET /csv HTTP/1.1"); client.println("Connection: close"); client.println(); flag_serv = HIGH; // note the time that the connection was made: lastConnectionTime = millis(); } else { // if you couldn't make a connection: Serial.println(); Serial.print("Connection ");Serial.print(server[line_counter]);Serial.println(" not available :("); tpa_status[line_counter].avail++; } } ///////////////////////сброс и инициализация сетевой платы//////////////////////////////////// void resetLAN() { digitalWrite(W5100_RESET_PIN, LOW); Serial.println("reset lock"); delay(100); digitalWrite(W5100_RESET_PIN, HIGH);Serial.println("reset release"); delay(1000); Ethernet.begin(mac,ip,dnServer,gateway,subnet); delay(500); Serial.print("My IP adress: "); Serial.println(Ethernet.localIP()); Serial.print("My gateway: "); Serial.println(Ethernet.gatewayIP()); Serial.print("My subnet mask: "); Serial.println(Ethernet.subnetMask()); Serial.print("My dns Server: "); Serial.println(Ethernet.dnsServerIP()); } /////////////////////очистка строки///////////////////////////////////////////////////////// void StrClear(char *str, char length) { for (int i = 0; i < length; i++) { str[i] = 0; } } ////////////////поиск в строке подстроки/////////////////////////////////////////////////// // returns 1 if string found // returns 0 if string not found char StrContains(char *str, char *sfind) { char found = 0; char index = 0; char len; len = strlen(str); if (strlen(sfind) > len) { return 0; } while (index < len) { if (str[index] == sfind[found]) { found++; if (strlen(sfind) == found) { return 1; } } else { found = 0; } index++; } return 0; }Также получилось на одной меге поднять сервер, отдающий страницу агрегированных данных с модулей из этого массива, клиента NTP, запись в лог на SF, выгрузку лога и его обнуление, но это уже другая история.
По кодировке выяснилось, что IDE периодически меняет кодировку на UTF-9 (BOM), перекодирование в ноте++ этот глюк исправляет.
и еще одна особенность. если в программе используется обращение по UDP к ntp серверам, то перед запросом необходимо гасить клиент принудительно client.stop();