Lua скрипт не выполняется по порядку
Я хочу получить время, используя EPS8266 с nodeMCU для установки моего RTC на I2C.
Это мой сценарий:
-- file print.lua
local file = assert(loadfile("httpget.lua"))
file() --get Date and Time from google
print("Print follows:") --this should be executed after "file()"
print(date)
Это файл httpget.lua
:
-- file httpget.lua
print('httpget.lua started')
conn=net.createConnection(net.TCP, 0)
-- show the retrieved web page
conn:on("receive", function(conn, payload)
date = string.sub(payload,string.find(payload,"Date: ")
+6,string.find(payload,"Date: ")+35)
conn:close()
end)
conn:on("connection", function(conn, payload)
print('\nConnected')
conn:send("HEAD / HTTP/1.1\r\n"
.."Host: google.com\r\n"
.."Accept: */*\r\n"
.."User-Agent: Mozilla/4.0 (compatible; esp8266 Lua;)"
.."\r\n\r\n")
end)
-- when disconnected, let it be known
conn:on("disconnection", function(conn, payload)
print("Disconnected\r\n"..date)
end)
conn:connect(80,'google.com')
conn = nil
Результат:
> dofile("print.lua")
httpget.lua started
Print follows: -- this should be at the end
nil -- date==nil because httpget.lua not executed
>
Connected
Disconnected
Sun, 26 Apr 2015 10:30:03 GMT
Если я выполню скипт снова (без сброса), я получу дату от исполнения раньше. Что я могу сделать, чтобы выполнить "httpget.lua" и получить "дату" в следующем тексте?
Я использую ESP8266 с NodeMCU 0.9.6 build 20150406 на базе Lua 5.1.4. https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_en
Я загружаю скрипты через USB с ESPlorer v2.0 на мой ESP8266. Команды conn.net... являются частью прошивки NodeMCU (см. Ссылку). Вы можете запустить скрипт только с прошивкой EPS8288 и NodeMCU. Моя проблема в том, что я не могу правильно завершить процедуру conn: net и вернуть данные в следующую часть программы.
2 ответа
Как указывают комментаторы, сетевой код будет работать асинхронно, т.е. conn:on
вызовы будут возвращены немедленно, и их обратные вызовы будут вызваны позже. conn:connect
вызов, вероятно, не асинхронный, но это не помогает.
Сразу после conn:connect
звонок заканчивается print
вызовы будут выполняться, пытаясь распечатать глобальную переменную date
, Большую часть времени это будет печатать nil
поскольку задержка в сети для получения данных от Google будет составлять>10 миллисекунд, что означает, что у вашего кода уже было достаточно времени для выполнения операторов печати. В некоторых редких случаях вы можете получить правильную дату, если вам действительно повезло с задержкой в сети (хотя это было бы очень удивительно).
Чтобы решить эту проблему, вы должны поместить код, который будет выполнен по завершении сетевого запроса, в обратный вызов, который вы передаете conn:on
который получает данные. В вашей текущей структуре кода это немного сложно сделать хорошим способом.
Простое решение заключается в следующем:
local function onReceiveCb(str)
print("Print follows:")
print(str)
end
local file = assert(loadfile("httpget.lua"))
....
Обратите внимание, что я добавил onReceiveCb
перед включением кода httpget. В httpget вы вызываете обратный вызов:
conn:on("receive", function(conn, payload)
date = string.sub(payload,string.find(payload,"Date: ")
+6,string.find(payload,"Date: ")+35)
conn:close()
onReceiveCb(date) -- Call the callback!
end)
Предложение с функцией обратного вызова не сработало. Я получил ошибку компилятора. Я решил это сейчас по-другому. В функции conn:on("отключение", функция (conn, payload) я загружаю файл для установки моего RTC. Таким образом, я могу передать данные в программу, которая устанавливает RTC (см. Мой вывод).
Спасибо за вашу помощь!!!
> dofile("httpget.lua");
httpget.lua started
>
Connected
Disconnected
----------------
Date: Mon, 27 Apr 2015 12:02:17 GMT -- printed in httpget.lua
Date: Mon, 27 Apr 2015 12:02:17 GMT -- printed in set_date.lua
Set RTC:
23 2 19 2 39 4 21 -- Bytes 0-6 in decimal of the DS1307 (1h for Daylight Savings Time added)
done
- Это рабочий скрипт:
print('httpget.lua started')
conn=net.createConnection(net.TCP, 0)
-- show the retrieved web page
conn:on("receive", function (conn, payload)
date = string.sub(payload,string.find(payload,"Date: ")
+0,string.find(payload,"Date: ")+35)
conn:close()
end)
-- when connected, request page (send parameters to a script)
conn:on("connection", function(conn, payload)
print('\nConnected')
conn:send("HEAD / HTTP/1.1\r\n"
.."Host: google.com\r\n"
.."Accept: */*\r\n"
.."User-Agent: Mozilla/4.0 (compatible; esp8266 Lua;)"
.."\r\n\r\n")
end)
-- when disconnected, let it be known
conn:on("disconnection", function(conn, payload)
print("Disconnected\r\n")
print("----------------")
print(date)
dofile("set_date.lua");
end)
conn:connect(80,'google.com')
conn=nil