ESP8266 Arduino IDE Частое переподключение Wifi

Если вы только начинаете осваивать систему MajorDoMo и чего-то не знаете или не можете понять, то задавайте свои вопросы в этой ветке.

Модератор: immortal

Ответить
alexmjdm
Сообщения: 30
Зарегистрирован: Пт сен 04, 2020 10:30 am
Благодарил (а): 35 раз
Поблагодарили: 0

ESP8266 Arduino IDE Частое переподключение Wifi

Сообщение alexmjdm » Вт май 17, 2022 8:58 pm

Добрый день, коллеги.

Программирую ESP8266 в среде Arduino IDE
Получаю частые подключения (читай частый дисконнект) к WiFi. Последний замер показал 360 переподключений за сутки. 149 секунд отсутствия в сети. Чем мне не нравится: если придет команда во время отсутствия в сети, устройство может не узнать о задаче.
Ну и вторая проблема: если кнопка или датчик движения на одной ESP а реле на другой, то не получается оперативно включить свет.

Тестировал питание от компьютера через USB Питание КМК должно быть стабилизировано.
Питал от блока питания. Конденсаторы на вход ESP поставил. электролит 470 мкФ и керамику 0.1 мкФ

Код привел ниже. Может кто подскажет решение моей задачи.
PS Поиском пользоваться умею. Не могу сформулировать проблему.

Код: Выделить всё

const char* EspNaveVer = "Test WiFi";

//2022-05-17
// Test WiFi

#include <PubSubClient.h>
#include <ESP8266WiFi.h>
 
// Change the credentials below, so your ESP8266 connects to your router
 const char* ssid = "ubuntu24";
 const char* password = "l";
 
// Change the variable to your Raspberry Pi IP address, so it connects to your MQTT broker
 const char* AIO_SERVER = "192.168.0.112";
 #define AIO_SERVERPORT  1883

// Initializes the espClient. You should change the espClient name if you have multiple ESPs running in your home automation system
WiFiClient espClient0003;
PubSubClient client(espClient0003);

int publikuem = 0;
int count = 0;
char countchar[6];
int countWiFiConnect = 0;
int timeWiFiConnect = 0;
long lastMsg = 0;

long now = millis();
long lastMeasure = millis() - 100000;

int FirstZapusk = 1;

//int D0status = 0;

String lastCmd = "EspRestart";
 
// Don't change the function below. This functions connects your ESP8266 to your router
void setup_wifi() {
  long now = millis();
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    }
  Serial.println("");
  Serial.print("WiFi connected - ESP IP address: ");
  Serial.println(WiFi.localIP());
  //countWiFiConnect = countWiFiConnect + 1;
  timeWiFiConnect = timeWiFiConnect + millis() - now;
  dtostrf(countWiFiConnect, 6, 0, countchar);
  client.publish("ESP0003/countWiFiConnect", countchar);

  dtostrf(timeWiFiConnect, 6, 0, countchar);
  client.publish("ESP0003/timeWiFiConnect", countchar);
}
 

void callback(String topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;
   
  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
    }
  Serial.println();

  }


// This functions reconnects your ESP8266 to your MQTT broker
// Change the function below if you want to subscribe to more topics with your ESP8266 
void reconnect() {
  // Loop until we're reconnected
  long now = millis();
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP0003_Client")) {
      Serial.println("connected");
      countWiFiConnect = countWiFiConnect + 1;
      // Subscribe or resubscribe to a topic
      // You can subscribe to more topics (to control more LEDs in this example)
      client.subscribe("ESP0003/LED/D0set");
      timeWiFiConnect = timeWiFiConnect + millis() - now;
      } 
  else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 1 seconds");
      // Wait 1 seconds before retrying
      delay(1000);
      }
    }
  }
 

void setup() {
  Serial.begin(9600, SERIAL_8N1, SERIAL_TX_ONLY);
  setup_wifi();
  client.setServer(AIO_SERVER, AIO_SERVERPORT);
  client.setCallback(callback);  
  }




// For this project, you don't need to change anything in the loop function. Basically it ensures that you ESP is connected to your broker
void loop() {
  byte i;

  now = millis();

  if (now - lastMeasure > 10000) {
    if (!client.connected()) {
      reconnect();
      }
  if(!client.loop())
      client.connect("ESP8266Client");
      lastMeasure = millis();

  if (FirstZapusk == 1) {
      publikuem = 1;
      FirstZapusk = 0; 
      lastCmd = "EspRestart";
      }
  if (UINT32_MAX - millis() < 20000 ) { // за 20 секунд до переполнения millis  Переполнение происходит раз в 49 дней
      lastCmd = "perepolnenie millis";
      publikuem = 1;
    }

  // раз в указанный период устанавливаем флаг publikuem в 1   
  if (now - lastMsg > 10000) {
    publikuem = 1;
    }

  // Публикуем необходимые данные
  if (publikuem == 1) {
    publikuem = 0;
    lastMsg = now;
    Serial.println("Публикуем наши данные");
    if ((String)lastCmd != (String)"") {
      char charBufVar[80];
      lastCmd.toCharArray(charBufVar, 80);
      client.publish("ESP0003/LastCmd", charBufVar);
      lastCmd = "";
      }
    }
    count = count + 1;
    dtostrf(count, 6, 0, countchar);
    client.publish("ESP0003_count", countchar);
    client.publish("ESP0003/name", EspNaveVer);    
    Serial.print("Count: ");
    Serial.println(count);
    Serial.print("countWiFiConnect: ");
    Serial.println(countWiFiConnect);

    Serial.print("timeWiFiConnect: ");
    Serial.println(timeWiFiConnect);
    
    dtostrf(countWiFiConnect, 6, 0, countchar);
    client.publish("ESP0003/countWiFiConnect", countchar);

    dtostrf(timeWiFiConnect, 6, 0, countchar);
    client.publish("ESP0003/timeWiFiConnect", countchar);
  }
}

ZyaK
Сообщения: 407
Зарегистрирован: Вт окт 24, 2017 2:01 pm
Откуда: Ижевск
Благодарил (а): 45 раз
Поблагодарили: 69 раз

Re: ESP8266 Arduino IDE Частое переподключение Wifi

Сообщение ZyaK » Ср май 18, 2022 10:55 am

лень разбираться, вот мой скетч на опрос 8 сенсорных кнопок и управлением 8-ю реле со сдвиговым регистром с защелкой.
всё работает, реконнектов нет.
https://mjdm.ru/forum/viewtopic.php?t=6 ... 95#p101695

Код: Выделить всё

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
//#include <ESP8266mDNS.h>

const char* ssid = "***********"; //Название сети
const char* password = "***********";           //пароль
const char* Smart_Home = "*************";    //ip брокера mqtt


#define BUTTON_1 3
#define BUTTON_2 5                           //Кнопка
#define BUTTON_3 4
#define BUTTON_4 0
#define BUTTON_5 2
#define BUTTON_6 14
#define BUTTON_7 12
#define BUTTON_8 13

#define relays_topic "ESP01/#"
#define relays_topic1 "ESP01/r_1"
#define relays_topic2 "ESP01/r_2"
#define relays_topic3 "ESP01/r_3"
#define relays_topic4 "ESP01/r_4"
#define relays_topic5 "ESP01/r_5"
#define relays_topic6 "ESP01/r_6"
#define relays_topic7 "ESP01/r_7"
#define relays_topic8 "ESP01/r_8"


#define clk 15
#define data 16
#define latch 1

WiFiClient espClient;                        //инициализация WiFi клиента
PubSubClient client(espClient);              //инициализация MQTT клиента

long last_mls = millis();                    //функция времени в милисекундах

boolean Status1 = false;                       //объявляем статус реле в 0
boolean btnPress1 = false;                    //объявляем что кнопка не нажата 0
boolean lastbtnStat1 = false;                 //временная переменная для хранения статуса
boolean Status2 = false;
boolean btnPress2 = false;                    //объявляем что кнопка не нажата 0
boolean lastbtnStat2 = false;
boolean Status3 = false;
boolean btnPress3 = false;                    //объявляем что кнопка не нажата 0
boolean lastbtnStat3 = false;
boolean Status4 = false;
boolean btnPress4 = false;                    //объявляем что кнопка не нажата 0
boolean lastbtnStat4 = false;
boolean Status5 = false;
boolean btnPress5 = false;                    //объявляем что кнопка не нажата 0
boolean lastbtnStat5 = false;
boolean Status6 = false;
boolean btnPress6 = false;                    //объявляем что кнопка не нажата 0
boolean lastbtnStat6 = false;
boolean Status7 = false;
boolean btnPress7 = false;                    //объявляем что кнопка не нажата 0
boolean lastbtnStat7 = false;
boolean Status8 = false;
boolean btnPress8 = false;                    //объявляем что кнопка не нажата 0
boolean lastbtnStat8 = false;

int regim1 = 0;                               //режим по умолчанию при включении
int regim2 = 0;
int regim3 = 0;
int regim4 = 0;
int regim5 = 0;
int regim6 = 0;
int regim7 = 0;
int regim8 = 0;

int Dannie = 0;

void setup() {

  pinMode(clk, OUTPUT);
  pinMode(data, OUTPUT);
  pinMode(latch, OUTPUT);
  digitalWrite(latch, HIGH);

  digitalWrite(latch, LOW);
  shiftOut(data, clk, LSBFIRST, 0b11111111);
  digitalWrite(latch, HIGH);

  pinMode(BUTTON_1, INPUT);
  pinMode(BUTTON_2, INPUT);
  pinMode(BUTTON_3, INPUT);
  pinMode(BUTTON_4, INPUT);
  pinMode(BUTTON_5, INPUT);
  pinMode(BUTTON_6, INPUT);
  pinMode(BUTTON_7, INPUT);
  pinMode(BUTTON_8, INPUT);
  //Кнопка

  //Serial.begin(9600);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);                //подключаемся к WiFi
  delay(6000);

  client.setServer(Smart_Home, 1883);       //подключаемся к MQTT
  client.setCallback(callback);              //функция получения топиков с брокера
  delay(100);

  //Serial.println("");
  //Serial.println("WiFi connected");
  //Serial.println("IP address: ");
  //Serial.println(WiFi.localIP());

  client.connect("ESP01Client");
  delay (100);//конектимся с брокером как клиент

  client.subscribe(relays_topic);
  client.loop();
  client.publish(relays_topic1, String(regim1).c_str());
  client.loop();
  client.publish(relays_topic2, String(regim2).c_str());
  client.loop();
  client.publish(relays_topic3, String(regim3).c_str());
  client.loop();
  client.publish(relays_topic4, String(regim4).c_str());
  client.loop();
  client.publish(relays_topic5, String(regim5).c_str());
  client.loop();
  client.publish(relays_topic6, String(regim6).c_str());
  client.loop();
  client.publish(relays_topic7, String(regim7).c_str());
  client.loop();
  client.publish(relays_topic8, String(regim8).c_str());
  client.loop();


}

void callback(char* topic, uint8_t* payload, unsigned int length) {
  //Serial.print("Message arrived [");
  //Serial.print(topic);
  //Serial.print("  ");
  String strTopic = String(topic);
  String strPayload = String((char*)payload);
  for (unsigned int i = 0; i < length; i++) {
    //Serial.print((char)payload[i]);
  }
  //Serial.println();
  if (strTopic == "ESP01/r_1") {
    if ((char)payload[0] == '0') {
      Status1 = false;
      regim1 = 0;
    }
    else if ((char)payload[0] == '1') {
      Status1 = true;
      regim1 = 1;
    }
  }

  if (strTopic == "ESP01/r_2") {
    if ((char)payload[0] == '0') {
      Status2 = false;
      regim2 = 0;
    }
    else if ((char)payload[0] == '1') {
      Status2 = true;
      regim2 = 1;
    }
  }
  if (strTopic == "ESP01/r_3") {
    if ((char)payload[0] == '0') {
      Status3 = false;
      regim3 = 0;
    }
    else if ((char)payload[0] == '1') {
      Status3 = true;
      regim3 = 1;
    }
  }
  if (strTopic == "ESP01/r_4") {
    if ((char)payload[0] == '0') {
      Status4 = true;
      regim4 = 0;
    }
    else if ((char)payload[0] == '1') {
      Status4 = false;
      regim4 = 1;
    }
  }
  if (strTopic == "ESP01/r_5") {
    if ((char)payload[0] == '0') {
      Status5 = false;
      regim5 = 0;
    }
    else if ((char)payload[0] == '1') {
      Status5 = true;
      regim5 = 1;
    }
  }
  if (strTopic == "ESP01/r_6") {
    if ((char)payload[0] == '0') {
      Status6 = false;
      regim6 = 0;
    }
    else if ((char)payload[0] == '1') {
      Status6 = true;
      regim6 = 1;
    }
  }
  if (strTopic == "ESP01/r_7") {
    if ((char)payload[0] == '0') {
      Status7 = false;
      regim7 = 0;
    }
    else if ((char)payload[0] == '1') {
      Status7 = true;
      regim7 = 1;
    }
  }
  if (strTopic == "ESP01/r_8") {
    if ((char)payload[0] == '0') {
      Status8 = false;
      regim8 = 0;
    }
    else if ((char)payload[0] == '1') {
      Status8 = true;
      regim8 = 1;
    }
  }
  Dannie = (regim1 << 7) | (regim2 << 6) | (regim3 << 5) | (regim4 << 4) | (regim5 << 3) | (regim6 << 2) | (regim7 << 1) | (regim8);
  client.loop();

}

void button1()
{
  btnPress1 = digitalRead(BUTTON_1);
  if (btnPress1 == LOW && lastbtnStat1 == false)
  {
    delay(100); // защита от дребезга
    btnPress1 = digitalRead(BUTTON_1);
    if (btnPress1 == LOW && lastbtnStat1 == false)
    {
      regim1++;
      lastbtnStat1 = true;
      if (regim1 > 1)
      {
        regim1 = 0;
      }
      client.publish(relays_topic1, String(regim1).c_str());

    }
  }
  if (btnPress1 == HIGH && lastbtnStat1 == true)
  {
    lastbtnStat1 = false;
  }

  if (regim1 == 0)
  {
    Status1 = false;

  }
  if (regim1 == 1)
  {
    Status1 = true;

  }
  client.loop();
}
void button2()
{
  btnPress2 = digitalRead(BUTTON_2);
  if (btnPress2 == LOW && lastbtnStat2 == false)
  {
    delay(100); // защита от дребезга
    btnPress2 = digitalRead(BUTTON_2);
    if (btnPress2 == LOW && lastbtnStat2 == false)
    {
      regim2++;
      lastbtnStat2 = true;
      if (regim2 > 1)
      {
        regim2 = 0;
      }
      client.publish(relays_topic2, String(regim2).c_str());

    }
  }
  if (btnPress2 == HIGH && lastbtnStat2 == true)
  {
    lastbtnStat2 = false;
  }

  if (regim2 == 0)
  {
    Status2 = false;

  }
  if (regim2 == 1)
  {
    Status2 = true;

  }
  client.loop();
}
void button3()
{
  btnPress3 = digitalRead(BUTTON_3);

  if (btnPress3 == LOW && lastbtnStat3 == false)
  {
    delay(100); // защита от дребезга
    btnPress3 = digitalRead(BUTTON_3);
    if (btnPress3 == LOW && lastbtnStat3 == false)
    {
      regim3++;
      lastbtnStat3 = true;
      if (regim3 > 1)
      {
        regim3 = 0;
      }
      client.publish(relays_topic3, String(regim3).c_str());

    }
  }
  if (btnPress3 == HIGH && lastbtnStat3 == true)
  {
    lastbtnStat3 = false;
  }

  if (regim3 == 0)
  {
    Status3 = false;

  }
  if (regim3 == 1)
  {
    Status3 = true;

  }
  client.loop();
}
void button4()
{
  btnPress4 = digitalRead(BUTTON_4);

  if (btnPress4 == LOW && lastbtnStat4 == false)
  {
    delay(100); // защита от дребезга
    btnPress4 = digitalRead(BUTTON_4);
    if (btnPress4 == LOW && lastbtnStat4 == false)
    {
      regim4++;
      lastbtnStat4 = true;
      if (regim4 > 1)
      {
        regim4 = 0;
      }
      client.publish(relays_topic4, String(regim4).c_str());

    }
  }
  if (btnPress4 == HIGH && lastbtnStat4 == true)
  {
    lastbtnStat4 = false;
  }

  if (regim4 == 0)
  {
    Status4 = false;

  }
  if (regim4 == 1)
  {
    Status4 = true;

  }
  client.loop();
}
void button5()
{
  btnPress5 = digitalRead(BUTTON_5);

  if (btnPress5 == LOW && lastbtnStat5 == false)
  {
    delay(100); // защита от дребезга
    btnPress5 = digitalRead(BUTTON_5);

    if (btnPress5 == LOW && lastbtnStat5 == false)
    {
      regim5++;
      lastbtnStat5 = true;
      if (regim5 > 1)
      {
        regim5 = 0;
      }
      client.publish(relays_topic5, String(regim5).c_str());

    }
  }
  if (btnPress5 == HIGH && lastbtnStat5 == true)
  {
    lastbtnStat5 = false;
  }

  if (regim5 == 0)
  {
    Status5 = false;

  }
  if (regim5 == 1)
  {
    Status5 = true;

  }
  client.loop();
}
void button6()
{
  btnPress6 = digitalRead(BUTTON_6);

  if (btnPress6 == LOW && lastbtnStat6 == false)
  {
    delay(100); // защита от дребезга
    btnPress6 = digitalRead(BUTTON_6);

    if (btnPress6 == LOW && lastbtnStat6 == false)
    {
      regim6++;
      lastbtnStat6 = true;
      if (regim6 > 1)
      {
        regim6 = 0;
      }
      client.publish(relays_topic6, String(regim6).c_str());

    }
  }
  if (btnPress6 == HIGH && lastbtnStat6 == true)
  {
    lastbtnStat6 = false;
  }

  if (regim6 == 0)
  {
    Status6 = false;

  }
  if (regim6 == 1)
  {
    Status6 = true;

  }
  client.loop();
}
void button7()
{
  btnPress7 = digitalRead(BUTTON_7);

  if (btnPress7 == LOW && lastbtnStat7 == false)
  {
    delay(100); // защита от дребезга
    btnPress7 = digitalRead(BUTTON_7);

    if (btnPress7 == LOW && lastbtnStat7 == false)
    {
      regim7++;
      lastbtnStat7 = true;
      if (regim7 > 1)
      {
        regim7 = 0;
      }
      client.publish(relays_topic7, String(regim7).c_str());

    }
  }
  if (btnPress7 == HIGH && lastbtnStat7 == true)
  {
    lastbtnStat7 = false;
  }

  if (regim7 == 0)
  {
    Status7 = false;

  }
  if (regim7 == 1)
  {
    Status7 = true;

  }
  client.loop();
}
void button8()
{
  btnPress8 = digitalRead(BUTTON_8);
  if (btnPress8 == LOW && lastbtnStat8 == false)
  {
    delay(100); // защита от дребезга
    btnPress8 = digitalRead(BUTTON_8);
    if (btnPress8 == LOW && lastbtnStat8 == false)
    {
      regim8++;
      lastbtnStat8 = true;
      if (regim8 > 1)
      {
        regim8 = 0;
      }
      client.publish(relays_topic8, String(regim8).c_str());

    }
  }
  if (btnPress8 == HIGH && lastbtnStat8 == true)
  {
    lastbtnStat8 = false;
  }

  if (regim8 == 0)
  {
    Status8 = false;

  }
  if (regim8 == 1)
  {
    Status8 = true;

  }
  client.loop();
}
void reconnect_server() //функция проверки подключения
{
  //Serial.println("");
  //Serial.println("WiFi connected");
  //Serial.println("IP address: ");
  //Serial.println(WiFi.localIP());

  if (WiFi.status() != WL_CONNECTED) //если нет подключения с сети
  {
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);                //подключаемся к WiFi
    delay(6000);
   // Serial.println("");
    //Serial.println("WiFi connect..."); //выводим в монитор порта что пытаемся подключиться
  }
  if (!client.connected() && WiFi.status() == WL_CONNECTED) {
    if (client.connect("ESP01Client")) {
   // Serial.println("Mosquitto connect...");
      client.setServer(Smart_Home, 1883);       //подключаемся к MQTT
      client.setCallback(callback);              //функция получения топиков с брокера
      delay(100);
      client.connect("ESP01Client");
      delay (100);//конектимся с брокером как клиент
      client.subscribe(relays_topic);
      client.loop();
      client.publish(relays_topic1, String(regim1).c_str());
      client.loop();
      client.publish(relays_topic2, String(regim2).c_str());
      client.loop();
      client.publish(relays_topic3, String(regim3).c_str());
      client.loop();
      client.publish(relays_topic4, String(regim4).c_str());
      client.loop();
      client.publish(relays_topic5, String(regim5).c_str());
      client.loop();
      client.publish(relays_topic6, String(regim6).c_str());
      client.loop();
      client.publish(relays_topic7, String(regim7).c_str());
      client.loop();
      client.publish(relays_topic8, String(regim8).c_str());
      client.loop();
       //подписываемся на топики
    }
  }
  Dannie = (regim1 << 7) | (regim2 << 6) | (regim3 << 5) | (regim4 << 4) | (regim5 << 3) | (regim6 << 2) | (regim7 << 1) | (regim8);
  Dannie = ~Dannie;
  digitalWrite(latch, LOW);
  shiftOut(data, clk, LSBFIRST, Dannie);
  digitalWrite(latch, HIGH);
}
void loop()
{
  client.loop();
  button1();
  button2();
  button3();
  button4();
  button5();
  button6();
  button7();
  button8();

  Dannie = (regim1 << 7) | (regim2 << 6) | (regim3 << 5) | (regim4 << 4) | (regim5 << 3) | (regim6 << 2) | (regim7 << 1) | (regim8);
  Dannie = ~Dannie;
  digitalWrite(latch, LOW);
  shiftOut(data, clk, LSBFIRST, Dannie);
  digitalWrite(latch, HIGH);
  //delay(200);
  if (millis() - last_mls > 10000)     //проверка подключений раз в 60 сек
  {
    last_mls = millis();
    reconnect_server();

  }
}
За это сообщение автора ZyaK поблагодарил:
alexmjdm (Ср май 18, 2022 11:39 am)
Рейтинг: 1.16%
PI2 + MQTT + 5 ESP8266 + Atmega16
Диаф
Сообщения: 58
Зарегистрирован: Пт сен 24, 2021 3:02 pm
Благодарил (а): 4 раза
Поблагодарили: 7 раз

Re: ESP8266 Arduino IDE Частое переподключение Wifi

Сообщение Диаф » Вт май 24, 2022 11:08 pm

Посмотри время жизни для адреса на DHCP сервере
За это сообщение автора Диаф поблагодарил:
alexmjdm (Чт июн 02, 2022 11:28 am)
Рейтинг: 1.16%
alexmjdm
Сообщения: 30
Зарегистрирован: Пт сен 04, 2020 10:30 am
Благодарил (а): 35 раз
Поблагодарили: 0

Re: ESP8266 Arduino IDE Частое переподключение Wifi

Сообщение alexmjdm » Чт июн 02, 2022 11:28 am

Диаф писал(а):
Вт май 24, 2022 11:08 pm
Посмотри время жизни для адреса на DHCP сервере
Отправка идет раз в 30 секунд. Так что этот параметр не влияет. За ответ спасибо.
alexsis_76
Сообщения: 791
Зарегистрирован: Пт янв 22, 2016 10:08 am
Благодарил (а): 6 раз
Поблагодарили: 63 раза

Re: ESP8266 Arduino IDE Частое переподключение Wifi

Сообщение alexsis_76 » Чт июн 02, 2022 12:40 pm

Добрый день!
ESP может регистрировать события связанные с wifi, так называемые event-ы(около 10 шт). Можно попытаться поймать событие. Можно взглянуть в логи роутера. Возможно не правильно функционирует код.
За это сообщение автора alexsis_76 поблагодарил:
alexmjdm (Ср июл 20, 2022 9:18 pm)
Рейтинг: 1.16%
Ответить