1

I'm trying to make a simple HTTP server with NodeMCU. I start up nodeMCU then connect it to the wifi and then run the program below. I can connect to the server from my browser. If I keep on reloading the page it would work forever, but when I stop sending requests for a minute or two, the server will somehow stop functioning. Which means, when I reload page nodeMCU does not receive any data (and cannot return any data back).

a=0

function receive(conn,payload) 
    a=a+1
    print(payload) 

    local content="<!DOCTYPE html><html><head><link rel='shortcut icon' href='/'></head><body><h1>Hello!</h1><p>Since the start of the server " .. a .. " connections were made</p></body></html>"
    local contentLength=string.len(content)

    conn:send("HTTP/1.1 200 OK\r\nContent-Length:" .. contentLength .. "\r\n\r\n" .. content)
    conn:close()
end

function connection(conn) 
    conn:on("receive",receive)
end

srv=net.createServer(net.TCP,1) 
srv:listen(8080,connection)

Some things I did:

  • I have stopped the browser from requesting favicon by adding the link to nothing.
  • I set the timeout for inactive client to 1 to prevent the browser from loading for a long time (the browser keeps on loading until timeout).
  • I updated my code to send some HTTP headers.
  • I tried closing and opening the server after each connection (no good because if you keep on doing connections it will never stop working even without this fix).
  • I added conn:close() as suggested by an answer here on StackOverflow.

I'm running precompiled firmware 0.9.6-dev_20150704 integer.

Edit: A solution burried in the comments below

The problem was some sort of incompatiblity between my AP and NodeMCU. To keep NodeMCU responding, I had to keep pinging it from my computer.

IsawU
  • 430
  • 3
  • 12

1 Answers1

2

First of all, you shouldn't use those old 0.9.x binaries. They're no longer supported and contain lots of bugs. Build a custom firmware from the dev (1.5.1) or master (1.4) branch: http://nodemcu.readthedocs.io/en/dev/en/build/.

With version >1.0 of the SDK (this is what you get if you build from current branches) conn:send is fully asynchronous i.e. you can't call it multiple consecutive times. Also, you must not call conn:close() right after conn:send() as the socket would possibly get closed before send() is finished. Instead you can listen to the sent event and close the socket in its callback. Your code works fine on an up-to-date firmware if you consider this.

A more elegant way of asynchronous sending is documented in the NodeMCU API docs for socket:send(). However, that method uses more heap and is not necessary for simple cases with little data like yours.

So, here's the full example with on("sent"). Note that I changed the favicon to an external resource. If you use "/" the browser still issues an extra request against your ESP8266.

a = 0

function receive(conn, payload)
    print(payload) 
    a = a + 1

    local content="<!DOCTYPE html><html><head><link rel='icon' type='image/png' href='http://nodemcu.com/favicon.png' /></head><body><h1>Hello!</h1><p>Since the start of the server " .. a .. " connections were made</p></body></html>"
    local contentLength=string.len(content)

    conn:on("sent", function(sck) sck:close() end)
    conn:send("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length:" .. contentLength .. "\r\n\r\n" .. content)
end

function connection(conn) 
    conn:on("receive", receive)
end

srv=net.createServer(net.TCP, 1) 
srv:listen(8080, connection)
Marcel Stör
  • 22,695
  • 19
  • 92
  • 198
  • Although I have not tried it yet, your answer covers my problem perfectly and the old firmware probably is the issue. – IsawU May 01 '16 at 22:34
  • Okay I'm now running a new firmware and I just found out that my problem with the server stopping responding is caused probably by my WiFi AP... I had some problems with my tablet periodically disconnecting. Now I tried few times to disconnect from WiFi and connect again when the server stopped responding and the server is running again after that. – IsawU May 02 '16 at 11:36
  • That was actually my first guess...until I saw you're running NodeMCU 0.9.6. – Marcel Stör May 02 '16 at 11:41
  • I fixed my tablet issues by connecting with static IP but for nodeMCU it didn't fix anything so what I did is that I use nodeMCU as AP which works just fine (of course the internet is now unaccessible) – IsawU May 02 '16 at 13:37
  • `wifi.sta.config` uses `auto=1`, right? http://nodemcu.readthedocs.io/en/dev/en/modules/wifi/#wifistaconfig – Marcel Stör May 02 '16 at 13:56
  • yes that's true... which would mean that I don't need to use wifi.sta.connect() in my connect to AP program – IsawU May 02 '16 at 14:41
  • I just found a way how to keep NodeMCU connected to the AP. It is not the best, but it stays connected if I connect to the AP and then I start pinging NodeMCU form another device. – IsawU May 02 '16 at 18:17