ESP8266 NodeMCU 运行内存不足

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

我现在有一个内存问题,因为每当我发送 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 请求成功接收\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 请求成功接收\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 状态="..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("已使用内存:"..collectgarbage("count"))
        print("剩余堆内存:"..heapSize)
    end)
end)

在 node.js 上:

var request = require('request');
// 配置请求
var options = {
    url: 'http://192.168.1.91',//ESP 的 IP 地址
    method: 'POST'
}
// 开始请求
request(options, function (error, response, body)
{
    if(!error)
    {
        return console.log('服务器响应:',body);
    }
    if(error)
    {
        return console.error('错误:', error);
    }
})

我的 init.lua 只连接到 Wifi。

感谢您的帮助!

Rey

点赞
用户1241224
用户1241224
你的发送回调函数应该接受一个参数——连接。而且你应该将发送处理程序设置在与接收处理程序相同的层次上——传递给接收处理程序的conn不一定与传递给 srv:listen 的 conn 相同。

最后,冗余的字符串常量会浪费内存(虽然这可能不会导致内存泄漏)。
2016-05-20 21:45:44
用户131929
用户131929

NodeMCU文档中的socket:send示例存在问题,你似乎是基于它来实现的。我们进行了讨论并进行了修复。

你的代码的改进版本是:

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代码(不再相关)。然而,真正的问题在于回调函数中的闭合变量。

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

  • 在第5行srv:listen(80,function(conn)中,回调中的套接字变量是conn
  • 在第6行,另一个回调函数接收一个套接字,这次称为sck。它应该在该函数中引用为scksck:on()send(sck))。
  • socket:on(“sent”)回调本身接收一个/ the套接字实例。但是,你最初的send()函数并没有使用它,而是使用了conn。因此,我添加了sk并在send()中仅使用它。
2016-05-22 20:39:42
用户6354580
用户6354580

所以来自Marcel的解决方案起作用了。

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

print(“启动main.lua …\ n”)
gpio.mode(3,gpio.OUTPUT)
srv = net.createServer(net.TCP,28800)
print(“服务器已创建…\ n”)
srv:listen(80,function(conn)
    conn:on(“receive”,function(conn,request)
        local _,_,method,path =字符串.find(request,“([A-Z] +)(.+)?(.+)HTTP”)
        local _,_,key,light_level =字符串.find(request,“(%a +)%s *:(%d +)”)
        if(方法== nil)then
            _,_,method,path =字符串.find(request,“([A-Z] +)(.+)HTTP”)
        end
        local duty = light_level * 1023 / 100
        pwm.setup(3,500,duty)
        local message = {}
        print(“Level:”..light_level)
        if(method ==“POST”)then--light_level作为请求头从node.js发送
            if(duty> 0)then
                pwm.start(3)
                message = {“HTTP / 1.0 200 OK \r \n Content-Type:text / html \r \n \r \n”}
                message [#message + 1] =(light_level / 100)
            elseif(duty == 0)then
                pwm.stop(3)
                message = {“HTTP / 1.0 200 OK \r \n Content-Type:text / html \r \n \r \n”}
                message [#message + 1] = 0
            end
        elseif(method ==“GET”)then
            message [#message + 1] =“HTTP / 1.1 200 OK \r \n 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()
                conn = nil
                collectgarbage()
            end
        end
        conn:on(“sent”,send)
        send()
        local message = nil
        local _,_,方法,路径= nil
        local _,_,key,light_level = nil
        local duty = nil
         - 调试用
        local heapSize = node.heap()
        if heapSize <2000 then
            node.restart()
        end
        print(“已使用的内存:”..collectgarbage(“count”))
        print(“可用的堆栈:”..heapSize)
        local heapSize = nil
        - 调试结束
    end)
end)
2016-05-24 21:13:43