• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Вопрос Не стабильно работает Web сервер

Bmax77

New member
Здравствуйте.
Столкнулся с такой проблемой, Web сервер работает очень не стабильно, странички как таковой нет, просто отвечает "ОК" и переключает реле.
Ситуацию улучшает маленькая задержка в цикле loop.

Код:
void loop() {
  // put your main code here, to run repeatedly:
server.handleClient();
ArduinoOTA.handle();
delay(10);
}
 

Юрий Ботов

Moderator
Команда форума
странички как таковой нет, просто отвечает "ОК"
это так и должно быть? Или ожидали другого а есть это?
Web сервер работает очень не стабильно
В чем заключается нестабильность?
Ситуацию улучшает
Что улучшается?
 

Bmax77

New member
Простите за сумбур.
Сервер отвечает как и положеео ему ответить, с заголовком и тп но сам ответ срдержит в себе ОК и все.
Если задержку убрать то сервер вообще не отвечает.
Если вставить задержку то работает но иногда перестает отвечать на некоторое время и потом опять нормально отвечает.


это так и должно быть? Или ожидали другого а есть это?

В чем заключается нестабильность?

Что улучшается?
 

Bmax77

New member
@Bmax77 может дело в сети. Вы весь код то приведите, а то гадать мы не обучены. Как подсоединяетесь, чем?
а что надо?
Дело в том что у меня есть работающий проект, метеостанция и там все замечательно.
Код в плане инициализации и подключения к wifi идентичный.
А код разбит на модули, даже не знаю как его сюда лучше запостить.
Я просто подумал может кто то сталкивался с такой проблемой, видел тут тему там тоже сервер чудил, и помогало вставииь в цикл вывод в консоль.
 

Bmax77

New member
Простите за сумбур.
Сервер отвечает как и положеео ему ответить, с заголовком и тп но сам ответ срдержит в себе ОК и все.
Если задержку убрать то сервер вообще не отвечает.
Если вставить задержку то работает но иногда перестает отвечать на некоторое время и потом опять нормально отвечает.


это так и должно быть? Или ожидали другого а есть это?

В чем заключается нестабильность?

Что улучшается?
 

Сергей_Ф

Moderator
Команда форума
Дело в том что у меня есть работающий проект, метеостанция и там все замечательно.
Код в плане инициализации и подключения к wifi идентичный.
может вы там фиксированные ip прописали и они конфликтуют. Хоть что то приведите: лог роутера, лог подключения, и т.д.
А то получается:
- " Доктор у меня что-то болит."
- "Ну так, попейте какие-нибудь таблетки."
 

Bmax77

New member
Основной код
Код:
//#define FAN
#define ONECHANNELS
//#define TWOCHANNELS
//#define FOURCHANNELS

#if defined(ONECHANNELS) || defined(TWOCHANNELS) || defined(FAN)
#define CH1_PIN 0
#define CH2_PIN 2
#endif
#if defined(FOURCHANNELS)
#define CH1_PIN 12
#define CH2_PIN 13
#define CH3_PIN 14
#define CH4_PIN 15
#endif

#include <ESP8266WiFi.h>
//#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <Ticker.h>  //Ticker Library

#define _ssids 3

Ticker setTim1;
//Ticker setTim2;
//uint16_t N = 0;
//uint16_t M = 100;
//uint16_t X = 200;
//uint32_t cnt = 0;
IPAddress broadcastIp(192,168,1,255);
unsigned int localPort = 8002;

//Hex command to send to serial for close relay
const byte rel1ON[]  = {0xA0, 0x01, 0x01, 0xA2};

//Hex command to send to serial for open relay
const byte rel1OFF[] = {0xA0, 0x01, 0x00, 0xA1};

//Hex command to send to serial for close relay
const byte rel2ON[]  = {0xA0, 0x02, 0x01, 0xA3};

//Hex command to send to serial for open relay
const byte rel2OFF[] = {0xA0, 0x02, 0x00, 0xA2};

String _ssid[] = {"******", "******", "******"};
String _password[] = {"******", "******", "******"};
//char Buff[255]="";
byte packetBuffer[512]; //buffer to hold incoming and outgoing packets
char replyPacket[] = "Command OK";
uint32_t udp_tim = 0;

ESP8266WebServer server(80);
WiFiUDP UdpClt;
//WiFiUDP UdpSrv;

void setup() {
  // put your setup code here, to run once:
   Serial.begin(74880);
   delay(100);
   Serial.println("");
   Serial.println("Hello!");
   Serial.println(ESP.getFlashChipSize());
   Serial.println(ESP.getFlashChipRealSize());

  pinMode(CH1_PIN, OUTPUT);
  digitalWrite(CH1_PIN, LOW);
  pinMode(CH2_PIN, OUTPUT);
  digitalWrite(CH2_PIN, LOW);
  WIFIinit();
  delay(1000);
  myOTASetup();
  delay(1000);
  WEBroutine();
  delay(1000);
//  UdpSrv.begin(localPort);
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localPort);
//  setTim1.attach(5, udpSendState);
  delay(5000);
  Serial.begin(115200);
  delay(1000);
  Serial.write (rel1OFF, sizeof(rel1OFF));
  delay(250);
  Serial.write (rel2OFF, sizeof(rel2OFF));
  for(int i = 0; i < 5; i++){
  udpSendState();
  delay(500);
  }
  setTim1.attach(5, udpSendState);
}

void loop() {
  // put your main code here, to run repeatedly:
server.handleClient();
ArduinoOTA.handle();
//handleUDPServer();
delay(10);
}
Код подключения к WIFI
Код:
boolean WIFIinit(void) {
  Serial.println("");
  Serial.println("");
  Serial.println("");
  boolean state = false;
  WiFi.mode(WIFI_STA);

  for (int n = 0; n < _ssids; n++) {
    byte tries = 30;
    Serial.println("Connecting to SSID: " + _ssid[n]);
    WiFi.begin(_ssid[n].c_str(), _password[n].c_str());
    while (--tries && WiFi.status() != WL_CONNECTED) {
      Serial.print(".");
      delay(1000);
    }
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("");
      Serial.println("WIFI connected");
      Serial.print("MAC address: ");
      Serial.println(WiFi.macAddress());
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
      Serial.print("WIFI ");
      Serial.print(WiFi.RSSI());
      Serial.println(" dBi");
      state = true;
      return state;
    }
    Serial.println("");
  }
  return state;
}
Код веб страницы
Код:
#ifdef FAN
void WEBroutine(void) {
  server.on("/api", []() {
    Serial.println(server.argName(0));
    //      Serial.println(server.arg(0));
    if (server.argName(0) == "CH1")
    {
      digitalWrite(CH1_PIN, HIGH);
      Serial.write(rel1ON, sizeof(rel1ON));
      delay(250);
      digitalWrite(CH2_PIN, LOW);
      Serial.write(rel2OFF, sizeof(rel2OFF));
    }
    else if (server.argName(0) == "CH2")
    {
      digitalWrite(CH1_PIN, HIGH);
      Serial.write(rel1ON, sizeof(rel1ON));

      delay(250);
      digitalWrite(CH2_PIN, HIGH);
      Serial.write(rel2ON, sizeof(rel2ON));

    }
    else if (server.argName(0) == "OFF")
    {
      digitalWrite(CH1_PIN, LOW);
      digitalWrite(CH2_PIN, LOW);
      Serial.write(rel1OFF, sizeof(rel1OFF));
      delay(250);
      Serial.write(rel2OFF, sizeof(rel2OFF));
    }
    udpSendState();
    server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
    server.sendHeader("Access-Control-Allow-Origin", "*");
    server.send(200, "text/html", "OK");
    //      server.setContentLength(CONTENT_LENGTH_UNKNOWN);
    //      server.send(200, "text/plain", "");
    //      server.sendContent("OK");
    //      server.sendContent("");
    //      server.client().stop();
  });
  server.on("/restart", []() {
    server.send(200, "text/plain", "RESTART");
    delay(2000);
    ESP.restart();
  });
  server.begin();
  Serial.println("Server started");
}
#endif
Код OTA
Код:
void myOTASetup(void) {
  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH) {
      type = "sketch";
    }
    else { // U_SPIFFS
      type = "filesystem";
      // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    }
    Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("OTA IP address: ");
  Serial.println(WiFi.localIP());
}
 

Bmax77

New member
Это что за зверь? Что делает udpSendState()?
Упс забыл скопировать.
там json шлет
Код:
#ifdef FAN
void udpSendState() {
  char Buff[255] = "";
  String web;
  web += "{"
         "\"id\": \"";
  web += "FUN0201";
  //    web += WiFi.macAddress();
  web += "\", "
         "\"type\" : \"relay\", "
         "\"ip\" : \"";
  web += WiFi.localIP().toString();
  web += "\", \"CH1\" : ";
  web += digitalRead(CH1_PIN);
  web += ", \"CH2\" : ";
  web += digitalRead(CH2_PIN);
  web += ", \"status\" : ";
  web += 2;
  web += "}";
  web.toCharArray(Buff, 255);
  UdpClt.beginPacket(broadcastIp, localPort);
  UdpClt.write(Buff);
  UdpClt.endPacket();
}
#endif

#if defined(ONECHANNELS) || defined(TWOCHANNELS)
void udpSendState() {
  char Buff[255] = "";
  String web;
  web += "{"
         "\"id\": \"";
#if  defined(ONECHANNELS)
  web += "SOCKET0103";
#endif
#if  defined(TWOCHANNELS)
  web += "SOCKET0201";
#endif
  //    web += WiFi.macAddress();
  web += "\", "
         "\"type\" : \"relay\", "
         "\"ip\" : \"";
  web += WiFi.localIP().toString();
  web += "\", \"CH1\" : ";
  web += digitalRead(CH1_PIN);
  web += ", \"CH2\" : ";
  web += digitalRead(CH2_PIN);
  web += ", \"status\" : ";
  web += 2;
  web += "}";
  web.toCharArray(Buff, 255);
  UdpClt.beginPacket(broadcastIp, localPort);
  UdpClt.write(Buff);
  UdpClt.endPacket();
//  Serial.println("UDP");
}
#endif
 

nikolz

Well-known member
Упс забыл скопировать.
там json шлет
Код:
#ifdef FAN
void udpSendState() {
  char Buff[255] = "";
  String web;
  web += "{"
         "\"id\": \"";
  web += "FUN0201";
  //    web += WiFi.macAddress();
  web += "\", "
         "\"type\" : \"relay\", "
         "\"ip\" : \"";
  web += WiFi.localIP().toString();
  web += "\", \"CH1\" : ";
  web += digitalRead(CH1_PIN);
  web += ", \"CH2\" : ";
  web += digitalRead(CH2_PIN);
  web += ", \"status\" : ";
  web += 2;
  web += "}";
  web.toCharArray(Buff, 255);
  UdpClt.beginPacket(broadcastIp, localPort);
  UdpClt.write(Buff);
  UdpClt.endPacket();
}
#endif

#if defined(ONECHANNELS) || defined(TWOCHANNELS)
void udpSendState() {
  char Buff[255] = "";
  String web;
  web += "{"
         "\"id\": \"";
#if  defined(ONECHANNELS)
  web += "SOCKET0103";
#endif
#if  defined(TWOCHANNELS)
  web += "SOCKET0201";
#endif
  //    web += WiFi.macAddress();
  web += "\", "
         "\"type\" : \"relay\", "
         "\"ip\" : \"";
  web += WiFi.localIP().toString();
  web += "\", \"CH1\" : ";
  web += digitalRead(CH1_PIN);
  web += ", \"CH2\" : ";
  web += digitalRead(CH2_PIN);
  web += ", \"status\" : ";
  web += 2;
  web += "}";
  web.toCharArray(Buff, 255);
  UdpClt.beginPacket(broadcastIp, localPort);
  UdpClt.write(Buff);
  UdpClt.endPacket();
//  Serial.println("UDP");
}
#endif
прикольно.
1) зачем каждый раз при обращении к udpSendState создавать массив Buff?
2) зачем массив преобразовывать в массив? это : web.toCharArray(Buff, 255); У вас Buff и так объявлен массивом.
3) программирование изучать не пробовали?
 

Bmax77

New member
прикольно.
1) зачем каждый раз при обращении к udpSendState создавать массив Buff?
2) зачем массив преобразовывать в массив? это : web.toCharArray(Buff, 255); У вас Buff и так объявлен массивом.
3) программирование изучать не пробовали?
1. А что динамически массив создавать в функции в языке С моветон?
2. web это строка, я знаю что в C строк нет, но в arduino IDE строки есть, уж как они там у нее внутри выглядят я не знаю, но библиотека udp, требует для отправки именно массив, так что приходится преобразовывать, если знаете как скормить udp строку поделитесь.
3. Да самоучка я, денег этим не зарабатываю, так что пишу как умею.
 

Сергей_Ф

Moderator
Команда форума
@Bmax77 вы бы лог привели программы, когда у вас сервер не работает. У вас везде вставлен отладочный вывод - значит вы видите где тормозит. Ну если с сетью все Ок, конечно.
И акцент тут не при чем. Зачем инициировать Serial два раза на разной скорости? Терминал на лету переключаете? Или как?
Зачем delay в командах CH1 и CH2 я ещё могу предположить, но зачем он в команде OFF - понять не могу.
 

Сергей_Ф

Moderator
Команда форума
Есть предположение, что ваш Ticker с переодическими посылками udp вполне может нарушить работу сервера. Попробуйте его убрать для начала. Если поможет, то делайте вызов udpSendState в основной программе отсчитывая промежуток вручную через millis.
 

Bmax77

New member
Да, у меня сильный акцент))))))
@Bmax77 вы бы лог привели программы, когда у вас сервер не работает. У вас везде вставлен отладочный вывод - значит вы видите где тормозит. Ну если с сетью все Ок, конечно.

И акцент тут не при чем. Зачем инициировать Serial два раза на разной скорости? Терминал на лету переключаете? Или как?
Зачем delay в командах CH1 и CH2 я ещё могу предположить, но зачем он в команде OFF - понять не могу.
Ну программа в процессе отладки, меняю сильно код не все сразу замечаю и подчищаю.
Задержки там для управления реле, если сразу две команды посылать то срабатывает только первое реле на плате.
Вообще конечно вставлять такой громоздкий код в ответ сервера как то не правильно, но мы уходим от сути вопроса, даже если вычистить все и оставить только веб сервер и в loop убрать задержку, сервер перестанет отвечать.
 

Bmax77

New member
Есть предположение, что ваш Ticker с переодическими посылками udp вполне может нарушить работу сервера. Попробуйте его убрать для начала. Если поможет, то делайте вызов udpSendState в основной программе отсчитывая промежуток вручную через millis.
Тикер убирал, не помогает.
Вроде бы millis в loop блокирует wifi.
 

nikolz

Well-known member
1. А что динамически массив создавать в функции в языке С моветон?
2. web это строка, я знаю что в C строк нет, но в arduino IDE строки есть, уж как они там у нее внутри выглядят я не знаю, но библиотека udp, требует для отправки именно массив, так что приходится преобразовывать, если знаете как скормить udp строку поделитесь.
3. Да самоучка я, денег этим не зарабатываю, так что пишу как умею.
В Си строки есть.
Создавать динамически один и тот же массив а потом его уничтожать и снова создавать - это трата времени и памяти
Вы динамический массив заполняете строками
Строки эти хранятся статически и каждый раз переписываются в массив
Прикольно потому что много ненужной траты памяти и времени процессора.
Т е написано очень плохо, поэтому спросил об уровне изучения Вами программирования.
-------------
Если следовать Вашей логике, то если авто хотите водить не для денег, то учиться вождению авто можно кое как , или вообще никак.
Прикольно.
 
Сверху Снизу