ESP8266 NodeMCU Running Out of Heap Memory

后端 未结 3 1711
刺人心
刺人心 2020-11-29 12:10

I am trying to toggle an LED using ESP8266-01 by sending POST from my laptop (using node.js)

I now have a memory issue because whenever I send POST request, the memo

相关标签:
3条回答
  • 2020-11-29 12:27

    So the solution from Marcel worked.

    Here is just another option to solve the problem:

    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)
    
    0 讨论(0)
  • 2020-11-29 12:33

    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... \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)
    

    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.

    Each of your callback functions should use its own copy of the passed socket instance rather referencing the one of a wrapping callback function.

    • On line 5 srv:listen(80, function(conn) the socket variable in the callback is conn.
    • On line 6 there's another callback function which receives a socket, this time called sck. It should be referenced within that function as sck (sck:on() and send(sck)).
    • The socket:on("sent") callback itself receives a/the socket instance. Your original send() function didn't not use that though and used conn instead. So, I added sk and use this one exclusively within send().
    0 讨论(0)
  • 2020-11-29 12:33

    Your on sent callback should accept one parameter, a connection. And you should setup the on sent handler at the same level as on receive -- conn that's passed to on receive is not necessarily the same conn passed to srv:listen.

    Lastly, redundant copies of string literals is a waste of memory, (though that likely won't cause it to leak.)

    0 讨论(0)
提交回复
热议问题