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
Другие вопросы по тегам