本文所有软件资源均可点击相应的超链接下载
我们的目标:利用网页web端为搭载NodeMcu的esp8266连接wifi
硬件准备:
基于NodeMcu的esp8266数据线:usb+micr-usb安装有Windows系统的电脑软件准备:
java运行环境:自行安装,注意,需要下载jdk8,太高的版本会使软件闪退nodemcu-flasher:esp8266固件烧录程序ESPlorer:为NodeMcu设计的编辑、上传软件CH340驱动:用来连接电脑和esp8266 验证码ja94
NodeMcu固件:NodeMcu团队为esp8266制作的固件 验证码u5zv
如何下载Github上的源码
我们以nodemcu-flasher的下载为例
进入GitHub相关界面
点击nodemcu-flasher进入nodemcu-flasher
的项目主页,只下载的话是不用注册的:
点击项目有时间的clone or download
按键后会弹出一个小框,选择小框里的download zip
即可下载源代码,下载完毕后解压缩即可
如何安装CH340驱动
下载百度云内的文件,得到一个叫Setup 32.64位元.exe
的程序,执行它安装驱动。安装成功后使用数据线连接esp8266,打开设备管理器,如果显示下面的情况,则说明驱动已经安装完成:
如果没有显示,则有可能是数据线的问题,换一根数据线。如果显示modify、repair、remove的话,说明你以前已经安装过这个驱动了,如果你的设备管理器没有正常的话,就需要remove把以前的程序删除再重新安装
固件烧录
下载NodeMcu固件,得到nodemcu-master-11-modules--07-22-07-39-27-float.bin
这个文件,打开Win64Release,然后我们打开NodeMcu-flash,连接esp8266到电脑:
我们选择config,再在下面绿色的框里填写NodeMcu固件的本地文件地址,也就是你放固件的地方
我们回到Operation(正常情况下COM Port后面的Select port是有值的,我这边为了操作方便没有连接电脑),点击Flash按钮,固件就会被烧录到esp8266中了。
源代码准备
源代码分为三类:控制esp8266的lua程序控制网页的html程序负责沟通esp8266和网页的http服务器程序
我们需要按以下步骤获得init.lua
index.html
HttpServe.lua
三个文件,并把它们放在一个文件夹
新建一个.txt
文件复制代码重命名文件为相应的名字
它们的源程序如下:
init.lua
wifi.setmode(wifi.STATIONAP)cfg={}cfg.ssid="config" --我们的NodeMcu热点cfg.pwd="00000000"--密码wifi.ap.config(cfg)cfg2 ={ip="192.168.1.1",--设置IPnetmask="255.255.255.0",--子网掩码gateway="192.168.1.1"--默认网关}wifi.ap.setip(cfg2)wifi.sta.autoconnect(1)--自动连接dofile('httpServer.lua')--执行HttpServer.luahttpServer:use('/config', function(req, res)if req.query.ssid ~= nil and req.query.pwd ~= nil thenprint(req.query.ssid ..req.query.pwd)config={}config.ssid=req.query.ssidconfig.pwd=req.query.pwdwifi.sta.config(config)endres:send('<head><meta charset="UTF-8"><title>配置终端</title></head><h1>您设置的wifi是:'..req.query.ssid..',请等待红灯常亮即连接完成。</h1>')end)httpServer:listen(80) --启动Server
httpServer.lua
---------------------- helper--------------------function urlDecode(url)return url:gsub('%%(%x%x)', function(x)return string.char(tonumber(x, 16))end)endfunction guessType(filename)local types = {['.css'] = 'text/css', ['.js'] = 'application/javascript', ['.html'] = 'text/html',['.png'] = 'image/png',['.jpg'] = 'image/jpeg'}for ext, type in pairs(types) doif string.sub(filename, -string.len(ext)) == extor string.sub(filename, -string.len(ext .. '.gz')) == ext .. '.gz' thenreturn typeendendreturn 'text/plain'end---------------------- Response--------------------Res = {_skt = nil,_type = nil,_status = nil,_redirectUrl = nil,}function Res:new(skt)local o = {}setmetatable(o, self)self.__index = selfo._skt = sktreturn oendfunction Res:redirect(url, status)status = status or 302self:status(status)self._redirectUrl = urlself:send(status)endfunction Res:type(type)self._type = typeendfunction Res:status(status)self._status = statusendfunction Res:send(body)self._status = self._status or 200self._type = self._type or 'text/html'local buf = 'HTTP/1.1 ' .. self._status .. 'rn'.. 'Content-Type: ' .. self._type .. 'rn'.. 'Content-Length:' .. string.len(body) .. 'rn'if self._redirectUrl ~= nil thenbuf = buf .. 'Location: ' .. self._redirectUrl .. 'rn'endbuf = buf .. 'rn' .. bodylocal function doSend()if buf == '' then self:close()elseself._skt:send(string.sub(buf, 1, 512))buf = string.sub(buf, 513)endendself._skt:on('sent', doSend)doSend()endfunction Res:sendFile(filename)if file.exists(filename .. '.gz') thenfilename = filename .. '.gz'elseif not file.exists(filename) thenself:status(404)if filename == '404.html' thenself:send(404)elseself:sendFile('404.html')endreturnendself._status = self._status or 200local header = 'HTTP/1.1 ' .. self._status .. 'rn'self._type = self._type or guessType(filename)header = header .. 'Content-Type: ' .. self._type .. 'rn'if string.sub(filename, -3) == '.gz' thenheader = header .. 'Content-Encoding: gziprn'endheader = header .. 'rn'print('* Sending ', filename)local pos = 0local function doSend()file.open(filename, 'r')if file.seek('set', pos) == nil thenself:close()print('* Finished ', filename)elselocal buf = file.read(512)pos = pos + 512self._skt:send(buf)endfile.close()endself._skt:on('sent', doSend)self._skt:send(header)endfunction Res:close()self._skt:on('sent', function() end) -- release closures contextself._skt:on('receive', function() end)self._skt:close()self._skt = nilend---------------------- Middleware--------------------function parseHeader(req, res)local _, _, method, path, vars = string.find(req.source, '([A-Z]+) (.+)?(.+) HTTP')if method == nil then_, _, method, path = string.find(req.source, '([A-Z]+) (.+) HTTP')endlocal _GET = {}if vars ~= nil thenvars = urlDecode(vars)for k, v in string.gmatch(vars, '([^&]+)=([^&]*)&*') do_GET[k] = vendendreq.method = methodreq.query = _GETreq.path = pathreturn trueendfunction staticFile(req, res)local filename = ''if req.path == '/' thenfilename = 'index.html'elsefilename = string.gsub(string.sub(req.path, 2), '/', '_')endres:sendFile(filename)end---------------------- HttpServer--------------------httpServer = {_srv = nil,_mids = {{url = '.*',cb = parseHeader}, {url = '.*',cb = staticFile}}}function httpServer:use(url, cb)table.insert(self._mids, #self._mids, {url = url,cb = cb})endfunction httpServer:close()self._srv:close()self._srv = nilendfunction httpServer:listen(port)self._srv = net.createServer(net.TCP)self._srv:listen(port, function(conn)conn:on('receive', function(skt, msg) local req = {source = msg, path = '', ip = skt:getpeer() }local res = Res:new(skt)for i = 1, #self._mids doif string.find(req.path, '^' .. self._mids[i].url .. '$')and not self._mids[i].cb(req, res) thenbreakendendcollectgarbage()end)end)end
index.html
<!DOCTYPE html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>配置终端</title></head><body style="text-align:center;background:#f8fffbb2;"><h1>配置页面</h1><form action="/config" method="get"><label>WiFi</label><input type="text" name="ssid" /><br /><label>密码</label><input type="password" name="pwd" /><br /><input type="submit" value="确认" style="background:#678df9;height:40px;width:60px;border-radius:5px;border:none;outline:none;"/></form><p style="max-width:50vw;margin:auto;">注意:由于NodeMCU内存很小,附近热点过多时,扫描热点会造成内存不足自动重启。请手动输入WIFI信息进行配置。</p></body><style>input{margin-bottom:30px;}</style></html>
硬件操作
上传服务器文件
我们把esp8266当作一个小型的服务器,我们需要把index.html
、init.lua
和HttpServe.lua
这两个文件传到esp8266上
打开ESPlorer
我们运行ESPlorer.jar
这个程序来运行这个软件,我们可以看到它的主界面:
连接硬件
我们通过数据线把esp8266和电脑连接起来
上传程序
再确定命令执行框上方open
右侧的波特率是否为115200
,如果不是的话请调整在点击右边命令执行框上方的open
来打开串口,会出现Communication with MCU..
,此时马上按硬件上靠近数据线的rst
键看见屏幕出现一些NodeMcu的信息即可点击源代码编辑框的upload
键,选择上传所有之前创立的三个文件点击右边的Reload
按键,右键点击init.lua
按键,点击Run init.lua
手机操作
手机连接esp8266产生的WiFi,名字是config
密码是00000000
,连接它
使用浏览器进入http://192.168.1.1
出现以下画面: