• Система автоматизации с открытым исходным кодом на базе 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
Алгоритм в законченном варианте был у предыдущего проекта, сейчас я выдёргиваю/переписываю куски кода из него, чтобы реализовать другой, аналогичный, но с другими функциями и железом.
--------------------
Вы полагаю путаете алгоритм и его кодирование. Алгоритм пишут на том языке, на котором Вы привыкли мыслить. Сомневаюсь, что Вы мыслите на Си лучше, чем на русском языке.
А после того, как Вы разрисовали(расписали ) свой алгоритм Вы его кодируете на том языке, с которого его можно преобразовать в исполняемый(интерпретируемый) код для железа.
Если научитесь делать так, как я рекомендую, то будете делать Ваши проекты в десятки раз быстрее и компактнее.
 
Сверху Снизу