Lua脚本不按顺序执行。

我想使用EPS8266和nodeMCU获取时间并通过I2C设置RTC。

这是我的脚本:

-- file print.lua
local file = assert(loadfile("httpget.lua"))
file()                  --从 google获取日期和时间
print("Print follows:") --此应在“file()”之后执行
print(date)

这是文件httpget.lua

-- file httpget.lua
print('httpget.lua started')
conn=net.createConnection(net.TCP, 0)
--显示检索的网页
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)

--断开连接后,让它知道
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:              --此应完全在之后
nil                         --因为未执行httpget.lua,date==nil
>
Connected
Disconnected
Sun, 26 Apr 2015 10:30:03 GMT

如果我再次执行脚本(不重置),我会得到先前执行的日期。

我该如何执行“httpget.lua”并在其后面的脚本中获取“date”?

我使用带有NodeMCU 0.9.6构建20150406的ESP8266和由Lua 5.1.4提供动力。 https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_en#index

我使用ESPlorer v2.0通过USB将脚本加载到我的ESP8266中。conn.net ...命令是NodeMCU固件的一部分(请参见链接)。只有使用EPS8288和NodeMCU固件才能运行脚本。我的问题是:我找不到合适的方法来正确结束“conn:net”例程并将数据返回到下一个程序部分。

点赞
用户1366533
用户1366533

正如评论者所指出的,网络代码将异步运行,即conn:on调用将立即返回,它们的回调在稍后调用。conn:connect调用可能不是异步的,但这并没有帮助。

conn:connect调用完成后,您的print调用将运行,尝试打印全局变量date。大多数情况下,由于从Google获取数据的网络延迟将在>> 10毫秒,这意味着您的代码已经有足够的时间执行打印语句,因此大多数情况下这将打印nil。在一些罕见的情况下,如果您在网络延迟方面非常幸运,您可能会得到正确的日期(尽管这将非常惊人)。

要解决这个问题,您需要将要在网络请求完成时执行的代码放入回调中,将回调传递给接收数据的conn:on函数中。在您当前的代码结构中,这有点难以优雅地完成。

一个简单的解决方案是这样的:

local function onReceiveCb(str)
 print("Print follows:")
 print(str)
end
local file = assert(loadfile("httpget.lua"))
....

请注意,我在包括httpget代码之前添加了一个onReceiveCb函数。在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) -- 调用回调!
                     end)
2015-04-26 19:46:37
用户4834101
用户4834101

使用回调函数的提案没有起作用。我得到了一个编译错误。我现在已经用另一种方式解决了它。 在conn:on("disconnection", function(conn, payload)中,我加载文件来设置我的RTC。这样我就可以将数据传递给设置RTC的程序。(请参见我的输出)

感谢您的帮助!!!

> dofile("httpget.lua");
httpget.lua started
>
已连接
已断开连接

----------------
Date: Mon, 27 Apr 2015 12:02:17 GMT -- 在httpget.lua中打印
Date: Mon, 27 Apr 2015 12:02:17 GMT -- 在set_date.lua中打印
设置RTC:
23 2 19 2 39 4 21  --DS1307中字节0-6的十进制数表示(为夏令时添加了1小时)
完成

--这是工作的脚本:

print('httpget.lua started')

conn=net.createConnection(net.TCP, 0)

--显示获取的网页
conn:on("receive", function (conn, payload)
                     date = string.sub(payload,string.find(payload,"Date: ")
                     +0,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)

--当连接断开时,让它知道
conn:on("disconnection", function(conn, payload)
                         print("已断开连接\r\n")
                         print("----------------")
                         print(date)
                         dofile("set_date.lua");
                         end)

conn:connect(80,'google.com')
conn=nil
2015-04-27 18:01:38