ESP8266: Автоматическая перезагрузка роутера. Бюджетный вариант.

Тема в разделе "Глядите, что я сделал", создана пользователем ИгорьК, 18 апр 2015.

  1. alp69

    alp69 Форумчанин

    Так и планирую.
     
  2. alp69

    alp69 Форумчанин

    То есть любой tmr.alarm() в этой ситуации потенциально может "глюкнуть"?
     
  3. ИгорьК

    ИгорьК Гуру

    Нет. Глюкает отсчет времени функцией tmr.now(). То есть и он не глюкает. Просто, когда Вы прибавляете 10 (секунд) к числу 2 147 483 647 (0b01111111111111111111111111111111) - 31 бит в 32 битном числе, то число увеличивается на 10 и Вы ждете наступления этого события. А системный таймер туда не идет, и сбрасывается в ноль. Так что событие не наступит никогда.
    А для tmr.alarm() это (НАДЕЮСЬ) не актуально.
     
  4. alp69

    alp69 Форумчанин

    Попробую спровоцировать.
     
  5. ИгорьК

    ИгорьК Гуру

    Как? :)
    И вообще - это не баг, то фича. Ее надо лишь учитывать. А чтобы учитывать - надо было просто знать :)
     
  6. ИгорьК

    ИгорьК Гуру

    Эскиз. Рабочий. Топик - "connect"
    В топик шлет число "10" каждые 10 секунд.
    Последняя воля - число 0. При первом соединении отправляет последовательно число 0 и 10.
    Если построить график по топику "connect" - будет видно когда было соединение, а когда - упало.

    Код (Lua):
    trying = - 14
    routerPin = 4
    lightPin = 3
    restarting = 0
    gpio.mode(routerPin,gpio.OUTPUT)
    gpio.mode(lightPin,gpio.OUTPUT)
    gpio.write(lightPin,gpio.LOW)
    servrs = {"www.google.com", "ya.ru", "www.yahoo.com"}
    svNow = 1

    Broker = "192.168.0.91"
    port = 1883
    myClient = "connect"
    name = myClient
    pass = "passw"
    publish = false

    m = mqtt.Client(myClient, 30, name, pass)
    m:lwt(myClient, 0, 0, 0)

    function connecting()
        print('(Re)Connecting')
        local getConnect
        getConnect = function()
           print("Start Connect")
           if wifi.sta.status() == 5 and wifi.sta.getip() ~= nil then
                print("Got WiFi!")
                m:connect(Broker, port, 0, 1,
                    function(conn)
                        print("Connected")
                        publish = true
                        m:publish(myClient,0,0,0,function(conn)
                            print("Sent 0 on start")
                            m:publish(myClient,10,0,0,function(conn)
                               print("Sent 10 on start")
                            end)
                        end)
                    end,
                    function(conn,error)
                        print("Lost connection!!!")
                end)
            else
                tmr.alarm(1, 1000, tmr.ALARM_SINGLE, function()
                    getConnect()
                end)
            end
        end
        getConnect()
    end

    m:on("offline", function(con)
          publish = false
    end)

    connecting()

    tmr.alarm(3, 10000, 1, function()
        if publish then
            m:publish(myClient,10,0,0,function(conn)
                print("Sent")
            end)
        end
    end)


    function check(srv)
        net.dns.resolve(srv, function(sk, ip)
            if (ip == nil) then
                print("DNS fail!")
            else
                print("Got IP: "..ip)
                trying, restarting = 0, 0
            end
        end)
    end

    function relay(muv)
        if muv then
            gpio.write(routerPin,gpio.LOW)
            gpio.write(lightPin,gpio.HIGH)
        else
            gpio.write(routerPin,gpio.HIGH)
            gpio.write(lightPin,gpio.LOW)
        end
    end


    function restartRouter()
        tmr.stop(0)
        relay(true)
        restarting = restarting + 1
        print("Restart No "..restarting)

        tmr.alarm(6, 10000, 0, function()
            relay(false)
            if restarting == 1 then
                trying = -14
            elseif restarting == 2 then
                trying = -28
            else
                trying = -120
            end
            tmr.start(0)
            print("Exit Restart Router!")
        end)
    end

    check(servrs[svNow])

    tmr.alarm(0, 30000, 1, function()
        trying = trying + 1
        print("Trying: "..trying)
        svNow = svNow + 1
        if svNow == 4 then svNow = 1 end

        ip = wifi.sta.getip()
        print("Got ip:", ip)
        if ((ip=="0.0.0.0" or ip==nil) and trying > 0) or trying > 3  then
            restartRouter()
        else
            print("Check conection with "..servrs[svNow])
            check(servrs[svNow])
        end
    end)
     
    Вот как это выглядит:
    009.jpg

    И ESPlorer:
    010.jpg

    Вот чем хорошо событийно ориентированное программирование: свалил в кучу два скрипта без размышления и оптимизации, а оно - (фигасе) работает. На Си убился бы все это улаживать между собой.
     
    Последнее редактирование: 17 янв 2017
    sys и alp69 нравится это.
  7. alp69

    alp69 Форумчанин

    Запустить таймер на период, превышающий время работы системного таймера. Точнее в конце цикла таймера. По схеме: старт tmr.alarm - конец цикла системного таймера - срабатывание tmr.alarm. Или полагаете, что не попрет?
     
  8. ИгорьК

    ИгорьК Гуру

    Подчитайте про tmr.alarm() доку и все станет ясно. Там предел значения есть. Если больше - выдаст ошибку и ничто не заведется.
     
  9. Zintut

    Zintut Нуб

    Игорь, добрый день, не подскажете в чем может быть проблема?
    После команды
    wifi.sta.config("APName","Password")
    выводит строчку
    stdin:1: bad argument #1 to 'config' (string expected, got nil)
    дальше ничего не получается. Коннекта к сети не происходит.
     
  10. ИгорьК

    ИгорьК Гуру

    Дело в том, что в последнее время порядок коннекта к сети изменился.
    Читаем здесь: http://forum.amperka.ru/threads/esp-8266-lua-азы-программирования-nodemcu.12558/page-8#post-127507

    Теперь так:

    Код (C++):
    wifi.setmode(wifi.STATION)
    station_cfg={}
    station_cfg.ssid="ТОЧКАДОСТУПА"
    station_cfg.pwd="ПАРОЛЬ"
    station_cfg.auto=true
    station_cfg.save=true
    wifi.sta.config(station_cfg)
    wifi.sta.connect()
     
     
  11. Zintut

    Zintut Нуб

    Ого, спасибо большое за ответ.

    А этот скрипт можно только один раз прописать в строке и отправить через эсплорер или лучше добавить его в самое начало init.lua?
     
  12. ИгорьК

    ИгорьК Гуру

    "Достаточно адной таблэтки"
     
  13. ИгорьК

    ИгорьК Гуру

    Я же Вам ссылку дал где разъясню смысл соединения с Wi-Fi. :-( Эх...
     
  14. Zintut

    Zintut Нуб

    Извините за глупые вопросы, я только учусь.
    Попробовал и так как по ссылке и так как здесь написано. Пока не получается
    после строки
    > wifi.sta.config(station_cfg)
    пишет следующее
    stdin:1: bad argument #1 to 'config' (string expected, got table)
     
  15. ИгорьК

    ИгорьК Гуру

  16. ИгорьК

    ИгорьК Гуру

    Так. Судя по всему у Вас старая прошивка и Вы должны загоняют в сеть плату старым способом. А проблема, вероятно в том, что Вы забыли кавычки в коде, хотя здесь они присутствуют. Об этом пишет компилятор.
     
  17. ИгорьК

    ИгорьК Гуру

    Здесь все абсолютно правильно, но компилятор ругается на первый аргумент "APName", утверждая что он отсутствует, а ожидалось строка. Строка ЗДЕСЬ есть. Значит у вас в коде ее все таки нет - то есть название сети У ВАС без кавычек.

    (Литерал без кавычек воспринимается как переменная. А переменная где-то раньше должна быть определена. Но этого не было, значит ее нет: nil. Об этом и сообщает компилятор.)
     
    Последнее редактирование: 14 сен 2017
  18. Zintut

    Zintut Нуб

    Вы правы, я имя сите и пароль без ковычек вписал.
    Сейчас попробую и то и другое с ковычками
     
  19. ИгорьК

    ИгорьК Гуру

    ... и вот попробуй догадайся что там юзер творит.
     
  20. Airbus

    Airbus Радиохулиган Модератор

    Интересная вещь!Заказал себе "умную розетку" Sonoff для практической реализации чтобы меньше было колхозить просто прошить находящийся внутри esp8266.А тут смотрю уже опередили!Правда код написан в среде Ардуино IDE но практическая реализация мне очень понравилась.Код
    Код (C++):
    #include <ESP8266WiFi.h>
    #include <ESP8266Ping.h>

    const char* ssid = «ssid»; // подставить название своей сети WiFi
    const char* password = «password»; //подставить пароль свой сети WiFi
    //IPAddress ip(192, 168, 1, 70); //Node static IP
    //IPAddress gateway(192, 168, 0, 1);
    //IPAddress subnet(255, 255, 255, 0);

    //const char* remote_host = «www.ya.ru»; //адрес для пинга
    const IPAddress remote_ip(87, 250, 250, 242); // адрес для пинга
    unsigned long previousMillis = 0;
    const long interval = 300; //интервал между пингами в сек
    const long T_ROUTER = 60; // время ожидания загрузки роутера в сек
    const long T_RELAY = 5; // задержка от выключения реле до включения в сек

    int PIN_RELAY = 12;
    int PIN_LED = 13;
    int PIN_BUTTON = 0;
    int COUNT_PING = 0; //количество попыток при отсутствии пинга (не задается)
    int COUNT_PING_MAX = 2; //максимальное количество отсутствия пинга до перезагрузки роутера
    int COUNT_WIFI = 0; //счетчик попыток подключения к WiFi
    int COUNT_WIFI_MAX = 60; //300; // Таймаут до перезагрузки роутера при отсутствии WiFi в сек

    void setup()
    {
    pinMode(PIN_LED, OUTPUT);
    pinMode(PIN_RELAY, OUTPUT);
    pinMode(PIN_BUTTON, INPUT);
    digitalWrite(PIN_RELAY, HIGH);
    digitalWrite(PIN_LED, LOW);
    Serial.begin(115200);
    delay(10);
    attachInterrupt(PIN_BUTTON, Click, FALLING);
    }

    void ConnectWIFI()
    {
    Serial.println(«Подключаюсь к WiFi»);
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    // WiFi.config(ip, gateway, subnet);
    while (WiFi.status() != WL_CONNECTED)
    {
    if (COUNT_WIFI <= COUNT_WIFI_MAX)
    {
    COUNT_WIFI++;
    }
    else
    {
    Serial.println();
    Relay(); //перезагружаемся так как нет подключения к WiFi
    Serial.println(«Подключаюсь к WiFi»);
    }
    //Serial.println(WiFi.status());
    digitalWrite(PIN_LED, !digitalRead(PIN_LED)); //моргаем зеленым светодиодом
    delay(1000);
    Serial.print(".");
    }
    COUNT_WIFI = 0; // сбрасываем счетчик попыток подключения к WiFi
    Serial.println();
    Serial.print(«WiFi подключен, ip:);
    Serial.println(WiFi.localIP());
    //Serial.println(WiFi.status());
    digitalWrite(PIN_LED, LOW); // зажигаем зеленый светодиод
    COUNT_PING = 0; // сбрасываем счетчик неуспешных пингов
    }

    void Relay()
    {
    if (digitalRead(PIN_RELAY) == HIGH)
    {
    digitalWrite(PIN_RELAY, LOW); //отключаем питание на розетке
    Serial.println(“Реле ВЫключено»);
    }
    delay(T_RELAY*1000);
    digitalWrite(PIN_RELAY, HIGH); //включаем питание на розетке
    Serial.println(«Реле Включено, ждем загрузки роутера»);
    delay(T_ROUTER*1000); // ждем загрузки роутера
    COUNT_PING = 0; // сбрасываем счетчик неуспешных пингов
    COUNT_WIFI = 0; // сбрасываем счетчик попыток подключения к WiFi
    previousMillis = 0;
    }

    void Click()
    {
    digitalWrite(PIN_RELAY, LOW); //отключаем питание на розетке
    Serial.println(«Реле выключено кнопкой»);
    }

    void loop()
    {
    if (WiFi.status() != WL_CONNECTED) // нет подключения к WiFi
    {
    ConnectWIFI(); //подключаемся к WiFi
    }
    unsigned long currentMillis = millis();
    if (((currentMillis — previousMillis) >= interval*1000) && (digitalRead(PIN_RELAY) == HIGH) && (WiFi.status() == WL_CONNECTED))
    {
    previousMillis = currentMillis;
    Serial.print(«Попытка пинга:);
    //Serial.println(remote_host);
    Serial.println(remote_ip);
    //if(Ping.ping(remote_host))
    if (Ping.ping(remote_ip))
    { //пинг есть
    Serial.println(“Пинг есть!!»);
    COUNT_PING = 0;// сбрасываем счетчик неуспешных пингов
    } else
    { // пинга нет
    Serial.print(«Пинг отсутствует :();
    COUNT_PING ++;
    Serial.println(COUNT_PING);
    }
    }
    if (COUNT_PING >= COUNT_PING_MAX) // если превышено количество попыток пинга перезагружаем роутер
    {
    Relay();
    }
    if (digitalRead(PIN_RELAY) == LOW) // нажата кнопка, перезагружаем роутер
    {
    Relay();
    }
    }