1. 为什么ESP32成了智能家居方案的“万金油”
做智能家居开发这行当久了的人,基本都会遇到一个共同的纠结:选WiFi方案还是选蓝牙方案。
选WiFi,好处是直接联网、远程控制方便,手机在外地也能开关家里的灯;坏处是功耗高、配网麻烦,一个开关面板天天保持在线,路由器压力也大。选BLE(低功耗蓝牙),功耗确实低、配网快,但没法直接上云,必须有个网关中转,不然手机离了十米就失联。
所以很多人家里最后变成了一堆协议的混搭:灯走WiFi,传感器走蓝牙,门锁走Zigbee,三个App来回切,搞了半年连自己都记不清哪个设备在哪个网络里。
ESP32的出现,把这个选择题直接取消了。这颗芯片是少见的“WiFi+BLE双协议”原生集成的SoC,一颗芯片同时具备WiFi(802.11 b/g/n)和BLE 4.2/5.0能力。你不需要在PCB上多塞一颗蓝牙芯片,不需要写两套通信栈做桥接,一个固件里就能同时管理两种连接。再加上它价格便宜(模组批量几块钱)、双核240MHz的性能足够跑小型Web服务器或者简单的逻辑处理,几乎成了智能家居DIY圈的事实标准。
这篇文章不聊那些PPT上的概念,就基于我自己实际搭过的一套“WiFi+BLE一站式”方案,把选型思路、架构设计、实操代码、踩坑记录全部摊开讲。适合手里有一块ESP32开发板、想从点灯玩具进阶到完整家居方案的开发者,也适合正在纠结网关架构怎么设计的入门玩家。
这套方案的核心思路很简单:ESP32作为每个设备节点的主控,WiFi负责上云和远程控制,BLE负责本地快配网和低功耗传感器数据回传。两者各干各擅长的活,而不是互替。接下来我一步步拆。
2. 整体方案架构:别一开始就想着“全屋智能”的大而全
2.1 先搞清WiFi和BLE在方案里分别扮演什么角色
很多新手拿到ESP32第一反应是:我能不能只用WiFi把活儿全干了?
能,但代价很实际。如果你把每个温湿度传感器都做成WiFi设备,它们得持续连路由器,功耗在几十毫安到上百毫安量级,电池供电方案基本凉了;而且WiFi设备数量一多,路由器负载和信道占用都会暴涨,一个运行良好的家庭网络带20个WiFi设备已经不太从容,传感器这种小数据量设备挤在里面纯粹浪费资源。
而BLE这边天然适合传感器和开关这类低功耗、小数据量的场景。BLE广播模式下的电流可以做到微安级别,一颗CR2032纽扣电池撑一年不是梦。但BLE的短板是没法直接上互联网,你得有台网关(通常就是树莓派或者另一块常电ESP32)把BLE的数据收上来,再转成WiFi/MQTT发到云端。所以BLE在这里不是WiFi的替代,而是WiFi的补充。
我最终定下来的分工是这样的:
- 常电设备(插座、灯控、中控屏):直接用WiFi,常在线、响应快、支持OTA升级。
- 电池设备(门磁、温湿度计、人体存在传感器):走BLE广播或BLE连接,数据汇聚到网关后统一上云。
- 配网环节:用BLE做“快配网通道”。手机App通过BLE把家里的WiFi账号密码发给ESP32,ESP32收到后切换成WiFi模式去连路由器。这比传统的smartConfig/网页配网可靠得多,尤其对不支持5GHz的老路由器和复杂SSID(比如带特殊字符的)场景,BLE配网几乎不会失败。
这样一张网里,两种协议的定位非常清晰,不会互相干扰。WiFi通道承载控制和状态上报,BLE通道承载低功耗数据采集与配网握手,核心逻辑是让每种协议待在自己的舒适区里。
2.2 网关节点怎么选:树莓派还是另一块ESP32?
有了BLE设备,你就需要一个网关。这个网关在家里7x24小时通电,负责扫描/连接BLE设备,然后把数据转发到MQTT Broker,供Home Assistant这类平台消费。
我最开始的方案是用树莓派4B跑Home Assistant,再挂一个USB蓝牙适配器当BLE网关。这套方案成熟、生态好,HA里直接有ESPHome和BLE tracker集成,配置一下就能用。但对大多数普通人来说,树莓派现在的价格已经被炒到离谱,而且整套系统依赖SD卡、电源稳定性、Python环境,真不是零基础玩家能轻松搞定的。
更轻量、更便宜的替代方案是:拿一块ESP32开发板当网关。
ESP32-Gateway板只需要做三件事:
- 上电后连家里WiFi,连上MQTT Broker
- 周期性扫描周围的BLE广播包(iBeacon格式或厂商自定义格式),把RSSI和数据字段解析出来
- 通过MQTT publish到指定topic,让上层平台订阅
这块板的成本不到20块钱,功耗也就一两瓦,完全不挑电源,坏了大不了再买一块。性能上来说,ESP32跑一个扫描转发任务绰绰有余,毕竟它不是跑数据库和Web界面,只是做数据的搬运工。
两张网的角色分配,用一个简单表格来说明:
| 节点类型 | 通信协议 | 供电方式 | 主要职责 |
|---|---|---|---|
| 主控节点(灯/插座) | WiFi | 常电 | 接收云端指令、执行控制、上报状态、OTA |
| 传感器节点(温湿度/门磁) | BLE | 纽扣电池 | 低功耗采集、周期广播数据 |
| 网关节点 | WiFi+BLE | 常电 | 扫描BLE广播、解析数据、MQTT转发 |
| 手机端 | WiFi+BLE | 电池 | 局域网/远程控制,BLE快配网 |
这个架构跑起来之后你会发现一个明显的好处:单个节点掉线不会拖垮整个系统。WiFi设备挂了只是那一路控制不了,BLE节点没电了也只是少一条数据流,网关本身不依赖任何具体节点的状态。相比之前那种“主机+分机”的强耦合设计,这种Mesh式的逻辑更抗故障。
3. 硬件选型与接线要点:别让小细节坑掉整个项目
3.1 主控板选择:ESP32 DevKit、ESP32-C3还是ESP32-S3?
确定协议分工后,选具体芯片型号也有一番权衡。市面上常见的ESP32变体有经典ESP32(双核240MHz,WiFi+BLE 4.2)、ESP32-C3(单核RISC-V 160MHz,WiFi+BLE 5.0)、ESP32-S3(双核240MHz,WiFi+BLE 5.0,带AI加速指令)。在不追求极致性能的场景里,三款都能胜任,区别主要在引脚数量和功耗特性上。
我建议把项目按“节点类型”来选型:
- 做温湿度传感器节点,选ESP32-C3,因为它体积小、射频性能稳定、深度睡眠电流可以压到10微安左右,纽扣电池方案就靠它了。
- 做中控屏/网关,选经典ESP32或ESP32-S3,因为要跑Web Server、MQTT客户端、BLE扫描同时进行,双核大内存更从容。S3的PSRAM版本做屏幕UI渲染的时候优势明显。
- 做简单的开关面板,经典ESP32即可,成本最低,社区资料最多,几乎任何问题都能搜到答案。
这里有个非常容易踩的坑:ESP32-C3虽然引脚少,但不少开发板把GPIO11直连了板载RGB LED,你用GPIO11去驱动继电器的话,上电瞬间的Level变化会触发LED闪烁,甚至因为竞争造成逻辑紊乱。选型阶段就把引脚冲突问题查清楚,比焊完板子再飞线补救省太多事。
3.2 GPIO分配与电源设计中的实战经验
硬件设计上,我给自己定了一条铁律:先把ESP32的ADC引脚留出来,别为了省事把模拟传感器全怼到同一个ADC通道上。
ESP32经典款的ADC2在WiFi开启时会严重抖动,测量结果完全不可用。如果你要把电池电压、光敏电阻、土壤湿度这一类模拟量采集到系统里,务必放在ADC1的通道上(GPIO32-GPIO39)。ADC2的通道留给数字信号,别指望它们在WiFi活跃时还能给出稳定读数。
接线的另一个细节是继电器和舵机这类感性负载的处理。ESP32的GPIO输出电流有限,直接驱动继电器线圈会拉垮整个3.3V供电轨,造成系统反复重启。正确做法是GPIO先接一个NPN三极管或者ULN2003驱动芯片,然后继电器线圈两端反向并联一个1N4007续流二极管,否则关断瞬间的感生电动势能烧掉GPIO。
电源方面,常见的坑来自面包板供电。很多人拿USB线直接给开发板供电,再接几个传感器和继电器,结果电压一掉,WiFi连接就开始周期性断开。我的习惯是节点供电统一采用5V/2A适配器进板子的VIN,板载AMS1117转3.3V给ESP32本体,传感器和继电器单独从5V轨取电,不挤占3.3V的余量。这样射频发射瞬时电流再大也不会把3.3V拉到复位阈值以下。
如果你计划做电池版传感器节点,那低压差LDO比AMS1117靠谱得多。AMS1117的静态电流和压差在那摆着,电池电压跌到4.2V以下就开始不稳定。换一个RT9013或者ME6211这类LDO,静态电流在微安级别,对电池供电方案的续航影响可以忽略。
4. 核心代码实现:从零搭一套WiFi+BLE双栈固件
4.1 开发环境与工程骨架搭建
软件开发我推荐直接用Arduino框架,WiFi和BLE的API虽然比ESP-IDF封装得“重”,但对快速验证和原型开发友好得多。里面对ESP32的支持已经非常成熟,特别是Arduino-ESP32 2.x版本加入了ArduinoEvent和Arduino_ESP32_OTA这类高级功能,基本是智能家居API开发者的标配。
工程结构不要写成一个大文件,至少按功能分模块。我的目录长这样:
smart_home_node/ ├── main.ino // 初始化与主循环 ├── wifi_manager.h/.cpp // WiFi连接与断线重连封装 ├── ble_server.h/.cpp // BLE server/广播+配网逻辑 ├── mqtt_helper.h/.cpp // MQTT发布订阅封装 ├── sensor_read.h/.cpp // 传感器采集与数据解析 └── config.h // 引脚定义、MQTT服务器地址等配置项单独放一个头文件,后面换设备、换服务器地址时只改这一处就行:
// config.h #pragma once #define WIFI_SSID "YourHome" #define WIFI_PASSWORD "YourPassword" #define MQTT_HOST "192.168.1.100" #define MQTT_PORT 1883 #define MQTT_USER "mqtt_user" #define MQTT_PASS "mqtt_pass" #define SENSOR_UPDATE_INTERVAL_MS 30000 // 传感器上报周期 #define BLE_SCAN_INTERVAL_MS 5000 // BLE扫描周期,网关用4.2 WiFi模块:断线重连与心跳保活
WiFi连接这块,ESP32的WiFi.onEvent()比在loop里反复检查WiFi.status()优雅得多。用事件回调注册WiFi连接成功、断开、获取IP的通知,然后在断线事件里做重连逻辑。
void setupWiFi() { WiFi.mode(WIFI_STA); WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t info) { switch (event) { case ARDUINO_EVENT_WIFI_STA_CONNECTED: Serial.println("WiFi connected"); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP: Serial.printf("Got IP: %s\n", WiFi.localIP().toString().c_str()); break; case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: Serial.println("WiFi lost, reconnecting..."); WiFi.reconnect(); break; } }); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); }心跳保活方面,MQTT的keepalive默认是60秒,但ESP32在深度睡眠后被唤醒时,时间戳完全错乱,如果你不做NTP同步,MQTT Broker会因心跳过期把客户端踢下线。我习惯在MQTT连接成功后立即发起一次SNTP同步,保证后续发布的消息时间戳可信。
注意:千万不要把WiFi credentials硬编码在源码里然后上传到GitHub。我在GitHub上看到过无数个把自家WiFi密码commit上去的案例,智能家居安全第一道防线就是你的WiFi密码,别把它变成开源资源。
4.3 BLE配网:用手机App把WiFi账号输给ESP32
BLE配网是我这套方案里最“稳”的部分。逻辑是:ESP32上电后先以BLE Peripheral角色广播一个特定Service UUID,手机App扫描到这个服务后,通过Write Characteristic把WiFi SSID/密码/服务器地址传过去。ESP32收到后校验非空,然后重启切换为WiFi Station模式。
服务定义长这样:
#include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> #define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" #define CHAR_WIFI_CFG_UUID "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" class ConfigCallback : public BLECharacteristicCallbacks { void onWrite(BLECharacteristic* pCharacteristic) override { std::string value = pCharacteristic->getValue(); if (value.length() > 0) { Serial.printf("Received config: %s\n", value.c_str()); // 解析JSON格式: {"ssid":"xxx","pwd":"yyy","mqtt":"192.168.1.100"} // 解析成功后写NVS并ESP.restart() } } };配网消息格式建议直接用JSON,虽然串口调试的时候看起来啰嗦,但便于未来扩展(比如顺便传服务器端口、设备名称)。ESP32侧用ArduinoJson库解析,解析出错就回一个错误码给手机App,用户立刻知道哪里输错了。
这里有一个关键细节:BLE配网时,ESP32在广播/连接状态下的射频活动和WiFi是分时共存的。如果配网流程里WiFi一直开着扫描,让ESP32同时尝试连路由器,广播行为会被压缩得很厉害,手机扫描到这个设备就要花很久。所以我的配网逻辑是:上电后先关WiFi、只开BLE,等收到完整配置再重启进WiFi模式,两者互不干扰。
4.4 BLE传感器广播:低功耗采集与防冲突
传感器节点这块,我是用BLE广播模式来发数据的,不维持连接,这样功耗最低。ESP32 GAP层的广播包最多只有31字节有效载荷,你得分一部分给iBeacon的UUID和major/minor,剩下的地方用来放温湿度值。这样设计的好处是任何支持BLE扫描的设备(手机、树莓派、另一块ESP32)都能看到数据,不需要配对,不需要连接表。
传感器采集和广播的核心代码:
void setup() { // 配置深度睡眠唤醒源为定时器,间隔由config.h控制 esp_sleep_enable_timer_wakeup(SENSOR_UPDATE_INTERVAL_MS * 1000ULL); // 初始化DHT20温湿度传感器 sensor_init(); // 读取一次传感器数据,存入全局变量 read_sensor_data(); } void loop() { // 构建广播payload uint8_t payload[31] = {0}; int idx = 0; payload[idx++] = 2; // Flags length payload[idx++] = 0x01; payload[idx++] = 0x06; // LE General Discoverable + BR/EDR Not Supported // iBeacon或厂商自定义格式填充温湿度 payload[idx++] = 0x1A; // 长度 payload[idx++] = 0xFF; // 厂商类型 // ... 填充温度、湿度、电池电量百分比 esp_err_t ret = esp_ble_gap_config_adv_data_raw(payload, idx); if (ret == ESP_OK) { esp_ble_gap_start_advertising(); // 广播一次 } // 广播完成后立即休眠,省电 esp_deep_sleep_start(); }广播和深度睡眠搭配,核心坑点在于:广播必须在WiFi关闭状态下进行,否则广播间隔会被WiFi活动打乱,甚至出现广播不完整被接收端丢弃的情况。我在传感器节点的main代码里明确做了WiFi.mode(WIFI_OFF),然后才初始化BLE广播。
4.5 MQTT消息协议设计
设备端和网关把数据都汇到MQTT Broker之后,消息topic的规范化就至关重要了,否则后期设备一多,管理就是灾难。我给每类设备定了统一topic前缀:
home/<device_location>/<device_type>/<device_id>/state home/<device_location>/<device_type>/<device_id>/command举个例子,客厅的温湿度传感器会上报:
home/livingroom/sensor/thermo_01/state 内容: {"temp":26.3,"hum":58.2,"battery":91}而灯光面板会订阅:
home/livingroom/light/light_main/command 内容: {"action":"toggle"}用device_type区分sensor/light/switch/cover,用device_id区分同一个位置的多个设备,发布端和订阅端都从这个规范里取数据,不写死任何topic字符串。这算是MQTT项目的基本素养,顺便说一句,设计不好的topic树等到你家里挂了30个设备之后,排查日志会让人崩溃。
家庭自动化平台方面,我直接接的Home Assistant,HA内置MQTT集成,订阅这些topic后通过mqtt.discovery自动发现设备,配置一个topic_prefix即可完成大部分自动化。你如果不想用HA,也可以用一个简单的Node-RED实例订阅这些topic做逻辑,甚至直接写一个Python脚本轮询也行,MQTT Broker本身不关心消费端是谁。
5. 实战实录:从烧录到上线的完整流程
5.1 烧录方式选择与避坑
ESP32的烧录方式五花八门,串口烧录(UART)、JTAG、USB直连(依赖芯片内置USB-Serial-JTAG)、OTA。日常开发阶段我推荐直接用板载串口,一条Micro-USB线接电脑,Arduino IDE里选好端口和板型点上传就完事。
但有几个烧录常见坑得提前说:
- 下载失败/连接超时:绝大多数是GPIO0电平问题。经典ESP32进入下载模式必须让GPIO0在复位时为低电平。很多开发板上有BOOT按键,上传前按住BOOT再按一下RESET,然后松BOOT。带自动下载电路的板子(比如ESP32 DevKit v4)则没有这个困扰,一键上传。
- 驱动问题:CP2102/CH340这类USB转串口芯片需要装驱动。Windows 10以上系统一般自动识别,Linux下可能需要
brltty驱动的干扰处理。遇到“No serial data received”这一行报错时,九成是驱动问题,先检查设备管理器有没有识别到COM口。 - 供电不足导致上传中断:部分劣质USB线只有电源线没有数据线,或者线材压降太大。换一根带磁环的短数据线,问题立解。我曾在车库调试半天无解,最后发现是USB延长线太劣质。
OTA烧录是量产节点最值得先部署的能力。ESP32的Arduino框架自带ArduinoOTA库,支持通过WiFi上传固件。我所有WiFi节点都刷上了OTA支持,这样后续改逻辑、改topic格式,不需要拆墙里预埋的开关面板,人在路由器旁边就能全部升级一遍。
5.2 实操:一块ESP32-C3做电池温湿度传感器节点
我拿一个实际项目来演示整个从接线到代码上线的流程。某次改造书房,需要监控桌面区域温度和湿度,我选了ESP32-C3 SuperMini板+一颗DHT20数字温湿度传感器,预算不到25块钱。
接线很简单:DHT20的VCC接C3的3V3,GND接GND,SDA接GPIO4,SCL接GPIO3(C3上的I2C默认引脚是4和3)。DHT20是I2C接口,不是DHT11那种单总线,所以驱动库用的是Adafruit_Sensor加DHT20,不是DHT库,这点很多人搞混。
代码主流程也就几十行,就是上面展示的广播逻辑,测量间隔设30秒,我实测平均电流在广播瞬间约20mA,广播持续约15ms,然后进入深度睡眠,平均下来整机功耗大约在40微安左右,用两节AA电池供电,理论续航七八个月(受低温环境影响可能打折扣)。
5.3 实操:网关节点部署与数据验证
路由器旁的网关我用的是经典ESP32 DevKit,代码相对长一点:初始化WiFi、连接MQTT、开启BLE扫描并解析广播包topic、转发到MQTT。核心代码片段如下:
void setup() { setupWiFi(); mqttClient.setServer(MQTT_HOST, MQTT_PORT); mqttClient.setCallback(mqttCallback); // 连接MQTT while (!mqttClient.connected()) { if (mqttClient.connect("esp32_gateway", MQTT_USER, MQTT_PASS)) { Serial.println("MQTT connected"); break; } delay(1000); } // 初始化BLE扫描器 BLEDevice::init(""); pBLEScan = BLEDevice::getScan(); pBLEScan->setActiveScan(true); // 主动扫描,能拿到广播数据+扫描响应 pBLEScan->setInterval(100); // 扫描间隔 pBLEScan->setWindow(99); // 扫描窗口 pBLEScan->start(BLE_SCAN_INTERVAL_MS, false); }每次扫描回调里,我把广播的原始字节捞出来,用自定义解析器把温度和湿度字段抠出来,然后mqttClient.publish("home/office/sensor/thermo_01/state", payload.c_str())。网关本身不存储数据、不跑自动化逻辑,它只是管道,唯一需要注意的BUG是不要在每个扫描结果里都去publish,否则数据量太大MQTT Broker会飙CPU,加一个5秒聚合窗口批量上报比较科学。
5.4 联动Home Assistant做自动化场景
HA接入后的效果最直观。MQTT集成配置好之后,书房温湿度实体自动出现,我给它配了两条自动化:温度超过28度时开风扇,回到25度以下关风扇;湿度低于40%时空气加湿器开半小时。这些规则在HA的automations.yaml里写,简单几行:
alias: "书房高温开风扇" trigger: - platform: state entity_id: sensor.office_temperature above: 28 action: - service: switch.turn_on entity_id: switch.office_fan整个过程从硬件焊接到HA里出现实体并联动,一个下午能跑通。这套链路的核心价值在于:它不是某个平台定制的点灯方案,而是用MQTT把硬件层和应用层彻底解耦。以后要换平台、换规则、加设备,都不影响底层节点。
6. 常见问题排查实录:这些坑我替你踩过了
6.1 问题速查表
| 现象 | 根本原因 | 解决思路 |
|---|---|---|
| ESP32反复重启,日志停在“Brownout” | 电源电压跌落 | 换独立5V电源,检查USB线压降,加1000uF电解电容缓冲 |
| WiFi连上后秒断,循环重连 | 射频干扰或供电不稳 | 调低ESP32 TX功率到12dBm;天线附近不要走长导线;排查同一频段2.4G干扰源 |
| BLE广播手机扫不到 | 未关闭WiFi、广播间隔过大、未设置广播类型 | 初始化前强制WiFi.mode(WIFI_OFF);setAdvData设置可连接广播 |
| 温度读数剧烈跳变 | ADC2通道受WiFi干扰 | 换到ADC1通道或用数字传感器接I2C |
| MQTT消息延迟高,状态回不来 | keepalive心跳超时、断线未重连 | 在loop里定期调用mqttClient.loop(),事件回调里重连 |
| OTA上传开始1秒就失败 | 分区表不对,默认没有OTA分区 | 烧写时选择“Huge APP (3MB No OTA)”或“Default 4MB with spiffs”等含OTA的分区表 |
| 深度睡眠后被唤醒但WiFi怎么也连不上 | WiFi_STA在唤醒后未初始化 | 唤醒后延迟100ms再初始化WiFi,先WiFi.persistent(false)再begin() |
6.2 最典型的“灵异”故障:ADC读数在全屋WiFi开启后瘫痪
这个故障我在好几个项目里遇到,症状是:传感器的ADC读数在单板调试时正常,一旦设备接入家庭WiFi,读数开始无规律波动。排查到最后发现是ESP32的ADC2与WiFi模块共用了部分模拟前端,当WiFi活跃时,ADC2完全不可用。
这是硬件设计层面的坑,无解,只能绕开。所有需要实际可信模拟采集的场景,一律走ADC1(GPIO32~GPIO39),或者干脆不用片内ADC,外挂一个I2C接口的ADS1115,精度还更高。
6.3 BLE和WiFi同时跑时的吞吐优先策略
当网关既要维持WiFi的MQTT长连接,又要不间断扫BLE广播时,两种射频同时启用会导致WiFi吞吐下降和BLE扫描丢包。实测下来,BLE扫描窗口占空比高时,WiFi的Ping延迟能到几百毫秒,控制指令响应像卡壳一样。
解决方法是调整扫描参数:setInterval(100)、setWindow(99)在ESP32上会触发连续扫描模式(即收完一个信道立刻切下一个信道),这会让WiFi的通讯时隙被挤占。实测中把setWindow降到50~60左右,WiFi延迟能恢复到50ms以内,BLE广播的接收率虽然会掉两三个百分点,但完全不影响温度这类慢变数据的准确性。优先保证控制通道的实时性,牺牲一点传感器上报频率,是智能家居网关场景下的正确取舍。
6.4 一个小技巧:NVS里存配置而不是每次重编译
很多新手改WiFi账号或MQTT地址时,每次都要改源码重新烧录,极其痛苦。ESP32内置的NVS(非易失性存储)可以直接把配置存进Flash,配网时写入一次,重启后自动读取。我的做法是配网流程里把接收到的JSON配置全部写进NVS,设备从BLE模式切换到WiFi模式前先尝试读NVS合法配置,读不到才进入配网模式。
用Preferences这个库就能搞定:
#include <Preferences.h> Preferences prefs; prefs.begin("net_cfg", false); prefs.putString("ssid", ssid); prefs.putString("pwd", pwd); prefs.putString("mqtt_host", mqttHost); prefs.end();重启后读出来,格式校验通过就直接连WiFi。这样一劳永逸,再也不用为了改密码把墙角的天花板拆了重刷固件。
7. 后续还能往哪些方向扩展
整套“WiFi+BLE一站式”架构跑通后,可扩展的方向非常多。我自己在实践中最想补的几块,也顺便给大家指个路:
一块是通过BLE Mesh做更复杂的设备联动。目前BLE广播方案适合点到点的传感器数据回传,但如果你需要做“门开了自动开灯”这种本地联动,只要设备支持BLE Mesh,不再依赖WiFi和云端,断网时本地自动化也能跑。ESP32的ESP-BLE-MESH协议栈已经能把灯、开关、传感器组成本地Mesh网络,响应延迟比走云端MOTT链路低一个量级,是个值得研究的方向。
另一块是电源管理的精细化。电池供电的传感器节点,如果深度睡眠时间足够长,可以把静态电流压到个位数微安,实测用一颗CR2032电池续航超过一年。这里面涉及的是一个很实用的小技巧:传感器上电后先做一次启动稳定延时(大约200ms),然后校准内部RC振荡器,在广播之前确保射频电路的电压稳定。这些小细节决定了电池方案能不能真的落地。
再就是语音控制入口的接入。家里有HA以后,加一个小爱同学或天猫精灵的接入,用语音控制灯和风扇就变得异常简单。ESP32的WiFi链路天然支持HTTP API,HA里给每个设备配一个webhook,语音助手调webhook比用MQTT直连简单很多。
8. 关于这套方案,我自己最想说的大实话
如果你问我把这套“WiFi+BLE一站式”方案推荐给什么程度的人,我的回答是:硬件基础为零的人也能玩,但别一上来就追求全部功能。先买一块ESP32开发板和几个DHT20传感器,照着这篇文章的步骤把温湿度数据打到MQTT上,再用手机订阅topic看到数据,你就已经超越了大多数只会“点灯”的初学者。至于网关、HA自动化、双协议并发这种高级玩法,等你有了第一台设备的部署经验后再逐步加,每一步都有实时反馈,不会走偏。
最后分享一个我每次帮朋友搭系统都要提的细节:智能家居的外网访问安全不要依赖端口转发,尤其是ESP32这类直连设备的Web面板,暴露到公网等于给黑客留后门。正确做法是全程走MQTT over TLS或者走HA的远程访问代理,保证家庭网络边界的安全性。这一点现在做项目的可能体会不深,等吃过亏会知道这比任何功能优化都重要。
这套架构的优点在于它不绑定任何平台、任何特定硬件版本,你说它是一个家居方案,其实它更像一套通信骨架。WiFi干WiFi擅长的,BLE干BLE擅长的,MQTT在中枢当传话筒,剩下的一切由你定义。