准備工作
1.NodeMCU模塊
2.ESPlorer v0.2.0-rc6
3.NodeMCU-HTTP-Server
搭建web服務器
下載https://github.com/wangzexi/NodeMCU-HTTP-Server文件,並上傳到NodeMCU中
修改init.lua文件,可參看NodeMCU-HTTP-Server Example

-- init.lua --------------------- -- wifi --------------------- print('Setting up WIFI...') wifi.setmode(wifi.STATION) wifi.sta.config('WX401901', 'smyh1234') wifi.sta.autoconnect(1) tmr.alarm(1, 1000, tmr.ALARM_AUTO, function() if wifi.sta.getip() == nil then print('Waiting for IP ...') else print('IP is ' .. wifi.sta.getip()) tmr.stop(1) end end) -- Serving static files dofile('httpServer.lua') httpServer:listen(80) -- Custom API -- Get text/html httpServer:use('/welcome', function(req, res) res:send('Hello ' .. req.query.name) -- /welcome?name=doge end) -- Get file httpServer:use('/doge', function(req, res) res:sendFile('doge.jpg') end) -- Get json httpServer:use('/json', function(req, res) res:type('application/json') res:send('{"doge": "smile"}') end) -- Redirect httpServer:use('/redirect', function(req, res) res:redirect('doge.jpg') end)
現在是工作在STATION模式下,保存后可以看到獲取的IP地址,在瀏覽器中輸入http://192.168.100.100就可以看到一個簡單的頁面了。
修改成 wifi.setmode(wifi.STATIONAP) 模式,出現了內存不足的錯誤,無視它。
E:M 248
not enough memory
stack traceback:
[C]: in function 'dofile'
init.lua:22: in main chunk
[C]: in function 'dofile'
stdin:1: in main chunk
現在NodeMCU有兩個IP,一個是作為STATION的192.168.100.100,另外一個是作為AP的192.168.4.1,這時在無線列表中會多出一個AI-THINKER_AC72F4,用手機或電腦連上后瀏覽器中輸入http://192.168.4.1 也可以看到頁面。
實現Web配置無線連接賬號和密碼
這里借用NodeMCU之旅(四):實現Web配置頁面的配置頁面。
首先,刪除上一步中上傳的測試文件 404.html和doge.jpg
然后,上傳新的配置頁面
最后,修改init.lua文件去掉演示web相關的路由配置添加兩個新的路由:
httpServer:use('/config', function(req, res) if req.query.ssid ~= nil and req.query.pwd ~= nil then wifi.sta.config(req.query.ssid, req.query.pwd) status = 'STA_CONNECTING' status_sleep=0 tmr.alarm(TMR_WIFI, 1000, tmr.ALARM_AUTO, function() status_sleep=status_sleep+1 --當設置的賬號密碼錯誤時,定時器不會停止,所以這里添加了超時檢查 if(status_sleep==10) then res:type('application/json') res:send('{"status":"timeout"}') tmr.stop(TMR_WIFI) end if status ~= 'STA_CONNECTING' then res:type('application/json') res:send('{"status":"' .. status .. '"}') tmr.stop(TMR_WIFI) end end) end end) -- Get json httpServer:use('/scanap', function(req, res) wifi.sta.getap(function(table) local aptable = {} for ssid,v in pairs(table) do local authmode, rssi, bssid, channel = string.match(v, "([^,]+),([^,]+),([^,]+),([^,]+)") aptable[ssid] = { authmode = authmode, rssi = rssi, bssid = bssid, channel = channel } end res:type('application/json')
--原來是cjson.encode(aptable),因為構建固件時沒有找到cjson用了sjson,所以這里改成sjson res:send(sjson.encode(aptable)) end) end)
當請求的方法里出現異常時前端看到的是404錯誤,這個坑讓我一直懷疑是httpServer.lua的問題
保存后,訪問http://192.168.100.100,修改成一個錯誤的密碼,點擊連接網絡,Led燈開始閃爍然后模塊重啟常亮,表示修改失敗。
* Sending index.html
* Finished index.html
PANIC: unprotected error in call to Lua API (httpServer.lua:77: not connected)
還得切換Wifi到AI-THINKER_AC72F4,通過http://192.168.4.1修改賬號密碼。

-- init.lua ---------------------- --define --------------------- IO_BLINK = 4 TMR_WIFI = 4 TMR_BLINK = 5 TMR_BTN = 6 gpio.mode(IO_BLINK, gpio.OUTPUT) --------------------- -- blink --------------------- blink = nil tmr.register(TMR_BLINK, 100, tmr.ALARM_AUTO, function() gpio.write(IO_BLINK, blink.i % 2) tmr.interval(TMR_BLINK, blink[blink.i + 1]) blink.i = (blink.i + 1) % #blink end) function blinking(param) if type(param) == 'table' then blink = param blink.i = 0 tmr.interval(TMR_BLINK, 1) running, _ = tmr.state(TMR_BLINK) if running ~= true then tmr.start(TMR_BLINK) end else tmr.stop(TMR_BLINK) gpio.write(IO_BLINK, param or gpio.LOW) end end --------------------- -- wifi --------------------- print('Setting up WIFI...') wifi.setmode(wifi.STATIONAP ) wifi.sta.config('WX401901', 'smyh1234') wifi.sta.autoconnect(1) tmr.alarm(1, 1000, tmr.ALARM_AUTO, function() if wifi.sta.getip() == nil then print('Waiting for IP ...') else print('IP is ' .. wifi.sta.getip()) tmr.stop(1) end end) status=nil wifi.sta.eventMonReg(wifi.STA_WRONGPWD, function() blinking({100, 100 , 100, 500}) status = 'STA_WRONGPWD' print(status) end) wifi.sta.eventMonReg(wifi.STA_APNOTFOUND, function() blinking({2000, 2000}) status = 'STA_APNOTFOUND' print(status) end) wifi.sta.eventMonReg(wifi.STA_CONNECTING, function(previous_State) blinking({300, 300}) status = 'STA_CONNECTING' print(status) end) wifi.sta.eventMonReg(wifi.STA_GOTIP, function() blinking() status = 'STA_GOTIP' print(status, wifi.sta.getip()) end) wifi.sta.eventMonStart(1000) --------------------- -- http --------------------- dofile('httpServer.lua') httpServer:listen(80) httpServer:use('/config', function(req, res) if req.query.ssid ~= nil and req.query.pwd ~= nil then wifi.sta.config(req.query.ssid, req.query.pwd) status = 'STA_CONNECTING' status_sleep=0 tmr.alarm(TMR_WIFI, 1000, tmr.ALARM_AUTO, function() status_sleep=status_sleep+1 if(status_sleep==10) then res:type('application/json') res:send('{"status":"timeout"}') tmr.stop(TMR_WIFI) end if status ~= 'STA_CONNECTING' then res:type('application/json') res:send('{"status":"' .. status .. '"}') tmr.stop(TMR_WIFI) end end) end end) -- Get json httpServer:use('/scanap', function(req, res) wifi.sta.getap(function(table) local aptable = {} for ssid,v in pairs(table) do local authmode, rssi, bssid, channel = string.match(v, "([^,]+),([^,]+),([^,]+),([^,]+)") aptable[ssid] = { authmode = authmode, rssi = rssi, bssid = bssid, channel = channel } end res:type('application/json') res:send(sjson.encode(aptable)) end) end)
相關資源
本文是在NodeMCU之旅(三):響應配置按鈕、NodeMCU之旅(四):實現Web配置頁面 基礎之上的學習過程,感謝原作者。