ESP8266 NodeMCU耗尽堆内存

时间:2016-05-19 06:36:20

标签: lua esp8266 nodemcu

我试图通过从我的笔记本电脑发送POST来使用ESP8266-01切换LED(使用node.js)

我现在有一个内存问题,因为每当我发送POST请求时,ESP中使用的内存会增加,堆内存会减少,并且当没有内存时它会崩溃(重启)。

有什么想法吗?

这是我在ESP方面的代码(main.lua):

gpio.mode(3, gpio.OUTPUT)
srv=net.createServer(net.TCP,28800)
print("Server created... \n")
local pinState=0
srv:listen(80,function(conn)
    conn:on("receive", function(conn,request)
        local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
        if(method == nil)then
            _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
        end
        local message={}
        print("Method:"..method);
        if(method == "POST")then
          if(pinState==0)then
              gpio.write(3,gpio.HIGH)
              pinState=1
              print("LED ON")
              message[#message + 1] = "HTTP/1.1 200 OK\r\n"
              message[#message + 1] = "Content-Type: text/html\r\n\r\n"
              message[#message + 1] = "POST request successfully received\r\n"
           elseif(pinState==1)then
              gpio.write(3,gpio.LOW)
              pinState=0
              print("LED OFF")
              message[#message + 1] = "HTTP/1.1 200 OK\r\n"
              message[#message + 1] = "Content-Type: text/html\r\n\r\n"
              message[#message + 1] = "POST request successfully received\r\n"
           end 
        elseif(method == "GET")then
           message[#message + 1] = "HTTP/1.1 200 OK\r\n"
           message[#message + 1] = "Content-Type: text/html\r\n\r\n"
           message[#message + 1] = "LED STATE="..tostring(pinState).."\r\n"
        end
        local function send()
          if #message > 0 then 
             conn:send(table.remove(message, 1))
          else
             conn:close()
          end
        end
        conn:on("sent", send)
        send()
        local message={}
        local _, _, method, path, vars= {}
        local heapSize=node.heap()
        if heapSize<1000 then
           node.restart()
        end
        collectgarbage()
        print("Memory Used:"..collectgarbage("count"))
        print("Heap Available:"..heapSize)
    end)
end)

在node.js上:

var request = require('request');
// Configure request
var options = {
    url: 'http://192.168.1.91',//ESP's IP address
    method: 'POST'
}
// Start the request
request(options, function (error, response, body) 
{
    if(!error) 
    {
        return console.log('Server responded with:',body);
    }
    if(error)
    {
        return console.error('ERROR:', error);
    }
})

我的init.lua只是连接到Wifi。

感谢您的帮助!

雷伊

3 个答案:

答案 0 :(得分:2)

您似乎根据自己的实施情况NodeMCU docs with the socket:send example出现了问题。我们讨论了它并修复了它。

您的代码的改进版本是:

gpio.mode(3, gpio.OUTPUT)
srv = net.createServer(net.TCP, 28800)
print("Server created... \n")
local pinState = 0
srv:listen(80, function(conn)
    conn:on("receive", function(sck, request)
        local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
        if (method == nil) then
            _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
        end
        local message = {}
        message[#message + 1] = "HTTP/1.1 200 OK\r\n"
        message[#message + 1] = "Content-Type: text/html\r\n\r\n"
        print("Method:" .. method);
        if (method == "POST") then
            message[#message + 1] = "POST request successfully received\r\n"
            if (pinState == 0) then
                gpio.write(3, gpio.HIGH)
                pinState = 1
                print("LED ON")
            elseif (pinState == 1) then
                gpio.write(3, gpio.LOW)
                pinState = 0
                print("LED OFF")
            end
        elseif (method == "GET") then
            message[#message + 1] = "LED STATE=" .. tostring(pinState) .. "\r\n"
        end
        local function send(sk)
            if #message > 0 then
                sk:send(table.remove(message, 1))
            else
                sk:close()
                message = nil
                print("Heap Available:" .. node.heap())
            end
        end
        sck:on("sent", send)
        send(sck)
    end)
end)

我删除了填充message的一些重复代码,我还删除了“重置”和GC代码(不再相关)。但真正的问题是在回调函数中关闭了upvalues

每个回调函数都应该使用自己传递的套接字实例的副本,而不是引用包装回调函数。

  • 在第5行srv:listen(80, function(conn),回调中的套接字变量为conn
  • 在第6行,有另一个回调函数接收套接字,这次调用sck。它应该在该函数中被引用为scksck:on()send(sck))。
  • socket:on("sent")回调本身接收/ socket实例。您原来的send()函数并没有使用它,而是使用了conn。因此,我添加了sk并在send()内完全使用此内容。

答案 1 :(得分:0)

您的on sent sent call应该接受一个参数,一个连接。你应该设置与发送处理程序处于同一级别的接收 - 在接收时传递给的conn不一定是传递给srv:listen的conn。

最后,字符串文字的冗余副本是浪费内存,(尽管这可能不会导致它泄漏。)

答案 2 :(得分:0)

所以Marcel的解决方案有效。

这是解决问题的另一种选择:

var str='<d:BC_1MONTH m:type="Edm.Double">0.11</d:BC_1MONTH>';
str= str.split(" "); 
str= str[0].split(":");
console.log(str[1]);