Lua ESP8266节点MCU堆内存不足
我试图通过从笔记本电脑发送帖子(使用node.js),使用ESP8266-01切换LED 我现在有一个内存问题,因为每当我发送POST请求时,ESP中使用的内存都会增加,堆内存会减少,当没有内存时,它会崩溃(重新启动) 有什么想法吗 以下是我在ESP端的代码(main.lua): 我的init.lua刚刚连接到Wifi 谢谢你的帮助Lua ESP8266节点MCU堆内存不足,lua,esp8266,nodemcu,Lua,Esp8266,Nodemcu,我试图通过从笔记本电脑发送帖子(使用node.js),使用ESP8266-01切换LED 我现在有一个内存问题,因为每当我发送POST请求时,ESP中使用的内存都会增加,堆内存会减少,当没有内存时,它会崩溃(重新启动) 有什么想法吗 以下是我在ESP端的代码(main.lua): 我的init.lua刚刚连接到Wifi 谢谢你的帮助 Rey您发送的回调应该接受一个参数,即连接。您应该将on-sent处理程序设置为与on-receive相同的级别——在接收时传递给的conn不一定与传递给srv:l
Rey您发送的回调应该接受一个参数,即连接。您应该将on-sent处理程序设置为与on-receive相同的级别——在接收时传递给的conn不一定与传递给srv:listen的conn相同
最后,字符串文本的冗余副本是对内存的浪费(尽管这可能不会导致它泄漏)。您的实现所基于的中似乎存在一个问题。我们讨论了一下,我把它修好了 代码的改进版本如下:
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)
我删除了一些重复的代码wrt填充消息
,我还删除了末尾的“重置”和GC代码(不再相关)。但真正的问题是回调函数中的closed
每个回调函数都应该使用自己传递的套接字实例的副本,而不是引用包装回调函数的副本。
- 第5行
回调中的套接字变量是srv:listen(80,函数(conn)
conn
- 第6行有另一个接收套接字的回调函数,这次称为
。它应该在该函数中作为sck
(sck
和sck:On()
)引用send(sck)
- 回调本身接收到一个/socket实例。您原来的
函数没有使用它,而是使用了send()
。因此,我添加了conn
,并在sk
中专门使用这个函数send()
- 因此,Marcel的解决方案起了作用
这里是解决问题的另一个选择:
print("Starting main.lua... \n")
gpio.mode(3, gpio.OUTPUT)
srv=net.createServer(net.TCP,28800)
print("Server created... \n")
srv:listen(80,function(conn)
conn:on("receive", function(conn,request)
local _,_,method,path= string.find(request, "([A-Z]+) (.+)?(.+) HTTP")
local _,_,key,light_level = string.find(request, "(%a+)%s*:%s*(%d+)")
if(method == nil)then
_,_,method,path = string.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 was sent from node.js as the header of the request
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 _,_,method,path = nil
local _,_,key,light_level = nil
local duty=nil
--for debugging
local heapSize=node.heap()
if heapSize<2000 then
node.restart()
end
print("Memory Used:"..collectgarbage("count"))
print("Heap Available:"..heapSize)
local heapSize=nil
--debugging end
end)
end)
print(“启动main.lua…\n”)
gpio.mode(3,gpio.OUTPUT)
srv=net.createServer(net.TCP,28800)
打印(“服务器已创建…\n”)
srv:监听(80,功能(连接)
连接:打开(“接收”,功能(连接,请求)
本地u,u,方法,路径=string.find(请求,([A-Z]+)(.+)?(.+)HTTP)
本地u、u、键、灯光级别=字符串。查找(请求,(%a+%s*:%s*(%d+))
如果(方法==nil),则
_,方法,路径=string.find(请求,“([A-Z]+)(.+)HTTP”)
结束
本地负载=照明水平*1023/100
脉宽调制设置(3500,占空比)
本地消息={}
打印(“级别:…灯光级别)
如果(method==“POST”),那么--light_level作为请求的头从node.js发送
如果(占空比>0),则
pwm.启动(3)
消息={“HTTP/1.0 200确定\r\n内容类型:text/html\r\n\r\n”}
消息[#消息+1]=(亮度/100)
elseif(占空比==0)则
脉宽调制停止(3)
消息={“HTTP/1.0 200确定\r\n内容类型:text/html\r\n\r\n”}
消息[#消息+1]=0
结束
elseif(method==“GET”)然后
message[#message+1]=“HTTP/1.1200确定\r\n内容类型:text/html\r\n\r\n”
消息[#消息+1]=“LED状态=“…tostring(pinState)…”\r\n
结束
本地函数send()
如果#消息>0,则
连接:发送(表。删除(消息,1))
其他的
康涅狄格州:关闭
康涅狄格=零
收集垃圾()
结束
结束
conn:on(“发送”,发送)
发送()
本地消息=nil
局部u,u,方法,路径=nil
本地u,u,按键,灯光_电平=零
本地税=零
--用于调试
本地heapSize=node.heap()
如果是heapSizeHey Marcel,谢谢你的解决方案!我试过了,它成功了:)有趣的是,我也能用不同的方法解决这个问题(我将在下面发布)。我并不觉得奇怪,但你不应该这样做!conn=nil
是固件应该做的事情,不要弄乱套接字实例。在send()
之后所有的local xxx
声明都是误导性的,因为这些变量已经声明,它们已经过时了。
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)
print("Starting main.lua... \n")
gpio.mode(3, gpio.OUTPUT)
srv=net.createServer(net.TCP,28800)
print("Server created... \n")
srv:listen(80,function(conn)
conn:on("receive", function(conn,request)
local _,_,method,path= string.find(request, "([A-Z]+) (.+)?(.+) HTTP")
local _,_,key,light_level = string.find(request, "(%a+)%s*:%s*(%d+)")
if(method == nil)then
_,_,method,path = string.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 was sent from node.js as the header of the request
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 _,_,method,path = nil
local _,_,key,light_level = nil
local duty=nil
--for debugging
local heapSize=node.heap()
if heapSize<2000 then
node.restart()
end
print("Memory Used:"..collectgarbage("count"))
print("Heap Available:"..heapSize)
local heapSize=nil
--debugging end
end)
end)