commit
189e4a5c56
12
Makefile
12
Makefile
@ -5,7 +5,9 @@
|
||||
NODEMCU-UPLOADER=../nodemcu-uploader/nodemcu-uploader.py
|
||||
# Serial port
|
||||
PORT=/dev/cu.SLAB_USBtoUART
|
||||
SPEED=9600
|
||||
SPEED=115200
|
||||
|
||||
NODEMCU-COMMAND=$(NODEMCU-UPLOADER) -b $(SPEED) --start_baud $(SPEED) -p $(PORT) upload
|
||||
|
||||
######################################################################
|
||||
# End of user config
|
||||
@ -33,17 +35,17 @@ usage:
|
||||
|
||||
# Upload one files only
|
||||
upload:
|
||||
@python $(NODEMCU-UPLOADER) -b $(SPEED) -p $(PORT) upload $(FILE)
|
||||
@python $(NODEMCU-COMMAND) $(FILE)
|
||||
|
||||
# Upload HTTP files only
|
||||
upload_http: $(HTTP_FILES)
|
||||
@python $(NODEMCU-UPLOADER) -b $(SPEED) -p $(PORT) upload $(foreach f, $^, $(f))
|
||||
@python $(NODEMCU-COMMAND) $(foreach f, $^, $(f))
|
||||
|
||||
# Upload httpserver lua files (init and server module)
|
||||
upload_server: $(LUA_FILES)
|
||||
@python $(NODEMCU-UPLOADER) -b $(SPEED) -p $(PORT) upload $(foreach f, $^, $(f))
|
||||
@python $(NODEMCU-COMMAND) $(foreach f, $^, $(f))
|
||||
|
||||
# Upload all
|
||||
upload_all: $(LUA_FILES) $(HTTP_FILES)
|
||||
@python $(NODEMCU-UPLOADER) -b $(SPEED) -p $(PORT) upload $(foreach f, $^, $(f))
|
||||
@python $(NODEMCU-COMMAND) $(foreach f, $^, $(f))
|
||||
|
||||
|
||||
@ -65,12 +65,13 @@ Let the abuse begin.
|
||||
|
||||
4. How to use HTTP Basic Authentication.
|
||||
|
||||
Enable and configure HTTP Basic Authentication by editing "httpserver-conf.lua" file.
|
||||
Modify variables in configuration file httpserver-conf.lua in order to enable and to configure usernames/passwords.
|
||||
See comments in that file for more details.
|
||||
|
||||
When enabled, HTTP Basic Authentication is global to every file served by the server.
|
||||
|
||||
Remember that HTTP Basic Authentication is a very basic authentication protocol, and should not be
|
||||
considered secure if the server is not using encryption, as your username and password travel
|
||||
considered as secure since the server is not using encryption. Username and passwords travel
|
||||
in plain text.
|
||||
|
||||
## How to use server-side scripting using your own Lua scripts
|
||||
|
||||
@ -1,17 +1,21 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<title>Nice cars</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Nice cars!</h1>
|
||||
<p>This page loads "large" images of fancy cars. It is meant to serve as a stress test for nodemcu-httpserver.</p>
|
||||
<figure><img src="cars-ferrari.jpg" /><figcaption>Ferrari</figcaption></figure>
|
||||
<figure><img src="cars-lambo.jpg" /><figcaption>Lamborghini</figcaption></figure>
|
||||
<figure><img src="cars-mas.jpg" /><figcaption>Maserati</figcaption></figure>
|
||||
<figure><img src="cars-porsche.jpg" /><figcaption>Porsche</figcaption></figure>
|
||||
</body>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<title>Nice cars</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Nice cars!</h1>
|
||||
<p>
|
||||
This page loads "large" images of fancy cars. It is meant to serve as a stress test for nodemcu-httpserver.<br>
|
||||
It works with three embedded images of cars, but the server crashes with four. Edit this file and try it yourself.<br>
|
||||
Whoever manages to modify nodemcu-httpserver to load all four images without crashing wins a prize!
|
||||
</p>
|
||||
<figure><img src="cars-ferrari.jpg" /><figcaption>Ferrari</figcaption></figure>
|
||||
<figure><img src="cars-lambo.jpg" /><figcaption>Lamborghini</figcaption></figure>
|
||||
<figure><img src="cars-mas.jpg" /><figcaption>Maserati</figcaption></figure>
|
||||
<figure><img src="cars-porsche.jpg" /><figcaption>Porsche</figcaption></figure>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
@ -7,12 +7,16 @@ return function (connection, req, args)
|
||||
<h1>Server File Listing</h1>
|
||||
]===])
|
||||
|
||||
local remaining, used, total=file.fsinfo()
|
||||
local remaining, used, total = file.fsinfo()
|
||||
connection:send("<b>Total size: </b> " .. total .. " bytes<br/>\n" ..
|
||||
"<b>In Use: </b> " .. used .. " bytes<br/>\n" ..
|
||||
"<b>Free: </b> " .. remaining .. " bytes<br/>\n" ..
|
||||
"<p>\n<b>Files:</b><br/>\n<ul>\n")
|
||||
"<b>Free: </b> " .. remaining .. " bytes<br/>\n")
|
||||
|
||||
local flashAddress, flashSize = file.fscfg ()
|
||||
connection:send("<b>Flash Address: </b> " .. flashAddress .. " bytes<br/>\n" ..
|
||||
"<b>Flash Size: </b> " .. flashSize .. " bytes<br/>\n")
|
||||
|
||||
connection:send("<p>\n<b>Files:</b><br/>\n<ul>\n")
|
||||
for name, size in pairs(file.list()) do
|
||||
local isHttpFile = string.match(name, "(http/)") ~= nil
|
||||
if isHttpFile then
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
<h3>Serve me some pages!</h3>
|
||||
<ul>
|
||||
<li><a href="index.html">Index</a>: This page (static)</li>
|
||||
<li><a href="cars.html">Nice cars</a>: Stress test, loads 4 "large" images. Makes the chip panic and restart :( (static)</li>
|
||||
<li><a href="cars.html">Nice cars</a>: Stress test, loads several "large" images. Makes the chip panic and restart :( (static)</li>
|
||||
<li><a href="zipped.html">Zipped</a>: File is actually saved as zipped.html.gz. A compressed file! (static but gzipped)</li>
|
||||
<li><a href="zipped.html.gz">Zipped</a>: Same exact file as served above. Server is smart enough to treat the .gz extension correctly (static but gzipped)</li>
|
||||
<li><a href="args.lua">Arguments</a>: Parses arguments passed in the URL and prints them. (Lua)</li>
|
||||
|
||||
@ -1,33 +1,44 @@
|
||||
#!/usr/local/bin/lua
|
||||
-- httpserver-b64decode.lua
|
||||
-- Part of nodemcu-httpserver, contains b64 decoding used for HTTP Basic Authentication.
|
||||
-- Modified to use an exponentiation by multiplication method for only applicable for unsigned integers.
|
||||
-- Based on http://lua-users.org/wiki/BaseSixtyFour by Alex Kloss
|
||||
-- compatible with lua 5.1
|
||||
-- http://www.it-rfc.de
|
||||
-- Author: Marcos Kirsch
|
||||
|
||||
local function uipow(a, b)
|
||||
local ret = 1
|
||||
if b >= 0 then
|
||||
for i = 1, b do
|
||||
ret = ret * a
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
-- bitshift functions (<<, >> equivalent)
|
||||
-- shift left
|
||||
local function lsh(value,shift)
|
||||
return (value*(2^shift)) % 256
|
||||
return (value*(uipow(2, shift))) % 256
|
||||
end
|
||||
|
||||
-- shift right
|
||||
local function rsh(value,shift)
|
||||
-- Lua builds with no floating point don't define math.
|
||||
if math then return math.floor(value/2^shift) % 256 end
|
||||
return (value/2^shift) % 256
|
||||
if math then return math.floor(value/uipow(2, shift)) % 256 end
|
||||
return (value/uipow(2, shift)) % 256
|
||||
end
|
||||
|
||||
-- return single bit (for OR)
|
||||
local function bit(x,b)
|
||||
return (x % 2^b - x % 2^(b-1) > 0)
|
||||
return (x % uipow(2, b) - x % uipow(2, (b-1)) > 0)
|
||||
end
|
||||
|
||||
-- logic OR for number values
|
||||
local function lor(x,y)
|
||||
result = 0
|
||||
for p=1,8 do result = result + (((bit(x,p) or bit(y,p)) == true) and 2^(p-1) or 0) end
|
||||
for p=1,8 do result = result + (((bit(x,p) or bit(y,p)) == true) and uipow(2, (p-1)) or 0) end
|
||||
return result
|
||||
end
|
||||
|
||||
@ -62,4 +73,3 @@ return function(data)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
@ -4,6 +4,16 @@
|
||||
|
||||
basicAuth = {}
|
||||
|
||||
-- Returns true if the user/password match one of the users/passwords in httpserver-conf.lua.
|
||||
-- Returns false otherwise.
|
||||
function loginIsValid(user, pwd, users)
|
||||
if user == nil then return false end
|
||||
if pwd == nil then return false end
|
||||
if users[user] == nil then return false end
|
||||
if users[user] ~= pwd then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Parse basic auth http header.
|
||||
-- Returns the username if header contains valid credentials,
|
||||
-- nil otherwise.
|
||||
@ -15,12 +25,13 @@ function basicAuth.authenticate(header)
|
||||
end
|
||||
local credentials = dofile("httpserver-b64decode.lc")(credentials_enc)
|
||||
local user, pwd = credentials:match("^(.*):(.*)$")
|
||||
if user ~= conf.auth.user or pwd ~= conf.auth.password then
|
||||
if loginIsValid(user, pwd, conf.auth.users) then
|
||||
print("httpserver-basicauth: User \"" .. user .. "\": Authenticated.")
|
||||
return user
|
||||
else
|
||||
print("httpserver-basicauth: User \"" .. user .. "\": Access denied.")
|
||||
return nil
|
||||
end
|
||||
print("httpserver-basicauth: User \"" .. user .. "\": Authenticated.")
|
||||
return user
|
||||
end
|
||||
|
||||
function basicAuth.authErrorHeader()
|
||||
|
||||
@ -4,12 +4,14 @@
|
||||
|
||||
local conf = {}
|
||||
|
||||
-- Basic Authentication Conf
|
||||
-- Configure Basic HTTP Authentication.
|
||||
local auth = {}
|
||||
-- Set to true if you want to enable.
|
||||
auth.enabled = false
|
||||
auth.realm = "nodemcu-httpserver" -- displayed in the login dialog users get
|
||||
auth.user = "user"
|
||||
auth.password = "password" -- PLEASE change this
|
||||
conf.auth = auth
|
||||
-- Displayed in the login dialog users see before authenticating.
|
||||
auth.realm = "nodemcu-httpserver"
|
||||
-- Add users and passwords to this table. Do not leave this unchanged if you enable authentication!
|
||||
auth.users = {user1 = "password1", user2 = "password2", user3 = "password3"}
|
||||
|
||||
conf.auth = auth
|
||||
return conf
|
||||
|
||||
@ -1,67 +1,59 @@
|
||||
-- httpserver-connection
|
||||
-- Part of nodemcu-httpserver, provides a buffered connection object that can handle multiple
|
||||
-- consecutive send() calls, and buffers small payloads to send once they get big.
|
||||
-- For this to work, it must be used from a coroutine and owner is responsible for the final
|
||||
-- flush() and for closing the connection.
|
||||
-- Author: Philip Gladstone, Marcos Kirsch
|
||||
|
||||
BufferedConnection = {}
|
||||
|
||||
-- parameter is the nodemcu-firmware connection
|
||||
function BufferedConnection:new(connection)
|
||||
local newInstance = {}
|
||||
newInstance.connection = connection
|
||||
newInstance.size = 0
|
||||
newInstance.data = {}
|
||||
|
||||
function newInstance:flush()
|
||||
if self.size > 0 then
|
||||
self.connection:send(table.concat(self.data, ""))
|
||||
self.data = {}
|
||||
self.size = 0
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function newInstance:send(payload)
|
||||
local flushthreshold = 1400
|
||||
|
||||
local newsize = self.size + payload:len()
|
||||
while newsize > flushthreshold do
|
||||
--STEP1: cut out piece from payload to complete threshold bytes in table
|
||||
local piecesize = flushthreshold - self.size
|
||||
local piece = payload:sub(1, piecesize)
|
||||
payload = payload:sub(piecesize + 1, -1)
|
||||
--STEP2: insert piece into table
|
||||
table.insert(self.data, piece)
|
||||
self.size = self.size + piecesize --size should be same as flushthreshold
|
||||
--STEP3: flush entire table
|
||||
if self:flush() then
|
||||
coroutine.yield()
|
||||
end
|
||||
--at this point, size should be 0, because the table was just flushed
|
||||
newsize = self.size + payload:len()
|
||||
end
|
||||
|
||||
--at this point, whatever is left in payload should be <= flushthreshold
|
||||
local plen = payload:len()
|
||||
if plen == flushthreshold then
|
||||
--case 1: what is left in payload is exactly flushthreshold bytes (boundary case), so flush it
|
||||
table.insert(self.data, payload)
|
||||
self.size = self.size + plen
|
||||
if self:flush() then
|
||||
coroutine.yield()
|
||||
end
|
||||
elseif payload:len() then
|
||||
--case 2: what is left in payload is less than flushthreshold, so just leave it in the table
|
||||
table.insert(self.data, payload)
|
||||
self.size = self.size + plen
|
||||
--else, case 3: nothing left in payload, so do nothing
|
||||
end
|
||||
end
|
||||
|
||||
return newInstance
|
||||
end
|
||||
|
||||
return BufferedConnection
|
||||
-- httpserver-connection
|
||||
-- Part of nodemcu-httpserver, provides a buffered connection object that can handle multiple
|
||||
-- consecutive send() calls, and buffers small payloads to send once they get big.
|
||||
-- For this to work, it must be used from a coroutine and owner is responsible for the final
|
||||
-- flush() and for closing the connection.
|
||||
-- Author: Philip Gladstone, Marcos Kirsch
|
||||
|
||||
BufferedConnection = {}
|
||||
|
||||
-- parameter is the nodemcu-firmware connection
|
||||
function BufferedConnection:new(connection)
|
||||
local newInstance = {}
|
||||
newInstance.connection = connection
|
||||
newInstance.size = 0
|
||||
newInstance.data = {}
|
||||
|
||||
-- Returns true if there was any data to be sent.
|
||||
function newInstance:flush()
|
||||
if self.size > 0 then
|
||||
self.connection:send(table.concat(self.data, ""))
|
||||
self.data = {}
|
||||
self.size = 0
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function newInstance:send(payload)
|
||||
local flushThreshold = 1400
|
||||
local newSize = self.size + payload:len()
|
||||
while newSize >= flushThreshold do
|
||||
--STEP1: cut out piece from payload to complete threshold bytes in table
|
||||
local pieceSize = flushThreshold - self.size
|
||||
local piece = payload:sub(1, pieceSize)
|
||||
payload = payload:sub(pieceSize + 1, -1)
|
||||
--STEP2: insert piece into table
|
||||
table.insert(self.data, piece)
|
||||
piece = nil
|
||||
self.size = self.size + pieceSize --size should be same as flushThreshold
|
||||
--STEP3: flush entire table
|
||||
if self:flush() then
|
||||
coroutine.yield()
|
||||
end
|
||||
--at this point, size should be 0, because the table was just flushed
|
||||
newSize = self.size + payload:len()
|
||||
end
|
||||
|
||||
--at this point, whatever is left in payload should be < flushThreshold
|
||||
if payload:len() ~= 0 then
|
||||
--leave remaining data in the table
|
||||
table.insert(self.data, payload)
|
||||
self.size = self.size + payload:len()
|
||||
end
|
||||
end
|
||||
return newInstance
|
||||
|
||||
end
|
||||
|
||||
return BufferedConnection
|
||||
|
||||
@ -13,15 +13,16 @@ return function(connection, code, extension, isGzipped)
|
||||
|
||||
local function getMimeType(ext)
|
||||
-- A few MIME types. Keep list short. If you need something that is missing, let's add it.
|
||||
local mt = { css = "text/css", gif = "image/gif", html = "text/html", ico = "image/x-icon", jpeg = "image/jpeg", jpg = "image/jpeg", js = "application/javascript", json = "application/json", png = "image/png", xml = "text/xml" }
|
||||
local mt = {css = "text/css", gif = "image/gif", html = "text/html", ico = "image/x-icon", jpeg = "image/jpeg",
|
||||
jpg = "image/jpeg", js = "application/javascript", json = "application/json", png = "image/png", xml = "text/xml"}
|
||||
if mt[ext] then return mt[ext] else return "text/plain" end
|
||||
end
|
||||
|
||||
local mimeType = getMimeType(extension)
|
||||
|
||||
connection:send("HTTP/1.0 " .. code .. " " .. getHTTPStatusString(code) .. "\r\nServer: nodemcu-httpserver\r\nContent-Type: " .. mimeType .. "\r\nCache-Control: private, no-store\r\n")
|
||||
connection:send("HTTP/1.0 " .. code .. " " .. getHTTPStatusString(code) .. "\r\nServer: nodemcu-httpserver\r\nContent-Type: " .. mimeType .. "\r\n")
|
||||
if isGzipped then
|
||||
connection:send("Cache-Control: max-age=2592000\r\nContent-Encoding: gzip\r\n")
|
||||
connection:send("Cache-Control: private, max-age=2592000\r\nContent-Encoding: gzip\r\n")
|
||||
end
|
||||
connection:send("Connection: close\r\n\r\n")
|
||||
end
|
||||
|
||||
@ -3,32 +3,25 @@
|
||||
-- Author: Marcos Kirsch
|
||||
|
||||
return function (connection, req, args)
|
||||
--print("Begin sending:", args.file)
|
||||
--print("node.heap(): ", node.heap())
|
||||
dofile("httpserver-header.lc")(connection, 200, args.ext, args.isGzipped)
|
||||
-- Send file in little chunks
|
||||
local continue = true
|
||||
local size = file.list()[args.file]
|
||||
local bytesSent = 0
|
||||
local bytesRemaining = file.list()[args.file]
|
||||
-- Chunks larger than 1024 don't work.
|
||||
-- https://github.com/nodemcu/nodemcu-firmware/issues/1075
|
||||
local chunkSize = 1024
|
||||
while continue do
|
||||
collectgarbage()
|
||||
|
||||
-- NodeMCU file API lets you open 1 file at a time.
|
||||
-- So we need to open, seek, close each time in order
|
||||
-- to support multiple simultaneous clients.
|
||||
file.open(args.file)
|
||||
file.seek("set", bytesSent)
|
||||
local chunk = file.read(chunkSize)
|
||||
file.close()
|
||||
|
||||
local fileHandle = file.open(args.file)
|
||||
while bytesRemaining > 0 do
|
||||
local bytesToRead = 0
|
||||
if bytesRemaining > chunkSize then bytesToRead = chunkSize else bytesToRead = bytesRemaining end
|
||||
local chunk = fileHandle:read(bytesToRead)
|
||||
connection:send(chunk)
|
||||
bytesSent = bytesSent + #chunk
|
||||
bytesRemaining = bytesRemaining - #chunk
|
||||
--print(args.file .. ": Sent "..#chunk.. " bytes, " .. bytesRemaining .. " to go.")
|
||||
chunk = nil
|
||||
--print("Sent: " .. bytesSent .. " of " .. size)
|
||||
if bytesSent == size then continue = false end
|
||||
collectgarbage()
|
||||
end
|
||||
--print("Finished sending: ", args.file)
|
||||
print("Finished sending: ", args.file)
|
||||
fileHandle:close()
|
||||
fileHandle = nil
|
||||
collectgarbage()
|
||||
end
|
||||
|
||||
@ -155,11 +155,6 @@ return function (port)
|
||||
|
||||
end
|
||||
)
|
||||
-- false and nil evaluate as false
|
||||
local ip = wifi.sta.getip()
|
||||
if not ip then ip = wifi.ap.getip() end
|
||||
if not ip then ip = "unknown IP" end
|
||||
print("nodemcu-httpserver running at http://" .. ip .. ":" .. port)
|
||||
return s
|
||||
|
||||
end
|
||||
|
||||
72
init.lua
72
init.lua
@ -5,7 +5,7 @@ local wifiConfig = {}
|
||||
-- wifi.STATION -- station: join a WiFi network
|
||||
-- wifi.SOFTAP -- access point: create a WiFi network
|
||||
-- wifi.wifi.STATIONAP -- both station and access point
|
||||
wifiConfig.mode = wifi.STATIONAP -- both station and access point
|
||||
wifiConfig.mode = wifi.STATION
|
||||
|
||||
wifiConfig.accessPointConfig = {}
|
||||
wifiConfig.accessPointConfig.ssid = "ESP-"..node.chipid() -- Name of the SSID you want to create
|
||||
@ -23,7 +23,7 @@ wifiConfig.stationPointConfig.pwd = "" -- Password for the WiFi
|
||||
-- Tell the chip to connect to the access point
|
||||
|
||||
wifi.setmode(wifiConfig.mode)
|
||||
print('set (mode='..wifi.getmode()..')')
|
||||
--print('set (mode='..wifi.getmode()..')')
|
||||
|
||||
if (wifiConfig.mode == wifi.SOFTAP) or (wifiConfig.mode == wifi.STATIONAP) then
|
||||
print('AP MAC: ',wifi.ap.getmac())
|
||||
@ -44,7 +44,7 @@ collectgarbage()
|
||||
-- End WiFi configuration
|
||||
|
||||
-- Compile server code and remove original .lua files.
|
||||
-- This only happens the first time afer the .lua files are uploaded.
|
||||
-- This only happens the first time after server .lua files are uploaded.
|
||||
|
||||
local compileAndRemoveIfNeeded = function(f)
|
||||
if file.open(f) then
|
||||
@ -74,32 +74,48 @@ serverFiles = nil
|
||||
collectgarbage()
|
||||
|
||||
-- Connect to the WiFi access point.
|
||||
-- Once the device is connected, you may start the HTTP server.
|
||||
-- Once the device is connected, start the HTTP server.
|
||||
|
||||
startServer = function(ip, hostname)
|
||||
local serverPort = 80
|
||||
if (dofile("httpserver.lc")(serverPort)) then
|
||||
print("nodemcu-httpserver running at:")
|
||||
print(" http://" .. ip .. ":" .. serverPort)
|
||||
if (mdns) then
|
||||
mdns.register(hostname, { description="A tiny server", service="http", port=serverPort, location='Earth' })
|
||||
print (' http://' .. hostname .. '.local.:' .. serverPort)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (wifi.getmode() == wifi.STATION) or (wifi.getmode() == wifi.STATIONAP) then
|
||||
local joinCounter = 0
|
||||
local joinMaxAttempts = 5
|
||||
tmr.alarm(0, 3000, 1, function()
|
||||
local ip = wifi.sta.getip()
|
||||
if ip == nil and joinCounter < joinMaxAttempts then
|
||||
print('Connecting to WiFi Access Point ...')
|
||||
joinCounter = joinCounter +1
|
||||
else
|
||||
if joinCounter == joinMaxAttempts then
|
||||
print('Failed to connect to WiFi Access Point.')
|
||||
else
|
||||
print('IP: ',ip)
|
||||
end
|
||||
tmr.stop(0)
|
||||
joinCounter = nil
|
||||
joinMaxAttempts = nil
|
||||
collectgarbage()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Uncomment to automatically start the server in port 80
|
||||
if (not not wifi.sta.getip()) or (not not wifi.ap.getip()) then
|
||||
--dofile("httpserver.lc")(80)
|
||||
local joinCounter = 0
|
||||
local joinMaxAttempts = 5
|
||||
tmr.alarm(0, 3000, 1, function()
|
||||
local ip = wifi.sta.getip()
|
||||
if (not ip) then ip = wifi.ap.getip() end
|
||||
if ip == nil and joinCounter < joinMaxAttempts then
|
||||
print('Connecting to WiFi Access Point ...')
|
||||
joinCounter = joinCounter + 1
|
||||
else
|
||||
if joinCounter == joinMaxAttempts then
|
||||
print('Failed to connect to WiFi Access Point.')
|
||||
else
|
||||
print("IP = " .. ip)
|
||||
if (not not wifi.sta.getip()) or (not not wifi.ap.getip()) then
|
||||
-- Second parameter is for mDNS (aka Zeroconf aka Bonjour) registration.
|
||||
-- If the mdns module is compiled in the firmware, advertise the server with this name.
|
||||
-- If no mdns is compiled, then parameter is ignored.
|
||||
startServer(ip, "nodemcu")
|
||||
end
|
||||
end
|
||||
tmr.stop(0)
|
||||
joinCounter = nil
|
||||
joinMaxAttempts = nil
|
||||
collectgarbage()
|
||||
end
|
||||
end)
|
||||
else
|
||||
startServer()
|
||||
end
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user