ESP-8266/ESP32 NodeMCU Lua: азы программирования.

Тема в разделе "ESP8266, ESP32", создана пользователем ИгорьК, 25 июл 2017.

  1. dmitrij2023

    dmitrij2023 Нуб

    Спасибо большое!
    Перенаправление ввода вывода есть в модуле node https://nodemcu.readthedocs.io/en/release/modules/node/#nodeoutput , в принципе этого достаточно, а телнет уже готовое решение. Писал я на автоите эмулятор компорта, дойдут руки займусь.
     
  2. obuhanoe

    obuhanoe Гик

    Доброго дня всем.
    Возник вопрос, как на ESP32 и Lua Nodemcu - определить что нет доступа в интернет (wifi есть, а за интернет например не оплачено или заблокирован доступ в роуторе для esp32).
    Попробовал два варианта, адрес nodemcu взят для примера :

    Код (C++):

    1.
    sk = net.createConnection(net.TCP, 0)
    sk:dns("www.nodemcu.com", function(conn, ip) print(ip) end)
    sk = nil

    2.
    net.dns.resolve("www.nodemcu.com", function(ip_out, sk)
      print(p_out)
    end
    Как проверял - сначала с доступом в интернет - IP возвращается в обоих случаях.
    Потом в интерфейсе роутера заблокировал доступ в инет для esp32 (типа с имитировал отсутствие интернета) и так же в обоих случаях IP возвращался.

    1. Может быть такое, что данные методы кэшируют результат?
    2. Если не правильно использую методы, какие могут быть варианты еще?

    Спасибо
     
  3. ИгорьК

    ИгорьК Гуру

    https://forum.amperka.ru/threads/Автоматическая-перезагрузка-роутера.3502/
     
  4. obuhanoe

    obuhanoe Гик

    ИгорьК нравится это.
  5. ИгорьК

    ИгорьК Гуру

    Не знаю, вы же спрашивали о подходе к проверке Интернет - там это реализовано, посмотрите как. А чтобы взять код и запустить на ESP32 - надо детальнее разбираться. Попробуйте, если не заработает, то все равно ничего не не сломает.
     
    Последнее редактирование: 28 окт 2022
  6. serg3295

    serg3295 Гик

    Зачем вам тут esp32?
    Я в своё время взял розетку Sonoff s20 с esp8265 на борту и всё туда влезает. Даже добавил датчик температуры и sntp для логгирования рестартов. Выглядит гораздо симпатичнее, нежели ваять свой корпус.
    Да и паять меньше. Всего-то 4pin разъём на плату.
     
    ИгорьК нравится это.
  7. obuhanoe

    obuhanoe Гик

    Проверку в ESP32 я тоже делаю через net.dns.resolve, но есть два нюанса:
    1. function(sk, ip) - пример с сайта nodemcu аргументы перепутаны местами и поэтому пример отрабатывает неверно
    Код (C++):
    net.dns.resolve("www.google.com", function(sk, ip)
        print(sk)
        print(ip)
        if (ip == nil) then print("DNS fail!") else print(ip) end
    end)
    2. когда я блокирую доступ ESP32 в интернет (это конечно не то же самое что реально отключили за неуплату) - net.dns.resolve все равно отрабатывает и получается IP.
    Если есть возможность проверить (забрать доступ у ESP32 выход в интернет) - будет получать IP или нет. Или это проблема моего роутера?

    Спасибо
     
    serg3295 нравится это.
  8. obuhanoe

    obuhanoe Гик

    В проекте (не перезагрузка роутера) нужна проверка о которой писал выше.
     
  9. obuhanoe

    obuhanoe Гик

    А вот такой пример, получения данных со страницы (адрес придуманный), действительно не дает получить информацию, когда заблокирован esp32 в роутере. Как только доступ возвращаешь - данные скачиваются со страницы.
    Код (C++):
    srv = net.createConnection(net.TCP, 0)
    srv:on("receive", function(sck, c)

        local start_pos, end_pos = string.find(c, "DDD={"), c:match('^.*()}')
     
        if start_pos ~= nil then
            print(c:sub(start_pos, end_pos))
            print("end2")
        end
        -- далее парсим и сохраняем в файл   c:match( "^%s*(.-)%s*$")
        print("end3")

    end)

    srv:on("connection", function(sck, c)
        sck:send("GET /test.php HTTP/1.1\r\nHost: test.su\r\nConnection: close\r\nAccept: */*\r\n\r\n")
    end)

    srv:connect(80,"test.su")  
     
    ИгорьК нравится это.
  10. serg3295

    serg3295 Гик

    Не то чтобы перепутаны, скорее sk вообще не нужен. Потому как в исходнике вот такая строчка есть в качестве образца вызова:
    // Lua: net.dns.resolve( domain, function(ip) )
    С документацией у них вообще беда. Я отправил несколько PR с правками, потом остановился, так как они новую ветку idf4 открыли и я решил подождать. Сейчас поправлю найденную вами ошибку у себя в аннотациях.
    А кто у вас DNS сервер для esp?
    Код (C++):
    print(net.dns.getdnsserver(0))
    print(net.dns.getdnsserver(1))
    Если роутер, то может он кэширует ответы? Хотя и не должен. Я проверил resolve с выключением интернета (как бы, wan оторвал). Без подключения к внешнему интернету выдал nil. Воткнул провод в wan - resolve отработал. Смотри картинку ниже.
    Извиняюсь, невнимательно прочитал. :confused:
    2022-10-28_16-53.png
     
  11. obuhanoe

    obuhanoe Гик

    print(net.dns.getdnsserver(0)) - адрес роутера 192.168.1.1
    print(net.dns.getdnsserver(1)) - nil

    Так же вытащил кабель из роутера, выполнил по адресам, которые получал ранее данные:google, nodemcu - IP возвращается, причем мгновенно, т.е. данные где то кэшируются, возможно даже в esp32

    Потом взял несколько новых адресов (кабель еще вытащен): rt.ru, mk.ru что в голову пришло - DNS fail стал приходить,не сразу а в течении 4-5 секунд.
    Кабель вставил запросил еще раз rt.ru, mk.ru - ip приходят тоже в течении 3-5 сек.
    Отключил кабель и еще раз запросил - rt.ru, mk.ru - Как и ожидалось IP приходят мгновенно, т.е. явно из кэша чьего-то.
    Как то так. :(
     
  12. serg3295

    serg3295 Гик

    Тогда это кэш роутера. Если в нём включена опция enable DNS relay, то он будет всё кэшировать. Вопрос только во времени обновления кэша. Если relay выключен, то все запросы dns будут сразу уходить к провайдеру. Её рекомендуется включать вообще-то.
     
  13. obuhanoe

    obuhanoe Гик

    Получается нужно другое решение искать?
    Не IP получать, а данные с какого-либо ресурса?
     
  14. ИгорьК

    ИгорьК Гуру

    Полагаю, надо запрашивать какой-то небольшой сайт (ya.ru) и смотреть HTTP status code - нормальный ответ - 200, Вот его то и вылавливать захватом. ESP32 дури много - это ненакладно сделать. Лучше еще поискать сайт - что-то встречал совсем легкое. Хотя просто надо посмотреть что приходит в заголовке, когда связи нет.
     
  15. ИгорьК

    ИгорьК Гуру

    Так вы же сами ответили здесь.
     
  16. serg3295

    serg3295 Гик

    Решение с DNS прекрасно работает. Настройка кэша DNS вообще не во всех роутерах есть. У меня в прошивке OpenWrt размер кэша по умолчанию установлен на 150 записей, на другом роутере с прошивкой Padavan вообще нет выбора, в dnsmasq.conf надо добавлять вручную. Я вообще, честно говоря, на это и не смотрел, пока вы не спросили. Алгоритм, предложенный ИгоремК, определяет отстутствие интернета вполне надёжно. У меня на даче редко бывает что отваливается интернет от базовой станции, и я вижу в логах domoticz'a время когда принудительно рестартовали.
    То есть размер кэша dns в роутере не бесконечен. Сделайте пачку запросов с небольшим интервалом. Запрашивайте не один, а пять разных сайтов. Кэш забьётся, и у вас появиться реальная информация.
    Если бы вы использовали esp8266, то там можно было бы пинговать сайт. На esp32 ping не портировали.
     
    arkadyf и ИгорьК нравится это.
  17. obuhanoe

    obuhanoe Гик

    Значит так и буду проверять.
    Если не затруднит, можете дать пример что туда нужно прописать? Попробую проверить и отпишусь после.

    P.S. - вот это отвечает ?
    Код (Text):
    ### Set the limit on DHCP leases, the default is 150
    #dhcp-lease-max=150
     
  18. ketusur

    ketusur Нуб

    Напоминает спор Apple против Android.
     
  19. obuhanoe

    obuhanoe Гик

    Почему при каждом запуске отправки в telegram, отъедается память.
    Хотя все за собой чищу
    Код (C++):
    local modn = ...
    print("Name module = ", modn)
    local M = {}

    function M.send_telegram(dat)

        local send_data_t_f = function(_tmr)

            _tmr = nil
            if params.ip == nil then
               send_data_t_f = nil
               return
            end
       
            local dat_new = dat.gsub(dat,"\r\n","_") -- убираем перенос строки
            dat_new = dat_new.gsub(dat_new,"%s","+") -- пробелы

            local curl = 'https://api.telegram.org/bot'..params.telegram_bot..'/sendMessage?chat_id='..params.telegram_chat_id..'&text='..dat_new

            local connect = http.createConnection(curl, http.POST)
            connect:on("complete", function(status)
              connect:close()
              dat_new, send_telegram, connect, curl, send_data_t_f = nil, nil, nil, nil, nil
              print("Request completed with status code =", status)      
              package.loaded[modn] = nil
            end)
       
            connect:request()
        end

        tmr.create():alarm(params._second*1.1, tmr.ALARM_SINGLE, send_data_t_f)

    end

    return M
    В ESPlorer выделяю в левом окне и жму Block ():
    Код (C++):
    do

      local sd_t = require("send_data_t")
      sd_t.send_telegram("GR=".."Test")
      sd_t = nil

    end
     
  20. serg3295

    serg3295 Гик

    Чтобы полностью очистить память от модуля необходимо использовать конструкцию:
    Код (C++):
    package.loaded["module_name"] = nil  -- выгружаем
    module_name = nil  -- убиваем ссылку