ESP8266 NodeMCU 运行 堆内存不足
ESP8266 NodeMCU Running Out of Heap Memory
我正在尝试通过从我的笔记本电脑发送 POST(使用 node.js)来使用 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 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。
感谢您的帮助!
雷伊
您发送的回调应该接受一个参数,一个连接。并且您应该将 on sent 处理程序设置为与 on receive 相同的级别 - 传递给 on receive 的 conn 不一定与传递给 srv:listen.
的 conn 相同
最后,字符串文字的冗余副本是一种内存浪费,(尽管这可能不会导致内存泄漏。)
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
的重复代码,我还删除了最后的 "resetting" 和 GC 代码(不再相关)。真正的问题是回调函数中的 closed upvalues。
你的每个回调函数都应该使用它自己的传递套接字实例的副本,而不是引用包装回调函数之一。
- 第 5 行
srv:listen(80, function(conn)
回调中的套接字变量是 conn
.
- 在第 6 行有另一个接收套接字的回调函数,这次称为
sck
。它应该在该函数中被引用为 sck
(sck:on()
和 send(sck)
)。
socket:on("sent")
回调本身接收 a/the 套接字实例。您原来的 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)
我正在尝试通过从我的笔记本电脑发送 POST(使用 node.js)来使用 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 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。
感谢您的帮助!
雷伊
您发送的回调应该接受一个参数,一个连接。并且您应该将 on sent 处理程序设置为与 on receive 相同的级别 - 传递给 on receive 的 conn 不一定与传递给 srv:listen.
的 conn 相同最后,字符串文字的冗余副本是一种内存浪费,(尽管这可能不会导致内存泄漏。)
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
的重复代码,我还删除了最后的 "resetting" 和 GC 代码(不再相关)。真正的问题是回调函数中的 closed upvalues。
你的每个回调函数都应该使用它自己的传递套接字实例的副本,而不是引用包装回调函数之一。
- 第 5 行
srv:listen(80, function(conn)
回调中的套接字变量是conn
. - 在第 6 行有另一个接收套接字的回调函数,这次称为
sck
。它应该在该函数中被引用为sck
(sck:on()
和send(sck)
)。 socket:on("sent")
回调本身接收 a/the 套接字实例。您原来的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)