问题
I created a lua file that implements a 2relay module to control a rolling shutter through a website.
I followed the led_webserver example and I extended my code from there.
I tried so many ways to send a full html page with the function client:send()
,
but it doesn't seem to work.
It's a page I developed myself and it works on the pc but I couldn't find an easy way to send it.
I declare a local variable (for example test) that contains all the html code and then i put it as parameter in `client:send(test).
Does someone know another way to do so?
回答1:
The TCP stack on the eps8266 doesn't support streaming across IP packets. Each send can be up to one full IP packet but longer than that and you have send them packet by packet using the soc:on("sent",callback)
. See the nodeMCU Unofficial FAQ for more discussion of this.
回答2:
Other posters have given a lot of good information, but I don't think there was a good specific solution to this problem given yet, even in the unofficial FAQ.
To send large static files, you can load them from flash and send them in chunks, using callbacks. As other people have mentioned, there is a limit to how much can be sent with a single call. And multiple send calls in a single callback may not be processed as you expect them to, and may take too much memory. Here is a short example loading and sending a file in chunks:
local idx = 0 --keep track of where we are in the file
local fname = "index.html"
function nextChunk(c) --open file, read a chunk, and send it!
file.open(fname)
file.seek("set", idx)
local str = file.read(500)
if not str then return end --no more to send.
c:send(str)
idx = idx + 500
file.close() --close the file to let other callbacks use the filesystem
end
client:on("sent", nextChunk) --every time we send a chunk, start the next one!
nextChunk(client) --send the first chunk.
or, using coroutines and a timer, we can make it more flexible:
local ready = true --represents whether we are ready to send again
client:on("sent", function() ready=true end) --we are ready after sending the previous chunk is finished.
local function sendFile(fname)
local idx=0 --keep track of where we are in the file
while true do
file.open(fname)
file.seek("set", idx)
local str = file.read(500)
if not str then return end --no more to send.
c:send(str)
ready=false --we have sent something. we are no longer ready.
idx = idx + 500
file.close() --close the file to let other callbacks use the filesystem
coroutine.yield() --give up control to the caller
end
end
local sendThread = coroutine.create(sendFile)
tmr.alarm(0, 100, 1, function() --make a repeating alarm that will send the file chunk-by-chunk
if ready then coroutine.resume(sendThread, "index.html") end
if coroutine.status(sendThread) == "dead" then tmr.stop(0) end --stop when we are done
end)
回答3:
You can use the following:
buf = "<h1> ESP8266 Web Server</h1>";
buf = buf.."<h2>Subtitle</h2>";
client:send(buf);
回答4:
Sending more than a couple hundred bytes in one call fails more often than not. Also realize that multiple successive calls to send within the same lua chunk are queued and performed asynchronously after the chunk returns -- this consumes impractical amounts of memory.
So building a page of any complexity at all with runtime values concatenated in is problematic. A more rational approach is for the ESP8266 to just return data as JSON, and serve the fancy pages from a PC, with embedded script to query the ESP and fold the data into the page.
回答5:
I found a simple solution for this. I had to send a large file containing text and I used the following code for it:
file.open("example.txt","r")
for counter=1, numboflinesinfile-1 do
client:send(file.readline() .. "<br>");
end
file.close()
counter is just a counting variable numberoflinesinfile is the number of lines you want to send.
Not a clean solution and maybe violating all program rules but working as a charm.
来源:https://stackoverflow.com/questions/30544301/send-entire-html-code-with-clientsend-in-nodemcu-esp8266-lua-programming