• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Вопрос Блокировка исполнения на время sta.connect?

ivdok

New member
Суть такова - имеется портянка кода (чуть-чуть обрезал и убрал точки доступа/пароли для релевантности):
Код:
function network()
    print("Network init...")
    --wifi.setmode(wifi.STATION)
    wifi.setmode(wifi.STATIONAP)
    --wifi.setmode(wifi.SOFTAP)
    --Start access point config--
    wifi.ap.config({ssid="Project",pwd="password"})
    wifi.ap.setip({ip="192.168.0.1",netmask="255.255.255.0",gateway="192.168.0.1"})
    wifi.ap.dhcp.config({start="192.168.0.10"})
    wifi.ap.dhcp.start()
    --End access point config--

    --Start router config--
    wifi.sta.config("OpenWrt","password")
    wifi.sta.connect()
    --End router config--
end

function debugging()
    print("WiFi module data:")
    print("Mode: "..tostring(wifi.getmode()))
    print("PHY mode: "..tostring(wifi.getphymode()))
    print("Channel "..tostring(wifi.getchannel()))
    print("Router connection:")
    print(tostring(wifi.sta.getmac()).." as "..tostring(wifi.sta.getip()))
    print("Point connection:")
    print(tostring(wifi.ap.getip()).."/"..tostring(wifi.ap.getbroadcast()))
    print("Users:")
    for mac,ip in pairs(wifi.ap.getclient()) do
        print(tostring(mac).." known as "..tostring(ip))
    end
end
В основном теле кода последовательно выполняются [inline]network()[/inline] и [inline]debugging()[/inline]. По идее, при функциональном программировании функции выполняются последовательно, одна за другой, но в NodeMCU реализовано что-то вроде многопоточности (камнями просьба не бить, знаю, что не многопоточность в истинном смысле этого слова), и эти функции выполняются асинхронно. В итоге они работают настолько быстро, что [inline]wifi.sta.connect()[/inline] не успевает отрабатывать вовремя, чтобы отладочная строка выводила свойства соединения к роутеру. Я пробовал использовать библиотеку nodemcu-timer (GitHub - simenkid/nodemcu-timer: Timer utility in node.js style for NodeMcu on ESP8266 WiFi SoC), но, как я говорил, работает она только в контексте функции, т.е. не блокирует основной поток.

Фикс опционален, устройство работает и так, но с эстетической точки зрения получается "не ок".
P.S. Знаю про злобную-злобную функцию tmr.delay(), которая способна уронить Wi-Fi на чипе на время действия, так что хотелось бы обойтись без неё.
P.P.S. В идеале надо ловить в функции debugging() эвент от network(), но я не знаю, как это делается в контексте NodeMCU.
 

nikolz

Well-known member
Так как не въехал в суть этих программ (
function debugging() выдает кучу принтов), но не понятно что Вы теряете и где, поэтому могу лишь предложить использовать кораунды для многопоточности.
 

ivdok

New member
Так как не въехал в суть этих программ (
function debugging() выдает кучу принтов), но не понятно что Вы теряете и где, поэтому могу лишь предложить использовать кораунды для многопоточности.
Если я вас правильно понял - надо завернуть network() в coroutine.create(), перед выводом строки с подключением сделать coroutine.yield(), в цикле чекать, закончилось ли подключение к роутеру, а затем coroutine.resume()? Я опирался на этот фрагмент: mqtt breaks easily...sending in process · Issue [HASHTAG]#146[/HASHTAG] · nodemcu/nodemcu-firmware · GitHub (правда там он используется в другом контексте, но вроде всё понятно)
А может стоит код писать более логично- в начале делать конфигурацию точки, а затем ее включать. А не наоборот, тогда и функции пойдут последовательно.
Только что пересмотрел код - всё именно так и происходит: задаётся режим чипа, затем настройки точки доступа, затем логин-пароль к роутеру, подключение, и всё. Точку доступа из кода включать не надо - она создаётся сама, а синтаксис конфига доступа к роутеру другой, по сравнению с точкой - параметров меньше, да и таблицу нам создавать не надо. Куда уж ещё логичнее, кроме как если разнести AP и STA в разные .lua и вызывать из основной проги, но это уже маразм какой-то.
 

nikolz

Well-known member
Если я вас правильно понял - надо завернуть network() в coroutine.create(), перед выводом строки с подключением сделать coroutine.yield(), в цикле чекать, закончилось ли подключение к роутеру, а затем coroutine.resume()? Я опирался на этот фрагмент: mqtt breaks easily...sending in process · Issue [HASHTAG]#146[/HASHTAG] · nodemcu/nodemcu-firmware · GitHub (правда там он используется в другом контексте, но вроде всё понятно)

Только что пересмотрел код - всё именно так и происходит: задаётся режим чипа, затем настройки точки доступа, затем логин-пароль к роутеру, подключение, и всё. Точку доступа из кода включать не надо - она создаётся сама, а синтаксис конфига доступа к роутеру другой, по сравнению с точкой - параметров меньше, да и таблицу нам создавать не надо. Куда уж ещё логичнее, кроме как если разнести AP и STA в разные .lua и вызывать из основной проги, но это уже маразм какой-то.
Как я понимаю, ВЫ debugging() постоянно крутите в колбеке?
Почему бы не вызывать ее , если что новое есть?
 

ivdok

New member
Как я понимаю, ВЫ debugging() постоянно крутите в колбеке?
Почему бы не вызывать ее , если что новое есть?
Я её вызываю TCP-пакетом с мобилы по вайфаю, и ещё раньше она раз прокручивалась разок в основном цикле программы. Таким образом, проблему я частично решил, убрав вызов внутри основной программы, но поскольку я собираюсь подключать DS18B20, когда она приедет из Китая, хотелось бы разобраться в этом вопросе сейчас, чтобы у меня не было сюрпризов при отправке данных на телефон.
 

ivdok

New member
@dimka_f eventmon не стал использовать, потому что сам проект стационарный (включил - забыл), а вот эту стену принтов расставил только чтобы понять, почему дропается/не идёт сигнал, т.е. к релизу хотел убрать. Но, может быть, действительно стоит переделать код. Спасибо.
 

ivdok

New member
@dimka_f А сборщик мусора? Я его могу вызывать как по таймеру (опрашивая кучу и вызывая при недостатке памяти), так и после каждого сеанса связи. В крайнем случае - делать софт-ребут, который я и так делаю при каждой заливке кода.
 

nikolz

Well-known member
@dimka_f А сборщик мусора? Я его могу вызывать как по таймеру (опрашивая кучу и вызывая при недостатке памяти), так и после каждого сеанса связи. В крайнем случае - делать софт-ребут, который я и так делаю при каждой заливке кода.
что-то у Вас суетно как-то.
Так обычно бывает, когда нет опыта и нет алгоритма и нет ясности в понимании что и зачем.
 

nikolz

Well-known member
сначала надо нарисовать алгоритм и подумать над ним. - для этого надо всего-то бумагу и карандаш. В результате много ненужного делать не придется.
 

ivdok

New member
сначала надо нарисовать алгоритм и подумать над ним. - для этого надо всего-то бумагу и карандаш. В результате много ненужного делать не придется.
Алгоритм в законченном варианте был у предыдущего проекта, сейчас я выдёргиваю/переписываю куски кода из него, чтобы реализовать другой, аналогичный, но с другими функциями и железом.
 

nikolz

Well-known member
Алгоритм в законченном варианте был у предыдущего проекта, сейчас я выдёргиваю/переписываю куски кода из него, чтобы реализовать другой, аналогичный, но с другими функциями и железом.
--------------------
Вы полагаю путаете алгоритм и его кодирование. Алгоритм пишут на том языке, на котором Вы привыкли мыслить. Сомневаюсь, что Вы мыслите на Си лучше, чем на русском языке.
А после того, как Вы разрисовали(расписали ) свой алгоритм Вы его кодируете на том языке, с которого его можно преобразовать в исполняемый(интерпретируемый) код для железа.
Если научитесь делать так, как я рекомендую, то будете делать Ваши проекты в десятки раз быстрее и компактнее.
 
Сверху Снизу