2016-05-13 19 views
1

Ich habe eine NodeMCU Lua-Anwendung, die zwei Timer verwendet. Jeder Zeitgeber ruft eine Funktion auf, die bewirkt, dass eine HTTP-Anforderung an einen lokalen Server gesendet wird.NodeMCU Timer stoppt unerwartet

Nach einigen Iterationen wird einer der Timer gestoppt und der andere Timer wird fortgesetzt. Die Anzahl der Iterationen vor dem Stopp des Timers scheint zufällig zu sein. Ich habe das Testskript viele Male ausgeführt und der Punkt, an dem der Timer stoppt, ist nie derselbe. Hinweis: Es ist nicht immer der gleiche Timer, der anhält.

Hier finden Sie einige Test-Code, der dieses Problem zuverlässig demonstriert:

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) 

Meine Anwendung so schnell wie der Testcode der HTTP-Anfragen nicht abfeuern, aber wenn die Anwendung läuft für mehrere Stunden das gleiche Ergebnis tritt schließlich auf (dh einer der Timer hört auf zu laufen). Durch die Verkürzung der Zeit zwischen HTTP-Anfragen tritt der Fehler früher auf.

Ist jemand auf dieses Problem gestoßen? Hat jemand irgendwelche Ideen, wie Sie dieses Problem beheben können? (Die Möglichkeit, kontinuierliche HTTP-Anfragen nicht zuverlässig zu senden, ist ein Show-Stop für diese Anwendung).

Antwort

1

Die Lösung besteht darin, Flags so einzurichten, dass immer nur eine HTTP-Anforderung aussteht. Hier ist der vorherige Test-Skript, das den Flags umfasst:

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) 

Ich lief dieses Skript für mehrere Stunden und beide http senden Funktionen weiterhin wie erwartet funktionieren.

ich die node.task.post() Option, Testskript versucht, wie folgt:

einer der http-Rückrufe von ausgeführt wird, wurde nicht aufgerufen
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) 

Aber nach ein paar Stunden, so gab es muss ein Zusammenstoß.

0

Ich weiß nicht viel über NodeMCU, aber gemäß dem Referenzhandbuch werden die Rückruffunktionen http.post und http.get aufgerufen, wenn eine Antwort empfangen wird. Daher werden Zeitgeber nur neu gestartet, wenn eine Antwort empfangen wird. Gibt es eine Chance, dass es eine Verzögerung gibt oder Sie vielleicht nie eine Antwort bekommen?

Das Neustarten eines Timers, nachdem einige Drittanbieter reagiert haben, würde eine variable Verzögerung hinzufügen und daher nicht sehr präzise sein. Ich würde nicht erwarten, dass es so genau ist wie ein Testcode.

Zum Debuggen empfehle ich Ihnen, die tatsächlichen Verzögerungen zwischen aufgerufenen Rückrufe oder die Verzögerung zwischen Post/Get und Antwort zu drucken.

+0

Ihr Kommentar zur Callback-Funktion ist interessant. Ich hatte einen Fall in Nodemcu, wo 2 HTTP-Anfragen nacheinander gestellt wurden und die Antwort auf die zweite Anfrage niemals die Callback-Funktion aufgerufen hat. Durch das Einfügen einer Verzögerung von 1 Sekunde zwischen http-Aufrufen wurde dieses Problem behoben. Ich frage mich, ob die zwei Timer, die unabhängig voneinander arbeiten, eine ähnliche Situation erzeugen (in der zwei HTTP-Anfragen nahe beieinander liegen). Ich werde einige Tests durchführen, um zu sehen, ob eine solche Kollision auftritt. – Jonathan

+0

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