2016-05-13 120 views
1

我有一个使用两个计时器的NodeMCU Lua应用程序。每个计时器都会调用一个函数,该函数会导致向本地服务器发出HTTP请求。NodeMCU计时器意外停止

经过几次迭代后,其中一个定时器停止,另一个定时器继续。计时器停止之前的迭代次数似乎是随机的。我已经多次运行测试脚本,并且定时器停止的点也不相同。注意:它并不总是与暂停的计时器相同。

下面是一些测试代码,可靠地说明此问题:

ctr1=0 
ctr2=0 

local function doCmdChk() 
    ctr1 = ctr1 + 1 
    http.get("http://192.168.2.38/ICmd.py?i=" .. ctr1 , nil, 
    function(rspCode, payload) 
     tmr.start(1) 
    end) 
end 

local function sendData() 
    ctr2 = ctr2 + 1 
    local msgBdy = '{"s":"' .. ctr2 .. '","i":"test23", "d":"heap='..node.heap()..'"}' 

    http.post("http://192.168.2.38/DeviceScan.py", "Content-Type: text/json\r\n", msgBdy, 
    function(rspCode, payload) 
     tmr.start(2) 
    end) 
end 

--mainline start: 
tmr.alarm(1, 3000, tmr.ALARM_SEMI, doCmdChk) 
tmr.alarm(2, 5000, tmr.ALARM_SEMI, sendData) 

我的应用程序不会很快关火HTTP请求的测试代码,但是当应用程序运行几个小时同样的结果最终发生(即其中一个定时器停止运行)。减少HTTP请求之间的时间会使错误更早发生。

有没有人遇到过这个问题?有没有人有任何想法如何解决这个问题? (不能够可靠地发送连续的HTTP请求是这个应用程序的一个阻碍)。

回答

1

解决方案是设置标志,以便在任何给定时间只有一个http请求未完成。下面是以前的测试脚本,其中包括标志:

ctr1=0 
ctr2=0 
sendFlag=true 

local function doCmdChk() 
    if sendFlag then 
     sendFlag=false   
     ctr1 = ctr1 + 1 
     http.get("http://192.168.2.38/ICmd.py?i=" .. ctr1 , nil, 
     function(rspCode, payload) 
      sendFlag=true 
      tmr.start(1) 
     end) 
    else 
     tmr.alarm(3, 1000, tmr.ALARM_SINGLE, doCmdChk) 
    end 
end 

local function sendData() 
    if sendFlag then 
     sendFlag=false   
     ctr2 = ctr2 + 1 
     local msgBdy = '{"s":"' .. ctr2 .. '","i":"test23", "d":"heap='..node.heap()..'"}' 

     http.post("http://192.168.2.38/DeviceScan.py", "Content-Type: text/json\r\n", msgBdy, 
     function(rspCode, payload) 
      sendFlag=true 
      tmr.start(2) 
     end) 
    else 
     tmr.alarm(3, 1000, tmr.ALARM_SINGLE, sendData) 
    end 
end 

--mainline start: 
tmr.alarm(1, 3000, tmr.ALARM_SEMI, doCmdChk) 
tmr.alarm(2, 5000, tmr.ALARM_SEMI, sendData) 

我跑这个剧本了几个小时,这两个HTTP发送功能,继续按预期运行。

我试过node.task.post()选项,测试脚本如下:

ctr1=0 
ctr2=0 

local function doCmdChk() 
     ctr1 = ctr1 + 1 
     http.get("http://192.168.2.38/ICmd.py?i=" .. ctr1 , nil, 
     function(rspCode, payload) 
      sendFlag=true 
      tmr.start(1) 
     end) 
end 

local function sendData() 
     ctr2 = ctr2 + 1 
     local msgBdy = '{"s":"' .. ctr2 .. '","i":"test23", "d":"heap='..node.heap()..'"}' 

     http.post("http://192.168.2.38/DeviceScan.py", "Content-Type: text/json\r\n", msgBdy, 
     function(rspCode, payload) 
      sendFlag=true 
      tmr.start(2) 
     end) 
end 

--mainline start: 
tmr.alarm(1, 3000, tmr.ALARM_SEMI, function() node.task.post(node.task.MEDIUM_PRIORITY, doCmdChk) end) 
tmr.alarm(2, 5000, tmr.ALARM_SEMI, function() node.task.post(node.task.HIGH_PRIORITY, sendData) end) 

但一对夫妇正在运行的HTTP回调的一个小时后,没有被引用,那么一定有碰撞。

0

我对NodeMCU了解不多,但根据参考手册,当收到响应时会调用回调函数http.posthttp.get。因此定时器仅在收到响应时才会重新启动。有没有延迟的机会,或者你永远不会得到回应?

一些第三方的东西已经响应后重新启动定时器会增加一个可变延迟,因此不应该非常精确。我不希望它和某些测试代码一样准确。

对于调试,我建议您打印被调用的回调之间的实际延迟或post/get和response之间的延迟。

+0

您对回调函数的评论很有趣。我在Nodemcu中有一个情况,那里有两个http请求一个接一个地做,而对第二个请求的响应从未调用回调函数。在http调用之间插入一个1秒的延迟解决了这个问题。我想知道两个独立运行的定时器是否会产生类似的情况(两个http请求靠近在一起)。我会做一些测试,看看是否会发生这样的碰撞。 – Jonathan

+0

@Jonathan参见https://github.com/nodemcu/nodemcu-firmware/issues/1258 –