1

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

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

以下是一些可靠地演示此问题的测试代码:

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 请求是这个应用程序的一个障碍)。

4

2 回答 2

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 回调没有被调用,所以肯定发生了冲突。

于 2016-05-14T19:01:28.020 回答
0

我对NodeMCU了解不多,但是根据参考手册,http.post收到http.get响应时会调用回调函数。因此,只有在收到响应时才会重新启动计时器。有没有可能会有延迟,或者您可能永远不会得到回复?

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

对于调试,我建议您打印调用回调之间的实际延迟或发布/获取和响应之间的延迟。

于 2016-05-13T19:05:35.033 回答