4、连接WiFi网络实战:编写第一个连接函数、处理连接超时、获取IP地址
好,咱们正式开始写代码了。
前面几章我们把WiFi的工作模式、状态机、事件驱动这些概念捋了一遍。说实话,光看理论容易犯困。我当年刚学ESP32的时候,也是看了三天文档,结果一上电连不上路由器,心态直接崩了。
所以这一章,咱们直接动手。目标很明确:写一个能用的WiFi连接函数。它要能连上指定的路由器,能处理连不上的情况(超时),最后还能拿到IP地址。
4.1 第一个连接函数:从阻塞到非阻塞
很多人写WiFi连接,第一版代码长这样:
# 初学者写法 —— 千万别这么用
import network
import time
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("MyWiFi", "password123")
while not wlan.isconnected():
time.sleep(0.5)
print("正在连接...")
print("连接成功!")
这段代码能跑吗?能。但问题很大——它把整个程序卡死了。
你想想看,如果WiFi信号弱,或者密码输错了,这个while循环会一直卡在那里。你的传感器读不了,LED闪不了,按键也响应不了。整个设备就像死机了一样。
我在项目里见过有人用这种写法做产品原型,结果测试的时候路由器一重启,设备就再也连不回来了——因为循环卡死,连看门狗都喂不了。
4.2 非阻塞连接:用超时机制替代死循环
正确的做法是什么?设定一个超时时间。到了时间连不上,就返回失败,让主循环继续跑。
import network
import time
def connect_wifi(ssid, password, timeout=10):
"""
连接WiFi网络,带超时控制
:param ssid: 路由器名称
:param password: 密码
:param timeout: 超时秒数,默认10秒
:return: True 连接成功,False 连接失败
"""
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if wlan.isconnected():
print("已经连接,跳过")
return True
wlan.connect(ssid, password)
start_time = time.time()
while not wlan.isconnected():
# 检查是否超时
if time.time() - start_time > timeout:
print(f"连接超时({timeout}秒),请检查SSID/密码")
return False
time.sleep(0.5)
print(".", end="")
print("\n连接成功!")
return True
这个函数的核心逻辑很简单:
- 先检查是否已经连接,避免重复操作
- 发起连接后,进入循环等待
- 每次循环检查是否超时
- 超时了就返回
False,不卡死
嗯,这里要注意:time.time()在MicroPython里返回的是秒级时间戳,精度够用。如果你需要更精细的控制,可以用time.ticks_ms()。
4.3 获取IP地址:连接成功的标志
连接成功之后,我们得拿到IP地址。没有IP,设备在局域网里就是透明的。
def get_ip_info(wlan):
"""
获取当前WiFi连接的IP信息
:param wlan: network.WLAN 对象
:return: dict 包含IP、子网掩码、网关、DNS
"""
if not wlan.isconnected():
print("未连接,无法获取IP")
return None
config = wlan.ifconfig()
# config 返回一个元组:(ip, subnet, gateway, dns)
info = {
"ip": config[0],
"subnet": config[1],
"gateway": config[2],
"dns": config[3]
}
return info
调用方式也很简单:
if connect_wifi("MyWiFi", "password123"):
wlan = network.WLAN(network.STA_IF)
ip_info = get_ip_info(wlan)
print(f"IP地址: {ip_info['ip']}")
print(f"网关: {ip_info['gateway']}")
我曾经遇到过一个坑:有些路由器会分配169.254.x.x的APIPA地址。这其实是设备没拿到有效IP的表现。所以拿到IP后,最好检查一下是不是以"169.254"开头。
wlan.ifconfig()返回的元组顺序是固定的——IP、子网掩码、网关、DNS。别搞反了,我见过有人把网关当IP用的。
4.4 完整连接流程:把函数串起来
现在我们把两个函数组合成一个完整的连接流程:
def wifi_connect_full(ssid, password, timeout=10):
"""
完整的WiFi连接流程:连接 + 获取IP
"""
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# 第一步:连接
if not connect_wifi(ssid, password, timeout):
return False, None
# 第二步:获取IP
ip_info = get_ip_info(wlan)
if ip_info:
print(f"连接成功,IP: {ip_info['ip']}")
return True, ip_info
else:
print("连接成功但无法获取IP")
return False, None
这个函数返回两个值:(是否成功, IP信息字典)。调用方可以根据返回值做后续处理。
4.5 连接状态与IP获取的SVG流程图
下面这张图把整个流程画清楚了。我建议你把它存下来,写代码的时候对照着看。
4.6 常见问题与避坑指南
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 一直连不上 | SSID或密码错误 | 检查SSID是否包含空格、特殊字符;密码是否区分大小写 |
| 连接成功但没IP | DHCP服务器未响应 | 检查路由器DHCP是否开启;尝试静态IP |
| IP是169.254.x.x | DHCP协商失败 | 重启路由器或设备;检查网线/信号强度 |
| 连接超时但WiFi正常 | 路由器开启了MAC过滤 | 在路由器后台添加设备MAC地址到白名单 |
4.7 本章小结
这一章我们干了三件事:
- 写了一个非阻塞的连接函数,用超时机制替代了死循环
- 实现了IP地址获取,并封装成可复用的函数
- 把两个函数组合成完整流程,返回成功状态和IP信息
说实话,这段代码看起来简单,但它是整个WiFi重连机制的基础。后面章节的自动重连、状态切换、事件回调,全都要依赖这个核心函数。
你现在可以把它烧到板子上试试。连上了,恭喜你——你的设备已经正式接入网络了。