ESP8266 NodeMCU 堆内存不足 [英] ESP8266 NodeMCU Running Out of Heap Memory
问题描述
我试图通过从我的笔记本电脑(使用 node.js)发送 POST 来使用 ESP8266-01 切换 LED
I am trying to toggle an LED using ESP8266-01 by sending POST from my laptop (using node.js)
我现在有一个内存问题,因为每当我发送 POST 请求时,ESP 中使用的内存增加,堆内存减少,并且在没有剩余内存时崩溃(重新启动).
I now have a memory issue because whenever I send POST request, the memory used in the ESP increases, and heap memory decreases, and it crashes (restart) when theres no memory left.
有什么想法吗?
这是我在 ESP 端的代码(main.lua):
Here is my code on the ESP side (main.lua):
gpio.mode(3, gpio.OUTPUT)
srv=net.createServer(net.TCP,28800)
print("Server created...
")
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
"
message[#message + 1] = "Content-Type: text/html
"
message[#message + 1] = "POST request successfully received
"
elseif(pinState==1)then
gpio.write(3,gpio.LOW)
pinState=0
print("LED OFF")
message[#message + 1] = "HTTP/1.1 200 OK
"
message[#message + 1] = "Content-Type: text/html
"
message[#message + 1] = "POST request successfully received
"
end
elseif(method == "GET")then
message[#message + 1] = "HTTP/1.1 200 OK
"
message[#message + 1] = "Content-Type: text/html
"
message[#message + 1] = "LED STATE="..tostring(pinState).."
"
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 上:
On the 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.
my init.lua is just connecting to Wifi.
感谢您的帮助!
雷伊
推荐答案
NodeMCU docs with the socket:send
example 你似乎已经基于你的实现.我们讨论了它,我修复了它.
There was a problem in the NodeMCU docs with the socket:send
example you seem to have based your implementation on. We discussed it and I fixed it.
您的代码的改进版本是这样的:
An improved version of your code is this:
gpio.mode(3, gpio.OUTPUT)
srv = net.createServer(net.TCP, 28800)
print("Server created...
")
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
"
message[#message + 1] = "Content-Type: text/html
"
print("Method:" .. method);
if (method == "POST") then
message[#message + 1] = "POST request successfully received
"
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) .. "
"
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 填充 message
并且我还删除了最后的重置"和 GC 代码(不再相关).但真正的问题是回调函数中关闭的 upvalues.
I removed some duplicated code wrt populating message
and I also remove the "resetting" and GC code at the end (no longer relevant). The real issue though was with closed upvalues in the callback functions.
你的每个回调函数都应该使用它自己的传递套接字实例的副本,而不是引用一个包装回调函数.
- 第5行
srv:listen(80, function(conn)
回调中的socket变量是conn
. - 在第 6 行还有另一个回调函数,它接收一个套接字,这次称为
sck
.它应该在该函数中被引用为sck
(sck:on()
和send(sck)
). socket:on("sent")
回调本身接收一个/套接字实例.您原来的send()
函数并没有使用它,而是使用了conn
代替.所以,我添加了sk
并在send()
中专门使用了这个.
- On line 5
srv:listen(80, function(conn)
the socket variable in the callback isconn
. - On line 6 there's another callback function which receives a socket, this time called
sck
. It should be referenced within that function assck
(sck:on()
andsend(sck)
). - The
socket:on("sent")
callback itself receives a/the socket instance. Your originalsend()
function didn't not use that though and usedconn
instead. So, I addedsk
and use this one exclusively withinsend()
.
这篇关于ESP8266 NodeMCU 堆内存不足的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!