ESP32 + Cloudflare Workers 的家庭 IoT 控制系统实践

通过 ESP32、DHT11、继电器和 LED 模块,配合 Cloudflare Workers 实现一个可在外网访问的家庭 IoT 控制面板。
你可以在公司打开网页,远程查看家里的温湿度,并控制灯泡、继电器等设备。

一、项目初衷

这个项目最初的想法很简单:
希望在外网环境下,也能安全地访问家里的 ESP32 设备,实现远程控制和环境监测。

具体动机有三个:

  1. 解决“人在公司,家里设备不好控制”的问题
    比如家里的灯、风扇、除湿设备,有时候需要根据温湿度手动调节。如果能远程看状态并控制,就方便很多。

  2. 把“本地智能”与“云端访问”结合起来
    ESP32 在本地负责采集温湿度并执行自动化逻辑;Cloudflare Workers 负责提供网页控制台和 WebSocket 转发。
    这样既保留了本地联动的实时性,也获得了公网可访问能力。

  3. 做一个低成本、易扩展的 IoT 原型
    这个方案只需要:

    • ESP32
    • DHT11 温湿度传感器
    • 3 路 LED 小灯泡
    • 4 路继电器
    • Cloudflare Workers 免费/低成本部署

整体成本低,但可扩展性不错,适合做家庭自动化、实验室控制面板,甚至作为后续智能家居项目的起点。


二、项目整体架构

这个项目的架构可以分成两部分:

1)ESP32 端

负责:

  • 连接家庭 Wi-Fi
  • 读取 DHT11 温湿度数据
  • 控制 LED 和继电器
  • 根据温湿度阈值执行本地自动化
  • 通过 WebSocket 与云端保持通信

2)Cloudflare Workers 端

负责:

  • 提供网页控制面板
  • 作为 WebSocket 中继
  • 校验访问密钥
  • 接收网页发出的控制指令
  • 接收 ESP32 上传的状态和传感器数据
  • 将消息广播给其他在线连接端

数据流

可以理解为:

  • 浏览器网页 → Cloudflare Worker → ESP32
  • ESP32 → Cloudflare Worker → 浏览器网页
  • ESP32 本地自动化 → 直接控制继电器/LED

也就是说,云端负责“连接”和“展示”,本地负责“执行”和“实时控制”


三、硬件组成与接线说明

硬件清单

  • ESP32 开发板
  • DHT11 温湿度传感器
  • 3 个 LED 小灯泡模块
  • 4 路继电器模块
  • 杜邦线若干
  • 供电模块或 USB 供电
  • 被控制的设备:例如灯、风扇、加湿器、除湿器等

引脚分配

项目中定义的 GPIO 如下:

  • DHT11 数据引脚:GPIO 4
  • 3 个 LED:
    • LED1 → GPIO 16
    • LED2 → GPIO 17
    • LED3 → GPIO 18
  • 4 路继电器:
    • R1 → GPIO 19
    • R2 → GPIO 21
    • R3 → GPIO 22
    • R4 → GPIO 23

接线逻辑说明

DHT11

  • VCC → 3.3V
  • GND → GND
  • DATA → GPIO 4

LED 模块

  • LED1 控制脚 → GPIO 16
  • LED2 控制脚 → GPIO 17
  • LED3 控制脚 → GPIO 18
  • 电源与地线按模块要求接入

继电器模块

  • IN1 → GPIO 19
  • IN2 → GPIO 21
  • IN3 → GPIO 22
  • IN4 → GPIO 23
  • VCC → 5V 或模块要求电源
  • GND → GND

代码里明确说明了:

  • 继电器多为低电平触发,LOW 表示开启
  • LED 为高电平触发,HIGH 表示开启

四、硬件接线图

文生图,有错误,仅供参考示意。

Gemini_Generated_Image_prdkbdprdkbdprdk


五、项目结构

这个仓库主要分成两个部分:

1)firmware/esp32-firmware/esp32-firmware.ino

ESP32 端固件,负责:

  • Wi-Fi 配网
  • 传感器读取
  • 设备控制
  • WebSocket 客户端通信
  • 自动化逻辑执行

2)src/index.js

Cloudflare Workers 端代码,负责:

  • WebSocket 服务端中继
  • Web 控制面板页面
  • 认证校验
  • 多终端广播

从职责上看,这是一个非常清晰的“端侧 + 云端”分层设计。


六、ESP32 端代码功能拆解

下面按功能模块拆解 firmware/esp32-firmware/esp32-firmware.ino


1)头文件引入

代码引入了这些库:

  • WiFi.h
  • DNSServer.h
  • WebServer.h
  • WiFiManager.h
  • WebSocketsClient.h
  • DHT.h
  • ArduinoJson.h

它们分别用于:

  • Wi-Fi 连接
  • 配网热点
  • WebSocket 通信
  • DHT11 传感器读取
  • JSON 数据打包与解析

2)GPIO 与硬件定义

1
2
3
4
5
#define DHTPIN 4
#define DHTTYPE DHT11

const int LED_PINS[3] = {16, 17, 18};
const int RELAY_PINS[4] = {19, 21, 22, 23};

这一段定义了硬件映射关系,是整个项目的基础。


3)云端配置变量

1
2
char cf_ws_host[64] = "your-worker.your-subdomain.workers.dev";
char cf_auth_key[32] = "";

这表示:

  • WebSocket 服务器地址可通过 WiFiManager 配置
  • 密钥也可以动态填写
  • 不需要把云端信息写死在代码里

这对部署和迁移非常友好。


4)设备封装函数

setRelay(int index, bool turnOn)

用于控制继电器:

  • turnOn == true 时输出 LOW
  • turnOn == false 时输出 HIGH

这是因为代码假设继电器板是低电平触发

setLED(int index, bool turnOn)

用于控制 LED:

  • turnOn == true 时输出 HIGH
  • turnOn == false 时输出 LOW

5)自动控制逻辑 handleAutoLogic()

这是项目里最有价值的逻辑之一。

逻辑规则

  • 若温度 > 30°C:
    • 打开继电器 1
    • 打开 LED 1
  • 若湿度 > 70%:
    • 打开继电器 2

这意味着:

  • 温度高时可以联动风扇/降温设备
  • 湿度高时可以联动除湿设备

这就是一个最小可用的家庭自动化规则引擎


6)状态上报函数 notifyStateChange()

这个函数会把设备状态封装成 JSON 并通过 WebSocket 发出去:

1
2
doc["device"] = device;
doc["state"] = state;

它用于把“某个设备开/关”的状态同步给云端或前端页面。


7)WebSocket 消息处理 webSocketEvent()

这部分是 ESP32 接收远程控制命令的核心。

它会解析收到的 JSON:

1
const char* action = doc["action"];

然后根据 action 执行动作,例如:

  • AUTO_ON / AUTO_OFF
  • LED1_ON / LED1_OFF
  • R1_ON / R1_OFF

这让网页控制台可以通过统一格式控制所有设备。


8)setup() 初始化过程

在启动时,ESP32 会完成这些动作:

  1. 串口初始化
  2. DHT11 初始化
  3. LED/继电器引脚初始化
  4. 启动 WiFiManager 配网页面
  5. 读取用户输入的 Worker 域名和密钥
  6. 构建 WebSocket 路径
  7. 连接 Cloudflare Worker

这一段体现了项目的“可部署性”:

  • 不用改代码就能改云端配置
  • 设备上电后自动接入网络

9)loop() 主循环

主循环中每 3 秒执行一次:

  1. 读取温湿度
  2. 执行本地自动化
  3. 将温湿度和自动模式状态上报给云端

这里的设计很合理:

  • 传感器轮询频率不高,避免资源浪费
  • 本地自动化不依赖云端网络稳定性
  • 云端负责展示和远程交互

七、Cloudflare Workers 端代码功能拆解

下面来看 src/index.js


1)入口函数 fetch()

Worker 接收到请求后,会先判断路径:

  • /ws:WebSocket 连接
  • 其他路径:返回 HTML 控制台

2)WebSocket 中继 /ws

这是整个系统的“桥梁”。

流程

  1. 判断是不是 WebSocket 请求
  2. 从 URL 查询参数取出 auth
  3. env.AUTH_SECRET 比较
  4. 验证通过后建立 WebSocketPair
  5. 把连接加入全局 sockets 集合
  6. 收到消息后广播给其他连接

这相当于:

  • 浏览器和 ESP32 都连到 Worker
  • Worker 作为消息中心进行转发

3)网页控制台 HTML

Worker 直接返回了一整页控制面板,页面功能包括:

  • 显示温度、湿度
  • 开关自动模式
  • 控制 3 路 LED
  • 控制 4 路继电器
  • 显示 WebSocket 连接状态

这是一个很适合演示和交互的轻量级前端方案,不需要单独维护复杂前端工程。

image-20260818170443916


4)前端 WebSocket 连接逻辑

浏览器端会:

  • 弹出输入框要求输入密钥
  • 根据当前协议生成 ws://wss://
  • 连接 /ws?auth=...
  • 接收 JSON 并更新页面状态

这使得页面既能控制设备,也能显示 ESP32 上报的数据。


八、这个项目的亮点

1)架构简单但实用

不是纯本地控制,也不是把所有逻辑都放到云端,而是做了清晰分层。

2)实时性不错

WebSocket 适合做控制面板和状态同步,延迟低,体验好。

3)支持自动化与手动控制并存

用户既可以远程手动控制,也可以开启自动模式,让设备按阈值联动。

4)配网方便

WiFiManager 让设备首次部署和改 Wi-Fi 非常方便。

5)云端部署成本低

Cloudflare Workers 非常适合这种轻量级中继和控制台场景。


最后

这次项目让我把 ESP32 的本地控制能力、Cloudflare Workers 的公网可访问能力、以及 WebSocket 的实时通信能力结合在了一起。
ESP32 负责读取温湿度并驱动继电器和 LED,Cloudflare Workers 负责提供远程控制面板和消息中继。
这个方案的优点是成本低、结构清晰、部署方便,同时具备一定的自动化能力。
虽然它还只是一个家庭 IoT 原型,但已经能完整覆盖“监测—控制—联动—远程访问”这条链路。
对我来说,这不仅是一个可用的小项目,也是一次把嵌入式、云函数和 WebSocket 串起来的完整实践。