• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Вопрос Странная логика выполнения Lua-скрипта

emc-problem.net

New member
Всем привет!

Совсем недавно начал осваивать esp8266. Эксперименты провожу на отладочной плате NodeMCU v3.
Залил последнюю прошивку powered by Lua 5.1.4 on SDK 1.5.4.1(39cb9a32)
Установил последний ESPlorer

Захотел разобраться как подключаться к точке доступа.

Вот такой скрипт работает без вопросов
Код:
 wifi.sta.config("SSID", "pass", 0)
wifi.sta.connect()
tmr.alarm(1, 1000, 1, function()
  if wifi.sta.getip()== nil then
  print("IP unavaiable, Waiting...")
else
  tmr.stop(1)
  print("ESP8266 mode is: ", wifi.getmode())
  print("Config done, IP is ", wifi.sta.getip())
  RSSI=wifi.sta.getrssi()
  print("RSSI is", RSSI)
end
end)
Решил попробовать разрывать соединение и дописал код вот так
Код:
wifi.sta.config("SSID", "pass", 0)

wifi.sta.connect()
tmr.alarm(1, 1000, 1, function()
  if wifi.sta.getip()== nil then
  print("IP unavaiable, Waiting...")
else
  tmr.stop(1)
  print("ESP8266 mode is: ", wifi.getmode())
  print("Config done, IP is ", wifi.sta.getip())
  RSSI=wifi.sta.getrssi()
  print("RSSI is", RSSI)
end
end)

wifi.sta.disconnect()
tmr.alarm(1, 1000, 1, function()
  if wifi.sta.getip()== nil then
  tmr.stop(1)
  print("Exit done, IP is ", wifi.sta.getip())
  else
  print("Disconnected, Waiting...")
end
end)
и тут началось веселье! Выполняется только вторая часть кода, т.е. в ESPlorere выводится
> dofile("wifi conn.lua");
> Exit done, IP is nil

Окончательно мой мозг взорвало перестановка кусков кода местами вот так
Код:
wifi.sta.config("SSID", "pass", 0)

wifi.sta.disconnect()
tmr.alarm(1, 1000, 1, function()
  if wifi.sta.getip()== nil then
  tmr.stop(1)
  print("Exit done, IP is ", wifi.sta.getip())
  else
  print("Disconnected, Waiting...")
end
end)

wifi.sta.connect()
tmr.alarm(1, 1000, 1, function()
  if wifi.sta.getip()== nil then
  print("IP unavaiable, Waiting...")
else
  tmr.stop(1)
  print("ESP8266 mode is: ", wifi.getmode())
  print("Config done, IP is ", wifi.sta.getip())
  RSSI=wifi.sta.getrssi()
  print("RSSI is", RSSI)
end
end)
Соответственно в ESPlorere выводится
> dofile("wifi conn.lua");
> IP unavaiable, Waiting...
IP unavaiable, Waiting...
IP unavaiable, Waiting...
ESP8266 mode is: 1
Config done, IP is 192.168.0.101 255.255.255.0 192.168.0.1
RSSI is -54

Как такое может быть?
Из моих размышлений
- wifi conn.lua вместо init.lua
- wifi.sta.config отключен режим автоматического подключени

Спасибо за помощь
 
Последнее редактирование:

Юрий Ботов

Moderator
Команда форума
А чего тут непонятного? Они же ассинхронные.
  1. wifi.sta.config("SSID", "pass", 0)
  2. wifi.sta.connect()
  3. tmr.alarm(1, 1000, 1, function()
  4. if wifi.sta.getip()== nil then
  5. print("IP unavaiable, Waiting...")
  6. else
  7. tmr.stop(1)
  8. print("ESP8266 mode is: ", wifi.getmode())
  9. print("Config done, IP is ", wifi.sta.getip())
  10. RSSI=wifi.sta.getrssi()
  11. print("RSSI is", RSSI)
  12. wifi.sta.disconnect()
  13. tmr.alarm(1, 1000, 1, function()
  14. if wifi.sta.getip()== nil then
  15. tmr.stop(1)
  16. print("Exit done, IP is ", wifi.sta.getip())
  17. else
  18. print("Disconnected, Waiting...")
  19. end
  20. end)
  21. end
  22. end)
На ошибки не проверял (нет Lua под рукой)
 

emc-problem.net

New member
А чего тут непонятного? Они же ассинхронные.
Непонятно почему пропускается первый кусок кода и выполняется сразу второй.
Представленный вами код вроде заработал как надо. Но с точки зрения линейного выполнения программы суть не меняется.
Зато код получается сложночитаемый.

И допустим мне надо между connect и disconnect выполнить кучу всего, получается все это надо также запихивать в ветку else

А можно ссылку какую-нибудь про "асинхронные" команды или если можно, то коротко объяснить
 
Последнее редактирование:

Юрий Ботов

Moderator
Команда форума
И допустим мне надо между connect и disconnect выполнить кучу всего, получается все это надо также запихивать в ветку else
именно так. Но разумнее создать отдельную функцию, все запихнуть в нее и ее вызов уже в в ветку else.
или если можно, то коротко объяснить
Объясню на примере второго блока кода в вашем первом сообщении.
Сначала запускается sta.config он много времени не занимает по сути просто куча присваиваний. С ним все просто, он синхронный.
Потом запускается sta.connect - его выполнение зависит от внешних ресурсов и достаточно длительное.
Затем, не дожидаясь окончания sta.connect запускается tmr.alarm
Затем, не ожидая окончания выполнения sta.connect запускается sta.disconnect и начинает убивать то что еще не до конца создано connect.
Затем опять никого не дожидаясь запускается новый tmr.alarm... причем того же самого таймера - №1 что естественно сбрасывает предыдущий еще не отработавший alarm и заменяет его новым.
Через 1000 мс отрабатывает функция из второго вызова tmr.alarm видит что все закрылось и радостно сообщает что IP = nil...
 

emc-problem.net

New member
@Юрий Ботов огромное спасибо!
Не привык к такой логике выполнения программ :)
Надо будет это как-то учитывать.

А много таких асинхронных функций в Lua? Или вообще все?
 

nikolz

Well-known member
Всем привет!

Совсем недавно начал осваивать esp8266. Эксперименты провожу на отладочной плате NodeMCU v3.
Залил последнюю прошивку powered by Lua 5.1.4 on SDK 1.5.4.1(39cb9a32)
Установил последний ESPlorer

Захотел разобраться как подключаться к точке доступа.

Вот такой скрипт работает без вопросов
Код:
 wifi.sta.config("SSID", "pass", 0)
wifi.sta.connect()
tmr.alarm(1, 1000, 1, function()
  if wifi.sta.getip()== nil then
  print("IP unavaiable, Waiting...")
else
  tmr.stop(1)
  print("ESP8266 mode is: ", wifi.getmode())
  print("Config done, IP is ", wifi.sta.getip())
  RSSI=wifi.sta.getrssi()
  print("RSSI is", RSSI)
end
end)
Решил попробовать разрывать соединение и дописал код вот так
Код:
wifi.sta.config("SSID", "pass", 0)

wifi.sta.connect()
tmr.alarm(1, 1000, 1, function()
  if wifi.sta.getip()== nil then
  print("IP unavaiable, Waiting...")
else
  tmr.stop(1)
  print("ESP8266 mode is: ", wifi.getmode())
  print("Config done, IP is ", wifi.sta.getip())
  RSSI=wifi.sta.getrssi()
  print("RSSI is", RSSI)
end
end)

wifi.sta.disconnect()
tmr.alarm(1, 1000, 1, function()
  if wifi.sta.getip()== nil then
  tmr.stop(1)
  print("Exit done, IP is ", wifi.sta.getip())
  else
  print("Disconnected, Waiting...")
end
end)
и тут началось веселье! Выполняется только вторая часть кода, т.е. в ESPlorere выводится
> dofile("wifi conn.lua");
> Exit done, IP is nil

Окончательно мой мозг взорвало перестановка кусков кода местами вот так
Код:
wifi.sta.config("SSID", "pass", 0)

wifi.sta.disconnect()
tmr.alarm(1, 1000, 1, function()
  if wifi.sta.getip()== nil then
  tmr.stop(1)
  print("Exit done, IP is ", wifi.sta.getip())
  else
  print("Disconnected, Waiting...")
end
end)

wifi.sta.connect()
tmr.alarm(1, 1000, 1, function()
  if wifi.sta.getip()== nil then
  print("IP unavaiable, Waiting...")
else
  tmr.stop(1)
  print("ESP8266 mode is: ", wifi.getmode())
  print("Config done, IP is ", wifi.sta.getip())
  RSSI=wifi.sta.getrssi()
  print("RSSI is", RSSI)
end
end)
Соответственно в ESPlorere выводится
> dofile("wifi conn.lua");
> IP unavaiable, Waiting...
IP unavaiable, Waiting...
IP unavaiable, Waiting...
ESP8266 mode is: 1
Config done, IP is 192.168.0.101 255.255.255.0 192.168.0.1
RSSI is -54

Как такое может быть?
Из моих размышлений
- wifi conn.lua вместо init.lua
- wifi.sta.config отключен режим автоматического подключени

Спасибо за помощь
Подробно не смотрел, но возможно, что у Вас ошибка в программе.
это условие wifi.sta.getip()== nil никогда не возникает.
Посмотрите по библиотеке может ли функция wifi.sta.getip() возвращать nil.
 

emc-problem.net

New member
Подробно не смотрел, но возможно, что у Вас ошибка в программе.
это условие wifi.sta.getip()== nil никогда не возникает.
Посмотрите по библиотеке может ли функция wifi.sta.getip() возвращать nil.
Мануал четко говорит - Returns nil if IP = "0.0.0.0"
В принципе @Юрий Ботов объяснил в чем дело.
Спасибо
 

Юрий Ботов

Moderator
Команда форума
@Юрий Ботов огромное спасибо!
Не привык к такой логике выполнения программ :)
Надо будет это как-то учитывать.

А много таких асинхронных функций в Lua? Или вообще все?
Да почти все. Сам язык построен на идеологии событий и их обработчиков.

... уточнюсь: все интерфейсные, те которые работают с внешними устройствами. Все вычислительные функции разумеется простые синхронные.
 

nikolz

Well-known member
Вообще-то он объяснил Вам не правильно.
У Вас в программе вторая часть затирает первую.
Т е в таблицу tmr будет записана функция alarm, у которой колбек функция будет определена как во второй части.
 

Юрий Ботов

Moderator
Команда форума
Т е в таблицу tmr будет записана функция alarm, у которой колбек функция будет определена как во второй части.
Затем опять никого не дожидаясь запускается новый tmr.alarm... причем того же самого таймера - №1 что естественно сбрасывает предыдущий еще не отработавший alarm и заменяет его новым.
Через 1000 мс отрабатывает функция из второго вызова tmr.alarm видит что все закрылось и радостно сообщает что IP = nil...
И чего не правильно?
 

nikolz

Well-known member
И чего не правильно?
таймер запускается лишь один раз -второй.
так как при загрузке скрипта в таблицу два раза в одну и туже ячейку пишется два различных вызова колбека.
После чего выполняется интерпретация последнего колбека.
Но ошибка в объяснении в том, что асинхронность здесь не причем.
 

emc-problem.net

New member
Друзья! Я думаю Вы оба правы.
Сейчас дал таймерам разные номера, в итоге выводиться вот такие сообщения

> dofile("wifi conn3.lua");
IP unavaiable, Waiting...
Exit done, IP is nil
IP unavaiable, Waiting...
IP unavaiable, Waiting...
IP unavaiable, Waiting...
IP unavaiable, Waiting...
IP unavaiable, Waiting...
IP unavaiable, Waiting...
IP unavaiable, Waiting...


Т.е. видно, что начинается подключение, но не успев выполниться происходит дисконнект (убивая процесс коннекта) и уже потом постоянны тщетные попытки подключиться.

Всем еще раз спасибо!
 
Сверху Снизу