Скрыть объявление
На нашем форуме недоступен просмотр изображений для неавторизованных пользователей. Если Вы уже зарегистрированы на нашем форуме, то можете войти. Если у Вас еще нет аккаунта, мы будем рады, если Вы к нам присоединитесь. Зарегистрироваться Вы можете здесь.

Нужна помощь Определение наличия подключения к сети WiFi

Тема в разделе "Общие вопросы по esp8266", создана пользователем iG2019, 28 июн 2019.

  1. iG2019

    iG2019 Новичок

    Сообщения:
    14
    Симпатии:
    0
    Нужно чтобы ESP при включении работала не зависмо от наличия сети WiFi, т.е. снимала показания датчиков, щелкала реле и т.д. Как только появляется сеть - подключалась к серверу mqtt и передавала на него показания. В случае пропадания сети продолжала нормальную работу.
    Начал с простенького кода
    Код (Text):
    1.  
    2. #include <OLED_I2C.h>
    3. #include <ESP8266WiFi.h>            
    4. #include <WiFiClient.h>
    5.  
    6. char *ssid = "********"; // Имя роутера
    7. char *pass = "********"; // Пароль роутера
    8.  
    9. OLED  myOLED(D2, D1);
    10.  
    11. extern uint8_t SmallFont[];
    12. extern uint8_t MediumNumbers[];
    13. extern uint8_t BigNumbers[];
    14. void setup() {
    15.    Serial.begin(115200);
    16.   WiFi.begin(ssid, pass);
    17.  
    18. if(!myOLED.begin(SSD1306_128X32))
    19.  while(1);   // In case the library failed to allocate enough RAM for the display buffer...
    20.  
    21.   myOLED.setFont(SmallFont);
    22.  
    23. }
    24.  
    25. void loop() {
    26.   if(WiFi.status() == WL_CONNECTED) {
    27. digitalWrite(LED_BUILTIN, LOW);
    28. Serial.println("WiFi");}
    29.     }
    30.  
    31.   if(WiFi.status() != WL_CONNECTED) {
    32.     digitalWrite(LED_BUILTIN, HIGH);
    33.   Serial.println("NO WiFi");
    34.   }
    35.  
    36. }
    37.  
    Включаю ESP - светодиод загорается, в сериал сыпятся сообщения о наличии WiFi. Выключаю на роутере WiFi - светодиод гаснет, в порт сыпятся сообщения об отсутствии сети. Опять включаю на роутере сеть и ... вот здесь начинаются непонятки. ESP может подключится к сети (светодиод загорается), а может и не подключиться. Аналогичная ситуация происходит если включить ESP при отсутствии сети WiFi. Какой либо закономерности не заметил.
    Подскажите что я делаю не так?
     
  2. CodeNameHawk

    CodeNameHawk Moderator Команда форума

    Сообщения:
    1.618
    Симпатии:
    180
    Так наверное вы все практически и сделали. События отключения и подключения отстают от фактического состояния сети.
    Установите свойства autoconnect и autoreconect, есп будет сама пере подключаться к сети.
     
  3. enjoynering

    enjoynering Авторитетный участник сообщества

    Сообщения:
    549
    Симпатии:
    52
    WiFi.status() == WL_CONNECTED показывает только наличие соединения с точкой доступа/роутером, а у него то как раз связи с инетом может не быть :). Вам нужен ping

    перед отправкой пингуете google.com или православный yandex.ru и если ответ пришел значит интернет есть. Неплохая библиотека обертка ping для arduino esp8266 framework-а ТУТ
     
  4. nikolz

    nikolz Гуру

    Сообщения:
    4.698
    Симпатии:
    452
    если сеть формируется роутером, то в общем случае надо определять три события
    1) работает ли роутер
    2) тот ли адрес дал вам роутер (нужный адрес, если он задан фиксировано в ESP, может быть занят)
    3) работает в сети устройство с котором обмениваемся данными
    подумайте над этим
     
  5. CodeNameHawk

    CodeNameHawk Moderator Команда форума

    Сообщения:
    1.618
    Симпатии:
    180
    Первые два пункты и проверяются WiFi.status().
    Насчет третьего, важно проверять, принял ли сервер посланные данные, а не доступен ли он.
    Проверка доступен ли сервер ничего не дает, проверка может пройти, а следующее обращение к нему может не пройти.
     
  6. kotyara12

    kotyara12 Новичок

    Сообщения:
    10
    Симпатии:
    0
    Не знаю, пригодится ли... Но я делаю это примерно так (см. ниже).
    wifiLoop() вставляю в основной цикл, вся "работа внутри" соединения выполняется в callback функции _cbWiFiConnWork().
    В этом случае ESP в случае обрыва соединения самостоятельно его восстановит, а при отсутствии - может спокойно функционировать и без интернета, автоматика спокойно работает в автономном режиме.

    Код (C):
    1.  
    2.  
    3. typedef enum {
    4.   wifiNotConnected, wifiConnectWait, wifiConnectInit, wifiConnectWork
    5. } wifiConnStage_t;
    6.  
    7. bool wifiConnect()
    8. {
    9.   _ledWiFi->ledBlinkOn(_wifiBlinkConn);
    10.  
    11.   _wifiTryConnect++;
    12.  
    13.   Serial.print(F("WiFi :: Connect to network '"));
    14.   Serial.print(_wifiSSID);
    15.   Serial.print(F("', try "));
    16.   Serial.print(_wifiTryConnect);
    17.   Serial.print(F(" "));
    18.  
    19.   #if defined(ESP32)
    20.     // -- ESP32 :: begin --------------------------------------------------
    21.     _wifiConnectedEvent = WiFi.onEvent(onWiFiConnected, WiFiEvent_t::SYSTEM_EVENT_STA_CONNECTED);
    22.     _wifiGotIPEvent = WiFi.onEvent(onWiFiGotIP, WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP);
    23.     if (_wifiDisconnectedEvent != 0) WiFi.removeEvent(_wifiDisconnectedEvent);
    24.     _wifiDisconnectedEvent = 0;
    25.     // -- ESP32 :: end ----------------------------------------------------
    26.   #else
    27.     // -- ESP8266 :: begin ------------------------------------------------
    28.     _wifiConnectedHandler = WiFi.onStationModeConnected(onWiFiConnected);
    29.     _wifiGotIPHandler = WiFi.onStationModeGotIP(onWiFiGotIP);
    30.     _wifiDisconnectedHandler = nullptr;
    31.     // -- ESP8266 :: end --------------------------------------------------
    32.   #endif
    33.  
    34.   WiFi.mode(WIFI_STA);
    35.   WiFi.setAutoReconnect(false);
    36.   #if defined(ESP32)
    37.     // -- ESP32 :: begin --------------------------------------------------
    38.     WiFi.begin(_wifiSSID.c_str(), _wifiPass.c_str(), 0, NULL, false);
    39.     // -- ESP32 :: end ----------------------------------------------------
    40.   #else
    41.     // -- ESP8266 :: begin ------------------------------------------------
    42.     WiFi.begin(_wifiSSID, _wifiPass, 0, NULL, false);
    43.     // -- ESP8266 :: end --------------------------------------------------
    44.   #endif
    45.  
    46.   _wifiStage = wifiConnectWait;
    47.   wifiConnTimerStart();
    48.   WiFi.reconnect();
    49. }
    50.  
    51. bool wifiConnectionFailed(wl_status_t wifiStatus, const byte printStatus)
    52. {
    53.   Serial.println();
    54.   Serial.println(F("WiFi :: Connection failed!"));
    55.   if (printStatus > 0) {
    56.     wifiPrintStatus(wifiStatus, printStatus > 1);
    57.   };
    58.  
    59.   wifiConnTimerStop();
    60.   WiFi.disconnect(true);
    61.  
    62.   #if defined(ESP32)
    63.     // -- ESP32 :: begin --------------------------------------------------
    64.     if (_cbWiFiConnLost != nullptr) {
    65.       _cbWiFiConnLost(WIFI_REASON_UNSPECIFIED);
    66.     };
    67.     // -- ESP32 :: end ----------------------------------------------------
    68.   #else
    69.     // -- ESP8266 :: begin ------------------------------------------------
    70.     if (_cbWiFiConnLost != nullptr) {
    71.       _cbWiFiConnLost(WIFI_DISCONNECT_REASON_UNSPECIFIED);
    72.     };
    73.     // -- ESP8266 :: end --------------------------------------------------
    74.   #endif
    75.  
    76.   if (_wifiTryConnect >= _wifiTryConnectMax) {
    77.     Serial.println();
    78.     Serial.println(F("*****************************************************************************************"));
    79.     Serial.println(F("$$$                                    SYSTEM RESTART                                 $$$"));
    80.     Serial.println(F("*****************************************************************************************"));
    81.    
    82.     wifiConnTimerStop();
    83.     fixResetReason(RR_WIFI_CONN_ATTEMPTS_EXCEEDED);
    84.     ESP.restart();
    85.   };
    86. }
    87.  
    88. bool wifiLoop()
    89. {
    90.   bool _result = false;
    91.  
    92.   // Проверяем статус подключения к WiFi
    93.   wl_status_t _wifiStatus = WiFi.status();
    94.  
    95.   // Подключение к WiFi еще не было установлено
    96.   if ((_wifiStatus == WL_IDLE_STATUS) || (_wifiStatus == WL_DISCONNECTED)) {
    97.     switch (_wifiStage) {
    98.       // Нет подключения, запускаем процедуру соединяемся...
    99.       case wifiNotConnected:
    100.         wifiConnect();
    101.         break;
    102.  
    103.       // В процессе подключения...
    104.       case wifiConnectWait:
    105.         yield();
    106.         // -- ESP8266 ONLY ------------------------------------------------------
    107.         #if defined(ESP8266)
    108.           // -- ESP8266 :: begin ------------------------------------------------
    109.           if (_connTimer.onRestart()) {
    110.             wifiConnTimerDo();
    111.           };
    112.           // -- ESP8266 :: end --------------------------------------------------
    113.         #endif
    114.         // -- ESP8266 ONLY ------------------------------------------------------
    115.         break;
    116.  
    117.       // Что-то пошло не так, пожалуй лучше всего будет сбросить соединение
    118.       default:
    119.         wifiConnectionFailed(_wifiStatus, 2);
    120.         break;
    121.       };
    122.   }
    123.  
    124.   // Подключение к WiFi установлено
    125.   else if (_wifiStatus == WL_CONNECTED) {
    126.     switch (_wifiStage) {
    127.       // Соединение установлено только что
    128.       case wifiConnectWait:
    129.         _result = true;
    130.         // Меняем частоту мигания светодиода
    131.         _ledWiFi->ledBlinkOn(_wifiBlinkInit);
    132.         // Останавливаем таймер подключения и сбрасываем счетчики
    133.         wifiConnTimerStop();
    134.         _wifiTimeSyncRun = 0;
    135.         _wifiStage = wifiConnectInit;
    136.         break;
    137.  
    138.       // Соединение установлено в предыдущем рабочем цикле
    139.       case wifiConnectInit:
    140.         // Синхронизация времени с NTP, но только если она еще не была ни разу запущена
    141.         if (year() < 2000) {
    142.           // Считаем количество попыток синхронизации времени (так как она почему-то иногда не проходит совсем)
    143.           _wifiTimeSyncRun++;
    144.           if (_wifiTimeSyncRun > _wifiTimeSyncRunMax) {
    145.             // Не удалось синхронизировать время - собрасываем соединение
    146.             wifiConnectionFailed(_wifiStatus, 0);
    147.           }
    148.           else {
    149.             // Запускаем синхронизацию времени c NTP
    150.             _result = true;
    151.             ntpTimeSyncRun();
    152.           };
    153.         }
    154.         else {
    155.           // Ставим отметку, что инициализация завершена
    156.           _wifiStage = wifiConnectWork;
    157.           // Сбрасываем счетчик попыток соединения
    158.           _wifiTryConnect = 0;
    159.           // Выполняем процедуру при установлении соединения
    160.           if (_cbWiFiConnInit != nullptr) {
    161.             _result = true;
    162.             _cbWiFiConnInit(_wifiFisrtConnect);
    163.           };
    164.           // Сбрасываем флаг _wifiFisrtConnect
    165.           if (_wifiFisrtConnect) {
    166.             _wifiFisrtConnect = false;
    167.           };
    168.           // Отключаем мигание светодиода
    169.           _ledWiFi->ledBlinkOff();
    170.         };
    171.         break;
    172.      
    173.       // Соединение установлено и инициализировано
    174.       case wifiConnectWork:
    175.         // Выполняем процедуру при постоянном соединении
    176.         if (_cbWiFiConnWork != nullptr) {
    177.           _result = true;
    178.           _cbWiFiConnWork();
    179.         };
    180.         break;
    181.  
    182.       // Другое состояние
    183.       default:
    184.         wifiConnectionFailed(_wifiStatus, 2);
    185.         break;
    186.     };
    187.   }
    188.  
    189.   // Ошибки : WL_NO_SSID_AVAIL, WL_CONNECTION_LOST, WL_CONNECT_FAILED, WL_SCAN_COMPLETED
    190.   else {
    191.     wifiConnectionFailed(_wifiStatus, 1);
    192.   };
    193.  
    194.   return _result;
    195. };
    Я не утверждаю, что код идеален. Нет, он далек от совершенства, но я над ним постоянно работаю :)

    Выглядит это примерно так:

    Код (Text):
    1. 16:30:41.382 -> Initialization...
    2. 16:30:41.382 -> Sketch version: 20190628.01
    3. 16:30:41.382 -> Inititailize PINs...
    4. 16:30:41.382 -> Inititailize WiFi connection...
    5. 16:30:41.460 -> Inititailize MQTT connection...
    6. 16:30:41.460 -> Inititailize NTP...
    7. 16:30:41.460 -> Inititailize sensors...
    8. 16:30:41.460 -> Read settings from EEPROM...
    9. 16:30:41.460 -> syncRequests = 1
    10. 16:30:41.460 -> intvPublishSensors = 300
    11. 16:30:41.492 -> publThingSpeak = 1
    12. 16:30:41.492 -> Start timers...
    13. 16:30:41.492 -> Initialization complete
    14. 16:30:41.492 ->
    15. 16:30:41.492 -> WiFi :: Connect to network 'Kotyara12', try 1 .
    16. 16:30:42.748 -> WiFi :: Connected to ssid 'Kotyara12', channel 12, rssi: -61
    17. 16:30:43.054 -> WiFi :: Local IP address: 192.168.1.41
    18. 16:30:43.088 -> NTP :: Transmit NTP request to 'ntp1.stratum2.ru' / '88.147.254.230': ok
    19. 16:30:43.292 -> NTP :: Current time: 29.06.2019 16:30:48
    20. 16:30:43.292 -> TELEGRAM :: Message " Устройство запущено, версия скетча 20190628.01" :: added to queue, total 1 messages
    21. 16:30:43.292 -> TELEGRAM :: Send message " Устройство запущено, версия скетча 20190628.01": HTTP/1.1 200 OK
    22. 16:30:46.348 -> MQTT :: Connecting to MQTT server '********:***************@m**.cloudmqtt.com:******'...
    23. 16:30:46.958 -> MQTT :: Connection completed
    24. 16:30:47.264 -> MQTT :: publish '/village/smarthome/sync_status': "1" [0,1] :: ok
    25. 16:30:47.366 -> MQTT :: subscribe on topic '/village/smarthome/sync_status'
    26. 16:30:47.774 -> MQTT :: subscribe on topic '/village/smarthome/ota'
    27. 16:30:48.080 -> MQTT :: subscribe on topic '/village/smarthome/settings/+'
    28. 16:30:48.386 -> MQTT :: subscribe on topic '/village/smarthome/settings/+/+'
    29.  
    Если нужно, могу выслать весь модуль
     
  7. nikolz

    nikolz Гуру

    Сообщения:
    4.698
    Симпатии:
    452
    В SDK есть пример колбека
    который позволяет отследить 10(десять) событий Wi-Fi.
     
  8. iG2019

    iG2019 Новичок

    Сообщения:
    14
    Симпатии:
    0
    это я уже понял и сам, но почему то приведенное мной решение не всегда срабатывает.

    так мне и не важно есть ли инет. Сервер может быть и локальным

    Можете ткнуть носом конкретно где посмотреть?

    з/ы меня бы вполне устроило "стандартное" решение в setup
    Код (Text):
    1. while (WiFi.status() != WL_CONNECTED) {
    2.      delay(500);
    3.      Serial.print(".");
    но оно работает только в условиях стабильной сети WiFi. Если же сеть отсутствует в момент включения ESP то вся работа тормозится.
     
  9. nikolz

    nikolz Гуру

    Сообщения:
    4.698
    Симпатии:
    452
    iG2019,
    стр 58
    рекомендую подробно изучить этот док
    в нем есть ответы на все вопросы по использованию ESP8266
    ---------------------
    список событий найдете в файле user_interface.h их всего 11
     

    Вложения:

  10. iG2019

    iG2019 Новичок

    Сообщения:
    14
    Симпатии:
    0
    объяснили бы еще такому рукожопу как я как этим пользоваться...
    Вставил пример из SDK в свой код
    Код (Text):
    1.  
    2. #include <ESP8266WiFi.h>
    3. #include <WiFiClient.h>
    4.  
    5. char *ssid = "********"; // Имя роутера
    6. char *pass = "********"; // Пароль роутера
    7.  
    8. void setup() {
    9.   Serial.begin(115200);
    10.   WiFi.begin(ssid, pass);
    11.   pinMode(LED_BUILTIN, OUTPUT);
    12. }
    13.  
    14. void loop() {
    15.   if (WiFi.status() == WL_CONNECTED) {
    16.     digitalWrite(LED_BUILTIN, LOW);
    17.   }
    18.  
    19.  
    20.   if (WiFi.status() != WL_CONNECTED) {
    21.     digitalWrite(LED_BUILTIN, HIGH);
    22.   }
    23.  
    24. void wifi_handle_event_cb(System_Event_t *evt);
    25.  
    26.  
    27. }
    28.  
    29.  
    30.  
    31. void wifi_handle_event_cb(System_Event_t *evt)
    32. {
    33.   os_printf("event %x\n", evt->event);
    34.   switch (evt->event) {
    35.     case EVENT_STAMODE_CONNECTED:
    36.       os_printf("connect to ssid %s, channel %d\n",
    37.                 evt->event_info.connected.ssid,
    38.                 evt->event_info.connected.channel);
    39.       break;
    40.     case EVENT_STAMODE_DISCONNECTED:
    41.       os_printf("disconnect from ssid %s, reason %d\n",
    42.                 evt->event_info.disconnected.ssid,
    43.                 evt->event_info.disconnected.reason);
    44.       break;
    45.     case EVENT_STAMODE_AUTHMODE_CHANGE:
    46.       os_printf("mode: %d -> %d\n",
    47.                 evt->event_info.auth_change.old_mode,
    48.                 evt->event_info.auth_change.new_mode);
    49.       break;
    50.     case EVENT_STAMODE_GOT_IP:
    51.       os_printf("ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR,
    52.                 IP2STR(&evt->event_info.got_ip.ip),
    53.                 IP2STR(&evt->event_info.got_ip.mask),
    54.                 IP2STR(&evt->event_info.got_ip.gw));
    55.       os_printf("\n");
    56.       break;
    57.     case EVENT_SOFTAPMODE_STACONNECTED:
    58.       os_printf("station: " MACSTR "join, AID = %d\n",
    59.                 MAC2STR(evt->event_info.sta_connected.mac),
    60.                 evt->event_info.sta_connected.aid);
    61.       break;
    62.     case EVENT_SOFTAPMODE_STADISCONNECTED:
    63.       os_printf("station: " MACSTR "leave, AID = %d\n",
    64.                 MAC2STR(evt->event_info.sta_disconnected.mac),
    65.                 evt->event_info.sta_disconnected.aid);
    66.       break;
    67.     default:
    68.       break;
    69.   }
    70. }
    если я правильно понял то в сериал должны печататься события, но там пусто ...
     
  11. nikolz

    nikolz Гуру

    Сообщения:
    4.698
    Симпатии:
    452
    это функция колбека wifi
    колбеки это такие функции, которые вызывает не пользователь а система
    чтобы система знала что эту функцию надо вызвать при наступлении события
    надо эту функцию зарегистрировать
    регистрация делается один раз
    при инициализации
    в примере на стр 58 это void user_init() - в самом конце
    но это для СИ
    для дурины
    можно поставить
    wifi_set_event_hander_cb(wifi_handle_event_cb);
    в setup
    ---------------------------
    оговорюсь, что я на дурине не пишу поэтому возможно и не сработает
    можно поискать по документации дурины как регистрировать колбеки
    --------------------
     
  12. tretyakov_sa

    tretyakov_sa Moderator Команда форума

    Сообщения:
    982
    Симпатии:
    151
  13. iG2019

    iG2019 Новичок

    Сообщения:
    14
    Симпатии:
    0
    похоже что да, не работает
    Порылся в нете по WiFiEventHandler и кое-что нашел WiFiEventHandler gotIpEventHandler, disconnectedEventHandler; Это, думаю, уже можно будет применить
     
  14. =AK=

    =AK= Гуру

    Сообщения:
    1.224
    Симпатии:
    100
    Вот пример скетча для Wemos, который это делает. В сетапе он пытается подключиться к WiFi в течении 10 сек, если не получилось - уходит в нормальный режим работы и время от времени пытается подключиться снова и снова (см. coos_task_wifi_reconnect). При пропадании WiFi точно так же, старается снова подключиться.

    Когда есть соединение с WiFi , то другая задача, coos_task_mqtt_reconnect, аналогично, следит за соединением с MQTT брокером и переподключается, если связь потеряна.

    Параллельно и независимо от этого скетч снимает показания с датчиков, выводит сообщения на свой дисплей, работает с локальной сетью, и т.п. Все это работает на простенькой кооперативной операционной системе, что позволило отделить задачи друг от друга и выполнять иx квази-одновременно.
     
  15. enjoynering

    enjoynering Авторитетный участник сообщества

    Сообщения:
    549
    Симпатии:
    52
    очень не плохо, но появился вопрос. зачем это самописный велосипед coos, когда в arduino esp8266 давно есть ticker?
     
  16. =AK=

    =AK= Гуру

    Сообщения:
    1.224
    Симпатии:
    100
    Вот этот? Без единого слова описания? Он только для ESP, а coos - для любой Ардино, включая ESP.Причем неизвестно кто из них раньше появился, поскольку на всяких разных платформах coos используется уже лет 15, наверное, с небольшими вариациями.

    Или вот этот? Который позволяет вызывать функции через равные интервалы времени? В нем нет гибкости.

    coos позволяет варировать задержки по мере необходимости, строить сложные автоматы состояния и циклограммы, в том числе с программно управляемыми задержками, а тикер этого не умеет. Причем тикеры ничуть не в меньшей степени "самописные велосипеды", разница только в том, что более широко известны.

    Все-таки coos, хоть и примитивная, но все-таки операционная система, с переключением задач и службой времени, а не просто разновидность таймера Дописав пару строчек кода, в coos можно добавить функциональность, позволяющую задачам останавливать и запускать друг друга, и т.п. Этого не сделано чтобы не пудрить мозги, кому надо - сам сделает.
     
  17. enjoynering

    enjoynering Авторитетный участник сообщества

    Сообщения:
    549
    Симпатии:
    52

Поделиться этой страницей