lua - ESP8266 NodeMCU quedando sin memoria de almacenamiento dinámico
(3)
Entonces la solución de Marcel funcionó.
Aquí hay otra opción para resolver el problema:
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)
Estoy tratando de alternar un LED usando ESP8266-01 enviando POST desde mi computadora portátil (usando node.js)
Ahora tengo un problema de memoria porque cada vez que envío una solicitud POST, la memoria utilizada en el ESP aumenta, y la memoria del montón disminuye, y se bloquea (reinicia) cuando no queda memoria.
¿Alguna idea?
Aquí está mi código en el lado 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)
En el nodo.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);
}
})
mi init.lua solo se está conectando a Wifi.
¡Gracias por tu ayuda!
Rey
Hubo un problema en los
documentos de NodeMCU con el
socket:send
ejemplo en el
que parece haber basado su implementación.
Lo discutimos y lo arreglé.
Una versión mejorada de su código es esta:
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)
Eliminé un
message
duplicado de código wrt y también eliminé el "restablecimiento" y el código GC al final (ya no es relevante).
Sin embargo, el problema real era con
upvalues
cerrados en las funciones de devolución de llamada.
Cada una de sus funciones de devolución de llamada debe usar su propia copia de la instancia de socket aprobada en lugar de hacer referencia a la de una función de devolución de llamada de ajuste.
-
En la línea 5
srv:listen(80, function(conn)
la variable de socket en la devolución de llamada esconn
. -
En la línea 6 hay otra función de devolución de llamada que recibe un socket, esta vez llamada
sck
. Debe hacerse referencia dentro de esa función comosck
(sck:on()
ysend(sck)
). -
La devolución de llamada
socket:on("sent")
recibe una instancia del socket. Sin embargo, su función originalsend()
no usó eso y usóconn
lugar. Entonces, agreguésk
y uso este exclusivamente dentro desend()
.
Su devolución de llamada enviada debe aceptar un parámetro, una conexión. Y debe configurar el controlador en enviado en el mismo nivel que en recepción: la conexión que se pasa a recepción no es necesariamente la misma conexión que se pasa a srv: escuchar.
Por último, las copias redundantes de literales de cadena son un desperdicio de memoria (aunque eso probablemente no hará que se filtre).