从无到有玩NodeMcu:web端控制

从无到有玩NodeMcu:web端控制

我们的目标:

利用网页web端为搭载NodeMcu的esp8266连接wifi

硬件准备:

  • 基于NodeMcu的esp8266
  • 数据线:usb+micr-usb
  • 安装有Windows系统的电脑

软件准备:

  • java运行环境:自行安装,注意,需要下载jdk8,太高的版本会使软件闪退
  • nodemcu-flasher:esp8266固件烧录程序
  • ESPIorer:为NodeMcu设计的编辑、上传软件
  • CH340驱动:用来连接电脑和esp8266 验证码ja94
  • NodeMcu固件:NodeMcu团队为esp8266制作的固件 验证码u5zv

如何下载Github上的源码

我们以nodemcu-flasher的下载为例

进入GitHub相关界面

点击nodemcu-flasher进入nodemcu-flasher的项目主页,只下载的话是不用注册的:

从无到有玩NodeMcu:web端控制_第1张图片

点击项目有时间的clone or download按键后会弹出一个小框,选择小框里的download zip即可下载源代码,下载完毕后解压缩即可

从无到有玩NodeMcu:web端控制_第2张图片

如何安装CH340驱动

下载百度云内的文件,得到一个叫Setup 32.64位元.exe的程序,执行它安装驱动。安装成功后使用数据线连接esp8266,打开设备管理器,如果显示下面的情况,则说明驱动已经安装完成:

从无到有玩NodeMcu:web端控制_第3张图片

如果没有显示,则有可能是数据线的问题,换一根数据线。如果显示modify、repair、remove的话,说明你以前已经安装过这个驱动了,如果你的设备管理器没有正常的话,就需要remove把以前的程序删除再重新安装

固件烧录

下载NodeMcu固件,得到nodemcu-master-11-modules-2019-07-22-07-39-27-float.bin这个文件,然后我们打开NodeMcu-flash,连接esp8266到电脑:

我们选择config,再在下面绿色的框里填写NodeMcu固件的本地文件地址,也就是你放固件的地方
从无到有玩NodeMcu:web端控制_第4张图片

我们回到Operation(正常情况下COM Port后面的Select port是有值的,我这边为了操作方便没有连接电脑),点击Flash按钮,固件就会被烧录到esp8266中了。
从无到有玩NodeMcu:web端控制_第5张图片

源代码准备

源代码分为三类:

  • 控制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.htmlinit.luaHttpServe.lua这两个文件传到esp8266上

打开ESPLore

我们运行ESPIorer.jar这个程序来运行这个软件,我们可以看到它的主界面:

从无到有玩NodeMcu:web端控制_第6张图片

连接硬件

我们通过数据线把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出现以下画面:

从无到有玩NodeMcu:web端控制_第7张图片

参考

  • NodeMCU-Tutorial
  • Nodemcu通过网页Web设置sta.config配置
  • win10如何安装CH340驱动? - 知乎
  • NodeMCU使用说明整理

你可能感兴趣的:(硬件,nodemcu)