Description
Checks
-
I agree to follow the MicroPython Code of Conduct to ensure a safe and respectful space for everyone.
-
I've searched for existing issues matching this bug, and didn't find any.
Port, board and/or hardware
ESP32-C3-MINI-1(DK) ESP-ROM:esp32c3-api1-20210207
MicroPython version
MicroPython v1.22.2 on 2024-02-22; ESP32C3 module with ESP32C3
Reproduction
run code:
'''
如果先激活WLAN再激活AP, 则会出错 OSError: Wifi Invalid Mode
'''
import network, time, json, machine
import uasyncio as asyncio
# 先开AP
ap = network.WLAN(network.AP_IF)
ap.config(essid='ESP32-C3', password='12345678')
ap.config(max_clients=3)
ap.active(False)
ap.active(True)
print('AP信息:', ap.ifconfig())
wlan = network.WLAN(network.STA_IF)
wlan.active(False)
wlan.active(True)
connect_wifi_task = ''
async def run_connect_wifi_task(ssid, password):
while True:
try:
wlan.active(False)
wlan.active(True)
wlan.connect(ssid, password)
print('开始连接', ssid, password)
count = 0
while not wlan.isconnected():
count += 1
print('连接重试:', count, wlan.status())
if count == 10:
raise Exception('超时')
if wlan.status() == 201:
raise Exception('没有找到网络')
await asyncio.sleep(1)
pass
except Exception as e:
print('连接出错', e)
# 立即关闭WLAN, 防止造成AP异常
wlan.active(False)
await asyncio.sleep(6)
pass
print('WLAN信息:', wlan.ifconfig())
def connect_wifi(ssid, password):
print('连接', ssid, password)
global connect_wifi_task
if connect_wifi_task != '':
connect_wifi_task.cancel()
connect_wifi_task = ''
pass
connect_wifi_task = asyncio.create_task(run_connect_wifi_task(ssid, password))
pass
# 处理HTTP请求
async def http_handle(reader, writer):
client = writer.get_extra_info('peername')
print(f'HTTP客户端连接 {client}')
# 读取方法路径协议行
line_path = await reader.readline()
line_path_text = str(line_path)
print(f'HTTP方法路径协议行 {line_path_text}')
# 读取Headers
# https://github.com/micropython/micropython/blob/d11ca092f75d2652df403dda7448fe1bc8f98cf7/tests/net_inet/asyncio_tcp_read_headers.py#L10
print('Headers 如下:')
while True:
line = await reader.readline()
line = line.strip()
if not line:
break
print(str(line, 'utf-8'))
pass
print('Headers ----')
if line_path_text.find("b'GET /") != -1:
print('HTTP客户端GET请求')
writer.write('HTTP/1.1 200 OK\r\nContent-type: text/html; charset=utf-8\r\n\r\n')
writer.write(f"""<!DOCTYPE html>
<html>
<head> <title>里路微控</title> </head>
<body>
<h1>里路微控</h1>
<p>{time.localtime()}</p>
<p>来自 <a href="https://lilu.red">里路</a></p>
</body>
</html>
""")
pass
if line_path_text.find("b'POST /") != -1:
print('HTTP客户端POST请求')
# 读取Body
body_data = await reader.read(512)
body_text = str(body_data, 'utf-8')
print('Body 如下:')
print(body_text)
print('Body ----')
# 解析数据
post_data = json.loads(body_text)
# 按逻辑处理
if line_path_text.find("b'POST /wifi ") != -1: # 设置WIFI
print(f'HTTP客户端POST请求设置WIFI')
if 'wifi_ssid' not in post_data or post_data['wifi_ssid'] == '' or 'wifi_password' not in post_data or post_data['wifi_password'] == '':
print('HTTP设置WIFI数据无效')
writer.write('HTTP/1.1 400 Bad Request\r\n\r\n')
pass
else:
connect_wifi(post_data['wifi_ssid'], post_data['wifi_password'])
writer.write('HTTP/1.1 200 OK\r\n\r\n')
pass
else:
print(f'HTTP客户端POST请求不在预期范围 {line_path_text}')
writer.write('HTTP/1.1 400 Bad Request\r\n\r\n')
pass
pass
# 发送响应内容
await writer.drain()
# 关闭
writer.close()
await writer.wait_closed()
print('HTTP客户端断开')
pass
async def main():
asyncio.create_task(asyncio.start_server(http_handle, "0.0.0.0", 80))
# asyncio.create_task(connect_wifi('a', '12345678'))
while True:
await asyncio.sleep(1)
pass
try:
asyncio.run(main())
except KeyboardInterrupt:
print("主动关闭")
finally:
asyncio.new_event_loop()
Post not exists SSID {"wifi_password": "wrong12345678", "wifi_ssid": "kmx"}
to http://192.168.4.1/wifi
:
连接 kmx wrong12345678
开始连接 kmx wrong12345678
连接重试: 1 1001
HTTP客户端断开
连接重试: 2 1001
连接重试: 3 1001
连接重试: 4 201
连接出错 没有找到网络
if wlan.status() == 201
, Post right SSID {"wifi_password": "wrong12345678", "wifi_ssid": "km"}
to http://192.168.4.1/wifi
:
连接 km wrong12345678
开始连接 km wrong12345678
连接重试: 1 201
连接出错 没有找到网络
HTTP客户端断开
开始连接 km wrong12345678
连接重试: 1 201
连接出错 没有找到网络
wlan.status()
always 201...
Expected behaviour
- The 201 status should not remain when reconnecting to an right network again.
- Regardless of whether it was 201 or 202 status before, network should be reset when reconnecting.
- WLAN connection failure should not cause the AP to disconnect.
Observed behaviour
When reconnect to right SSID with wrong password, the wlan.status()
should be 202
. After testing, it was found that the board may still be connected to the previous SSID(kmx).
When wlan.status()
is 201
, I must call wlan.active(False)
immediately. If not do this, the AP will shutdown automatic. But after call wlan.active(False)
, the AP can continue to work.
And if connect to right SSID with wrong password at first time(wlan.status() is 202), Then post right SSID and right password, The board can connect successful.
Additional Information
The user's situation is much more complicated when distributing the network. Hope the API behaves as expected. Thanks very much.