Android/iOS应用蓝牙向Pi Pico W传WiFi配置的技术求助
问题描述
我有个项目需求:通过蓝牙让Android/iOS应用和Pi Pico W连接,把WiFi配置信息传给Pico,Pico本地存储这些信息后连接指定WiFi热点。
我已经用Jetpack Compose(Kotlin)开发了安卓应用,目前能搜索并连接蓝牙设备。
我的Raspberry Pi Pico W运行MicroPython,这部分遇到了困难:用aioble库实现了设备广播与连接,但不知道怎么接收数据并处理成JSON文件。
现有代码(来自YouTube教程):
import sys import aioble import bluetooth import machine import uasyncio as asyncio from micropython import const def uuid(): return "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}".format( *machine.unique_id() ) MANUFACTURER_ID = const(0x02A29) MODEL_NUMBER_ID = const(0x2A24) SERIAL_NUMBER_ID = const(0x2A25) HARDWARE_REVISION_ID = const(0x2A26) BLE_VERSION_ID = const(0x2A28) led = machine.Pin("LED", machine.Pin.OUT) _GENERIC = bluetooth.UUID(0x1848) _BLE_APPEARANCE = const(960) ADV_INTERVAL_MS = 250_000 device_info = aioble.Service(_GENERIC) connection = None #Characteristics for device info aioble.Characteristic(device_info, bluetooth.UUID(MANUFACTURER_ID), read=True, initial="AuraByte") aioble.Characteristic(device_info, bluetooth.UUID(MODEL_NUMBER_ID), read=True, initial="1.0") aioble.Characteristic(device_info, bluetooth.UUID(SERIAL_NUMBER_ID), read=True, initial=uuid()) aioble.Characteristic(device_info, bluetooth.UUID(HARDWARE_REVISION_ID), read=True, initial=sys.version) aioble.Characteristic(device_info, bluetooth.UUID(BLE_VERSION_ID), read=True, initial="1.0") async def peripheral_task(): print('peripheral task started') global connected, connection while True: connected = False async with await aioble.advertise( ADV_INTERVAL_MS, name="AuraByteGateModule", appearance=_BLE_APPEARANCE, services=[_GENERIC] ) as connection: print("Connection from", connection.device) connected = True print(f"connected: {connected}") await connection.disconnected() print(f'disconnected') async def blink_task(): print('blink task started') toggle = True while True: led.value(toggle) toggle = not toggle blink = 1000 if connected: blink = 1000 else: blink = 250 await asyncio.sleep_ms(blink) async def main(): tasks = [ asyncio.create_task(peripheral_task()), asyncio.create_task(blink_task()) ] await asyncio.gather(*tasks) asyncio.run(main())
解决方案
1. 添加可写BLE特征接收数据
要接收手机端的WiFi配置,需新增一个支持写入的BLE特征,让手机能把JSON格式的配置数据写入该特征。在现有设备信息特征后添加:
# 自定义UUID用于WiFi配置传输(可自行更换为任意合法UUID) WIFI_CONFIG_UUID = bluetooth.UUID("0000ffb2-0000-1000-8000-00805f9b34fb") # 创建可写特征,支持手机写入数据 wifi_config_char = aioble.Characteristic( device_info, WIFI_CONFIG_UUID, write=True, notify=False, # 若需给手机回传连接结果,可设为True max_len=256 # 根据JSON大小调整,默认足够存储WiFi账号密码 )
2. 监听写入事件并解析JSON
新增异步任务监听特征写入事件,解析传入的JSON数据并执行后续操作:
import ujson # MicroPython自带JSON解析库 async def handle_wifi_config_task(): while True: # 等待数据写入wifi_config_char conn, data = await wifi_config_char.written() raw_data = data.decode('utf-8') print(f"收到WiFi配置: {raw_data}") try: # 解析JSON(手机需传入{"ssid":"热点名称","password":"热点密码"}格式) wifi_config = ujson.loads(raw_data) ssid = wifi_config.get("ssid") password = wifi_config.get("password") if not ssid or not password: print("配置不完整:缺少ssid或password") continue # 存储配置到本地文件 save_wifi_config(wifi_config) # 尝试连接WiFi await connect_to_wifi(ssid, password) except ValueError as e: print(f"JSON解析失败: {e}") except Exception as e: print(f"处理配置出错: {e}")
3. 实现本地JSON存储
添加函数将配置写入Pico文件系统:
def save_wifi_config(config): try: with open("wifi_config.json", "w") as f: ujson.dump(config, f) print("WiFi配置已保存到wifi_config.json") except OSError as e: print(f"保存文件失败: {e}")
4. 实现WiFi连接逻辑
添加函数连接指定WiFi热点:
import network async def connect_to_wifi(ssid, password): wlan = network.WLAN(network.STA_IF) wlan.active(True) if wlan.isconnected(): print(f"已连接WiFi: {wlan.ifconfig()}") return print(f"正在连接WiFi: {ssid}") wlan.connect(ssid, password) # 最多等待10秒连接 timeout = 10 while timeout > 0: if wlan.isconnected(): print(f"连接成功!IP: {wlan.ifconfig()[0]}") return timeout -= 1 await asyncio.sleep(1) print("WiFi连接超时失败")
5. 整合所有任务到主函数
修改main函数,加入新的配置处理任务:
async def main(): tasks = [ asyncio.create_task(peripheral_task()), asyncio.create_task(blink_task()), asyncio.create_task(handle_wifi_config_task()) # 新增任务 ] await asyncio.gather(*tasks)
额外优化:开机自动连接WiFi
在代码开头添加逻辑,启动时读取已保存的配置并自动连接:
# 开机尝试读取已保存的配置并连接WiFi def load_and_connect_wifi(): try: with open("wifi_config.json", "r") as f: config = ujson.load(f) asyncio.create_task(connect_to_wifi(config["ssid"], config["password"])) except OSError: print("未找到已保存的WiFi配置") # 在启动主任务前调用 load_and_connect_wifi()
注意事项
- 手机端需对应写入上述自定义UUID的特征,数据必须是严格的JSON字符串
- 若需给手机回传连接结果,可将特征
notify设为True,用wifi_config_char.notify(conn, b"success")发送通知 - Pico文件系统默认可写,若出现权限问题需检查固件设置
内容的提问来源于stack exchange,提问作者quinzyamg
相关产品推荐
相关产品推荐

