我们的目标:
利用网页web端为搭载NodeMcu的esp8266连接wifi
ja94
u5zv
我们以nodemcu-flasher的下载为例
点击nodemcu-flasher进入nodemcu-flasher
的项目主页,只下载的话是不用注册的:
点击项目有时间的clone or download
按键后会弹出一个小框,选择小框里的download zip
即可下载源代码,下载完毕后解压缩即可
下载百度云内的文件,得到一个叫Setup 32.64位元.exe
的程序,执行它安装驱动。安装成功后使用数据线连接esp8266,打开设备管理器,如果显示下面的情况,则说明驱动已经安装完成:
如果没有显示,则有可能是数据线的问题,换一根数据线。如果显示modify、repair、remove的话,说明你以前已经安装过这个驱动了,如果你的设备管理器没有正常的话,就需要remove把以前的程序删除再重新安装
下载NodeMcu固件,得到nodemcu-master-11-modules-2019-07-22-07-39-27-float.bin
这个文件,然后我们打开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",
--设置IP
netmask="255.255.255.0",
--子网掩码
gateway="192.168.1.1"
--默认网关
}
wifi.ap.setip(cfg2)
wifi.sta.autoconnect(1)
--自动连接
dofile('httpServer.lua')
--执行HttpServer.lua
httpServer:use('/config', function(req, res)
if req.query.ssid ~= nil and req.query.pwd ~= nil then
print(req.query.ssid ..req.query.pwd)
config={}
config.ssid=req.query.ssid
config.pwd=req.query.pwd
wifi.sta.config(config)
end
res:send('配置终端 您设置的wifi是:'..req.query.ssid..',请等待红灯常亮即连接完成。
')
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)
end
function 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) do
if string.sub(filename, -string.len(ext)) == ext
or string.sub(filename, -string.len(ext .. '.gz')) == ext .. '.gz' then
return type
end
end
return 'text/plain'
end
--------------------
-- Response
--------------------
Res = {
_skt = nil,
_type = nil,
_status = nil,
_redirectUrl = nil,
}
function Res:new(skt)
local o = {}
setmetatable(o, self)
self.__index = self
o._skt = skt
return o
end
function Res:redirect(url, status)
status = status or 302
self:status(status)
self._redirectUrl = url
self:send(status)
end
function Res:type(type)
self._type = type
end
function Res:status(status)
self._status = status
end
function Res:send(body)
self._status = self._status or 200
self._type = self._type or 'text/html'
local buf = 'HTTP/1.1 ' .. self._status .. '\r\n'
.. 'Content-Type: ' .. self._type .. '\r\n'
.. 'Content-Length:' .. string.len(body) .. '\r\n'
if self._redirectUrl ~= nil then
buf = buf .. 'Location: ' .. self._redirectUrl .. '\r\n'
end
buf = buf .. '\r\n' .. body
local function doSend()
if buf == '' then
self:close()
else
self._skt:send(string.sub(buf, 1, 512))
buf = string.sub(buf, 513)
end
end
self._skt:on('sent', doSend)
doSend()
end
function Res:sendFile(filename)
if file.exists(filename .. '.gz') then
filename = filename .. '.gz'
elseif not file.exists(filename) then
self:status(404)
if filename == '404.html' then
self:send(404)
else
self:sendFile('404.html')
end
return
end
self._status = self._status or 200
local header = 'HTTP/1.1 ' .. self._status .. '\r\n'
self._type = self._type or guessType(filename)
header = header .. 'Content-Type: ' .. self._type .. '\r\n'
if string.sub(filename, -3) == '.gz' then
header = header .. 'Content-Encoding: gzip\r\n'
end
header = header .. '\r\n'
print('* Sending ', filename)
local pos = 0
local function doSend()
file.open(filename, 'r')
if file.seek('set', pos) == nil then
self:close()
print('* Finished ', filename)
else
local buf = file.read(512)
pos = pos + 512
self._skt:send(buf)
end
file.close()
end
self._skt:on('sent', doSend)
self._skt:send(header)
end
function Res:close()
self._skt:on('sent', function() end) -- release closures context
self._skt:on('receive', function() end)
self._skt:close()
self._skt = nil
end
--------------------
-- 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')
end
local _GET = {}
if vars ~= nil then
vars = urlDecode(vars)
for k, v in string.gmatch(vars, '([^&]+)=([^&]*)&*') do
_GET[k] = v
end
end
req.method = method
req.query = _GET
req.path = path
return true
end
function staticFile(req, res)
local filename = ''
if req.path == '/' then
filename = 'index.html'
else
filename = string.gsub(string.sub(req.path, 2), '/', '_')
end
res: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
})
end
function httpServer:close()
self._srv:close()
self._srv = nil
end
function 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 do
if string.find(req.path, '^' .. self._mids[i].url .. '$')
and not self._mids[i].cb(req, res) then
break
end
end
collectgarbage()
end)
end)
end
index.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>WiFilabel>
<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上
我们运行ESPIorer.jar
这个程序来运行这个软件,我们可以看到它的主界面:
我们通过数据线把esp8266和电脑连接起来
open
右侧的波特率是否为115200
,如果不是的话请调整open
来打开串口,会出现Communication with MCU..
,此时马上按硬件上靠近数据线的rst
键upload
键,选择上传所有之前创立的三个文件Reload
按键,右键点击init.lua
按键,点击Run init.lua
手机连接esp8266产生的WiFi,名字是config
密码是00000000
,连接它
使用浏览器进入http://192.168.1.1
出现以下画面: