ESP-01S实现本地网页AP配网
一、前言
借由之前做过的STM32机器人项目,我们可以用相同的方式实现本地AP配网,只不过这一次我们使用的是ESP-01S模块。相较于之前使用的ESP32-CAM,ESP-01S的资源明显要小的多得多的多。虽然小多少我不知道,懒得搜,但是至少我们可以知道ESP-01S模块板载的Flash大小一般分为512k和1M大小的,01S一般是1M大小。所以思路就很清晰了,理论上只要想办法让Microdot在极小资源的ESP-01S上跑起来就能实现相同的效果了。
二、实践过程
好在MicroPython固件是可以直接到官方网站下载的,所以第一步我们可以直接到官网下载固件。
根据自己的实际情况下载对应的固件,我下载使用的是1MB版本的固件。下载完成后将固件烧录到模块当中,我使用的是Mu Editor自带的固件下载功能,实际上也是使用esptool.py下载,只不过Mu Editor自带的有GUI界面下载比较方便。关于固件烧录的细节网上有详细教程,这里不做过多赘述。
固件烧录完成之后就可以准备开发了,我使用的开发工具是Arduino Lab for MicroPython。
Arduino Lab for MicroPython下载地址
电脑最好再准备一个串口助手以方便调试。
三、开发过程
可以直接从我原来的STM32机器人项目拉取原来在ESP32-CAM的代码,接下来就准备将文件上传至模块当中。
但是且慢!由于ESP-01S模块那点小的可怜的内存,因此我们需要下载下来的.py文件进行预编译成.mpy文件以节省模块的内存开销,至于如何预编译以及预编译的原因,可以查看MicroPython的官方文档。
MicroPython官方提供了专门的工具为我们首先预编译,因此我们需要先去拉取MicroPython的Github官方代码仓库,其中readme文档中也有提到关于预编译工具,关于预编译的过程我选择在Ubuntu环境下进行。
将代码拉取到本地后,cd到mpy-cross目录中,在终端中使用make命令编译mpy-cross工具。
编译完成后,cd到build目录当中,将准备预编译成.mpy的.py文件置于文件夹当中,这里我选择的是用户Download文件夹。
接下来我们需要准备预编译的.py文件,如果只需要AP配网的功能,则仅需要以下文件:
/
├─ main.html
├─ main.py
├─ success_page.html
├─ wifi_info.html
└─ lib
├─ microdot.py
└─ uasyncio
├─ core.py
├─ stream.py
└─ __init__.py
由于ESP-01S资源紧张,原来的Microdot直接上传是无法运行的,终端会提示MemoryError,因此在预编译之前,需要对microdot.py文件进行修改。通过AI的帮助,将源码中的默认缓冲区大小进行调整,修改后的函数如下,将源文件中的对应函数直接替换即可:
def body_iter(self):
if hasattr(self.body, '__anext__'):
# 如果是异步生成器,直接返回
return self.body
response = self
class iter:
ITER_UNKNOWN = 0
ITER_FILE_OBJ = 2
ITER_NO_BODY = -1
def __aiter__(self):
if response.body:
self.i = self.ITER_UNKNOWN
else:
self.i = self.ITER_NO_BODY
return self
async def __anext__(self):
if self.i == self.ITER_NO_BODY:
await self.aclose()
raise StopAsyncIteration
if self.i == self.ITER_UNKNOWN:
if hasattr(response.body, 'read'):
self.i = self.ITER_FILE_OBJ
else:
# 如果是字符串或字节串,返回一次就结束
self.i = self.ITER_NO_BODY
result = response.body
await self.aclose()
raise StopAsyncIteration(result)
if self.i == self.ITER_FILE_OBJ:
# 自适应缓冲区大小
size = getattr(response, 'send_file_buffer_size', 128)
size = min(size, 256) # 限制最大值
while size >= 32:
try:
buf = response.body.read(size)
if iscoroutine(buf):
buf = await buf
if not buf:
self.i = self.ITER_NO_BODY
await self.aclose()
raise StopAsyncIteration
return buf
except MemoryError:
print("MemoryError: reducing buffer size to", size // 2)
size = size // 2
print("MemoryError: all buffer sizes failed")
self.i = self.ITER_NO_BODY
await self.aclose()
raise StopAsyncIteration
async def aclose(self):
if hasattr(response.body, 'close'):
result = response.body.close()
if iscoroutine(result):
await result
return iter()
同时将源码中开头的import asyncio修改成import uasyncio,以便于使用准备好的MicroPython uasyncio库。
其中uasyncio文件夹内的文件也来自MicroPython的Github官方代码仓库,在/extmod/asyncio目录下。
修改main.py文件,将原来负责发送命令以及传输图像的代码删除,保留AP配网的部分:
from lib.microdot import Microdot, send_file, redirect
import network
import time
app = Microdot()
@app.route('/')
def main(request):
return send_file('main.html')
@app.route('/wifi_info')
def wifi_info(request):
return send_file('wifi_info.html')
@app.get('/connect_wifi')
def success_page(request):
WIFI_Connect()
# get wifi info
@app.post('/success_page')
def handle_form_submission(request):
global ssid
global password
form_data = request.form
ssid = form_data.get('ssid')
password = form_data.get('password')
print(ssid, password)
# return redirect('/success_page')
return send_file('success_page.html')
def AP_Connect():
print("ap_mode")
global AP_State
AP_State = network.WLAN(network.AP_IF)
AP_State.active(True)
# AP_State.config(essid = 'Robots Config AP', authmode=network.AUTH_WPA_WPA2_PSK, password = '12345678')
AP_State.config(essid = 'Robots Config AP')
while AP_State.isconnected() != True:
time.sleep(1)
print("device_no_connect")
print("have_device_connected")
time.sleep(1)
def WIFI_Connect():
# AP_State.active(False)
# 连接wifi
sta_if = network.WLAN(network.STA_IF)
if not sta_if.isconnected():
print('connecting to network...')
sta_if.active(True)
sta_if.connect(ssid, password)
# sta_if.connect("RM2100_2.4G", "21802366")
while not sta_if.isconnected():
pass
print("connect!")
if __name__ == '__main__':
AP_Connect()
app.run(port=80)
至此文件修改完成。
预编译的示例命令如下,该命令只针对单个.py文件,依次对需要预编译的文件都执行一遍:
./mpy-cross ~/Downloads/microdot.py
将预编译完成的文件按照上文提到的文件路径一一上传至ESP-01S当中,使用方式和ESP32-CAM相同:
- 1、连接AP热点
- 2、浏览器访问192.168.4.1
- 3、输入wifi名称和密码
- 4、点击提交并确认连接
至此完成整个本地网页AP配网流程。