云计算百科
云计算领域专业知识百科平台

IoT 系统架构全景:从传感器到云,一张图讲清“端-边-云“

IoT 系列第 1 篇。在《09_无线通信》里我们解决了"数据怎么飞出去",这一篇往上抬一层,看整张地图。

适用人群:玩过 STM32 或 ESP32、能读传感器、能连 Wi-Fi,但一被问"你这套东西架构是怎样的"就答不上来的同学。不需要服务器经验,Docker 命令我会从 0 给。

读完你能得到:

  • 一张能默出来的端-边-云三层架构图,面试画在白板上不心虚;
  • “为什么中间非要多一个网关”——四个能折算成钱或可靠性的理由;
  • 常见软硬件的对号入座(STM32/ESP32/树莓派/EMQX/云平台各站哪一层);
  • 一次完整数据流的六步走,知道你的字节过了几道手;
  • 协议选型视角:MQTT / CoAP / HTTP / LwM2M 不是四选一,是各管一段;
  • 半小时在本机跑起来的最小端边云(ESP32 + EMQX Docker + Node-RED)。

没看过无线通信那几篇也能懂的核心:传感器只负责"把物理量变成数字",数字要变成"别人能用的信息",中间还隔着链路、协议、网关、平台四层。本文讲的就是这四层怎么分工。


一、我曾经以为"IoT = ESP32 连 Wi-Fi 发个 HTTP"

大二那年我做了个"教室温湿度监测":ESP32 读 SHT30,每 10 秒 POST 一个 JSON 到我自己写的 Flask 接口,网页能看曲线。当时我觉得物联网不过如此。后来两个"看起来差不多"的需求把我打醒了。

第一个是学校试验田的土壤墒情。 田里没 Wi-Fi、没市电,要太阳能 + 电池活一学期。我原来的方案直接作废:一台设备开一个 HTTP 长连,光 TCP 握手的开销都比一包数据大。而且 20 个节点各自直连我的云服务器,20 条 TCP 连接 24 小时挂着——云是我自己的,钱包也是我自己的。

第二个是智慧路灯。 要求是"天黑自动亮、人走过加亮、断网了也要亮"。我第一反应是"云端写个规则呗",老师问我一句:校园网断了,你的路灯是不是就全瞎了? 我答不上来。这类"断网也要能工作"的需求,本质上是要求判断逻辑不在云上,而在路灯旁边。

这两个需求把我逼出了"设备直连云"的单一思维。真实的 IoT 系统里,设备和云之间几乎总是夹着一层东西,它叫边(Edge)。加上它之后,原本无解的问题突然有解了:

  • 田里 20 个电池节点不用各自连云,用 BLE 或 LoRa 甩给田埂上那个有电有网的网关统一上行——省电、省流量、省连接数;
  • 路灯的联动规则写在本地网关里,断网只是"上不了报",灯照样亮;
  • 上行数据先在网关滤波、聚合、只传变化量,流量费直接降一个数量级。

我没有量产经验,这些是我在课设和啃文档过程中整理的。但"端-边-云"不是我发明的,它是行业通用语言——你去面试,白板上画出来的那张图应该跟本文图 1 同一个骨架。


二、前置概念表:先把这几个词对齐

术语白话解释一句话记住它
端(Device / Node) 真正接触物理世界的板子:采集数据或执行动作 大多数端节点压根不会直接上网,也上不起网
边(Edge) 端和云之间的"中转 + 处理站"。有电、有网、算力比端强 它不是"转发器",是会思考的中转站
云(Cloud) 远端服务器集群:存储、分析、下发、对接业务 长处是算力和全局视角,短处是离设备太远
Broker MQTT 的消息中转服务器,按主题转发 设备之间从不直连,都在跟 Broker 说话
网关(Gateway) 协议转换器:把 BLE/Modbus/Zigbee 翻译成 MQTT/HTTP 网关是边最常见的物理形态;"边"还包括网关里跑的逻辑
上行 / 下行 设备→云叫上行(遥测),云→设备叫下行(命令) 上行求"稳",下行求"快"
主题(Topic) MQTT 里消息的地址,agri/gw01/telemetry,用 / 分层 主题设计好不好,决定以后加设备痛不痛苦

⚠️ 最容易搞混的一对:"边"是逻辑层,"网关"是具体设备。一个树莓派上跑 Mosquitto + Node-RED + 联动脚本,它既是网关(硬件),也是边(逻辑)。阿里云的"边缘计算实例"则是把边做成软件塞进别的机器——层还在,只是不再是一台看得见的盒子。


三、端-边-云三层全景图

[图 1] IoT 系统"端-边-云"三层全景(面试白板上画的那张)

┌──────────────────────────── 云 CLOUD ────────────────────────────┐
│ ┌─────────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ 物联网平台 │ │ 规则引擎 │ │ 业务应用 │ │
│ │ EMQX / 阿里云IoT │──>│ 阈值告警 │──>│ 大屏 / App / MES │ │
│ │ 华为云 / OneNET │ │ 数据清洗 │ │ 时序数据库 │ │
│ └─────────────────┘ └──────────────┘ └──────────────────┘ │
└────────┼─────────────────────────────────────────────────────────┘
│ MQTT over TLS:1883 / 8883
│ ↑ 这一段是广域网,会断、会慢、按流量收费
═════════╪══════════════════════════════════════════════════════════
│ 园区 / 现场局域网:通常免费、快,但地理范围有限
┌──────────────────────────── 边 EDGE ────────────────────────────┐
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 边缘网关(树莓派 / ESP32-S3 / 工控机 / 工业网关) │ │
│ │ ① 协议转换 BLE / Modbus / Zigbee / LoRa ⇄ MQTT │ │
│ │ ② 本地 Broker(可选)Mosquitto / EMQX,断网也能内部通信 │ │
│ │ ③ 边缘计算 滑动滤波、越限判断、聚合上报、单位换算 │ │
│ │ ④ 断网续传 本地队列 + SQLite / 文件缓存,联网后补传 │ │
│ │ ⑤ 本地联动 "温度>30 就开风扇",不依赖云 │ │
│ └───────────────────────────────────────────────────────────┘ │
└──────▲──────────────▲─────────────────────▲─────────────────────┘
│ │ │
BLE / Zigbee RS-485 / Modbus LoRa / 私有射频
┌──────┴───────┐ ┌────┴───────┐ ┌──────┴────────┐
│ 温湿度节点 │ │ 电表 / 水表 │ │ 土壤墒情节点 │
│ STM32+传感器 │ │ 工业仪表 │ │ 电池 + 太阳能 │
└──────────────┘ └────────────┘ └───────────────┘
端 DEVICES(数量多、资源少、大多不通 IP)

3.1 三层各自该干什么、不该干什么

判断一个功能放哪层,我的土办法是问三个问题:要不要全局信息?能不能容忍延迟?断网时还要不要工作?

层该它干的不该它干的典型软硬件
端 采样、执行、本地安全联锁、低功耗休眠(Stop / Deep Sleep)、基础自检 复杂规则判断、长连接、TLS 握手、大数据缓存 STM32(F1/F4/L4/U5 按功耗算力选)、ESP32-C3/S3(自带 Wi-Fi/BLE)、nRF52(纯 BLE)
边 协议转换、聚合/滤波、本地联动、断网续传、本地告警、固件分发 跨站点全局分析、长期历史存储 树莓派/香橙派(Linux + Docker)、ESP32-S3(轻量网关)、工业网关(RS-485/DI/DO)、跑 Mosquitto / EMQX / Node-RED
云 海量存储、跨设备关联分析、用户权限、OTA 版本管理、对接业务 毫秒级实时控制、单点高频联动 阿里云 IoT / 华为云 / OneNET(托管);自建:EMQX / Mosquitto + 时序库(TDengine/InfluxDB)+ 规则引擎

⚠️ 平台差异:同样叫"边",ESP32-S3 和树莓派不是一个量级。ESP32-S3 几百 KB RAM、无 MMU、跑 FreeRTOS,让它做"本地 Broker + 一周缓存"是想多了;树莓派是瓦级功耗、GB 级内存,能干的多得多但费电、贵、要管系统。选硬件前先算清楚"要缓存多少"“要不要跑容器”,别上来就上树莓派,也别硬扛。

💡 云端选型:托管平台的好处是"接入、鉴权、影子、OTA 都给你做好了",坏处是被绑死、按消息数收费、数据过别人手。自建全在自己手里、本地就能练手,代价是鉴权/高可用/监控自己扛。我的建议是先自建把 MQTT 搞明白,再学平台的封装——顺序反了,平台的"物模型"“影子”"Topic 类"你一个都看不懂。


四、为什么非要多一个"边":四个理由,逐个能算账

如果你以后只记得一句话,我希望是这句:边不是为了"多一层显得专业",它解决的都是能折算成钱或可靠性的问题。

4.1 省钱:带宽和云成本

假设一个大棚有 50 个节点,每 30 秒上报一次 100 字节:

方案 A:50 个节点各自直连云(每个都开 TCP + TLS)
每包实际开销 ≈ 100 B 载荷 + 40 B TCP/IP 头 + ~30 B MQTT 头 + TLS 记录头 ≈ 200 B 往上
每天:50 × 2880 × 200 B ≈ 28.8 MB/天 ≈ 864 MB/月;服务器维持 50 条 TLS 长连接

方案 B:节点走 BLE/LoRa 给网关,网关每 5 分钟聚合发一包(约 2 KB)
每天:288 × 2 KB ≈ 0.58 MB/天 ≈ 17 MB/月;服务器只维持 1 条连接

→ 流量降到约 1/50,连接数从 50 降到 1

数字是估算的,但数量级是对的:聚合 + 批量上传,是边缘层最直白的省钱方式。

4.2 省电:把最费电的活从电池节点身上拿走

《低功耗》那几篇的公式:平均电流 = Σ(各状态电流 × 停留时间) ÷ 周期。一次 MQTT 上报要 3~5 秒的高电流(含建连、TLS 握手),而一次 BLE 广播只要几十毫秒。把射频发射时长砍掉一两个数量级,续航直接翻倍。 所以我那个"发 HTTP"的 ESP32 教室节点用市电毫无问题,一换电池架构就得改:电池端只做短距离低功耗通信,联网的重活交给有市电的网关。

4.3 断网续传:最容易被忽视,也最容易在验收时翻车

我第一次做户外项目时写的是:采样 → 连 Wi-Fi → 发 HTTP → 失败就丢弃。只要那 5 分钟网络抖一下,数据就永久没了。验收时对方问我"昨天下午 3 点到 4 点的数据呢",我只能说"那会儿断网了"。

[图 2] 断网续传的基本结构

采样 ──> 打时间戳 ──> 本地环形队列(内存 + 掉电保存到 Flash/SQLite)
│
联网?───────┤
是 ─────────> 批量上行 → 收到确认 → 删除队列条目
否 ─────────> 继续攒,到上限就按策略丢最旧的

三个要点,每条都是踩过的:① 时间戳要在采样那一刻打,不是上传时打——否则断网一小时后补传的数据全挤在同一时刻,曲线是错的;② 队列要有上限,别把 Flash 写穿(和《17_存储》的写平衡、掉电保护是同一个问题);③ 补传要分批限速——断网两小时后一恢复灌几千条进去,轻则卡死自己,重则被 Broker 限流踢下线。

4.4 本地联动:呼应我在《项目实战_02》做的 BLE 网关

我在《项目实战_02:智能家居环境网关——ESP32 做 BLE 中心 + 本地联动》里干的事,用本篇的语言重述一遍:

[图 3] 同一个项目,两种架构

(a) 我最初的"云上联动"想法
传感器 ──Wi-Fi──> 云规则引擎 ──> 下发命令 ──> 执行器
断网 = 全瘫;每次联动绕一圈,延迟几百毫秒到几秒

(b) 实际做成的"本地联动"(边在起作用)
传感器 ──BLE──> ESP32 网关【规则:温度>28℃ 且 有人 → 开风扇】──> 执行器
└──MQTT──> 云(只负责记录和远程手动控制)
断网 = 只是上不了报,联动照常;延迟是毫秒级

这个经历让我彻底理解了"边":判断逻辑离被控对象越近,系统越可靠。 云是"全局视角和记忆力",不是"反射神经"——你不会指望大脑皮层负责膝跳反射。


五、数据是怎么流过去的:一次上行 + 一次下行

[图 4] 一次完整闭环,六个阶段

① 采集 传感器 → 数字量(I2C/SPI/ADC)
② 本地处理 标定、单位换算、滑动平均、剔除跳变、越限标记
③ 协议封装 组 JSON/CBOR,加设备 ID、时间戳、序号、校验
④ 上行 MQTT PUBLISH(QoS 1) → Wi-Fi/4G/LoRa → 网关 → Broker
⑤ 平台 解析、鉴权、入库、规则引擎判定、更新设备影子
⑥ 下行控制 PUBLISH 到 cmd 主题 → 设备校验执行 → 回报新状态(回到 ①)

关键:⑥ 执行完必须回报,形成闭环。否则 App 上永远是"已发送",
你不知道设备到底开没开——而这个"回报"本身就是一次上行。

⚠️ 第 ③ 步新手最常踩:把所有东西塞进一个主题。比如 device/data 里一会儿温度一会儿电量一会儿心跳,靠解析 payload 区分。后果是没法用主题过滤(云端规则写得又臭又长)、retained 消息也没法用。主题要按"用途"分层,不是按"设备"打包。


六、协议选型:不是四选一,是各管一段

这是我最想纠正的误解。教程常把 MQTT/CoAP/HTTP/LwM2M 摆一排让你"选一个",但真实架构里它们常常同时出现,只是在不同的段上。

[图 5] 协议是分段的,不是互斥的

端 ────────────> 边 ────────────> 云 ──────────> 业务
BLE GATT MQTT over TLS HTTPS / AMQP / Kafka
Modbus RTU (也可能直接 CoAP)数据库驱动
Zigbee / LoRa 私有帧

└─ 根本不是 IP 网络, └─ 这一段才是 └─ 跟嵌入式关系不大,
轮不到 MQTT MQTT 的主战场 是后端的事

所以听到"这设备用什么协议",第一个该问的是"从哪儿到哪儿"。

协议跑在报文开销模型该用的地方别用的地方
MQTT TCP(+TLS) 固定头最小 2 B 发布/订阅,长连接,支持推送 边↔云主力;遥测 + 下行命令;有市电设备 电池 + NB-IoT 的极低频上报(心跳本身就费电,见《无线_03》)
CoAP UDP 固定头 4 B 请求/响应(像精简 HTTP) 电池设备 + 极受限网络;NB-IoT/LoRa 直连 需要服务端主动推命令、对丢包零容忍的业务
HTTP(S) TCP 文本头,动辄几百字节 请求/响应,短连接 偶尔取配置、下载固件、对接 Web 后端 高频遥测(头比载荷大);下行实时控制
LwM2M 通常在 CoAP 之上 同 CoAP 面向"资源"(如 /3/0/1) 设备管理:远程配置、固件升级、生命周期 当"数据上报协议"用——那不是它的主场

💡 一句话记忆:MQTT 管来回传数据,CoAP 管极省电地传一包,HTTP 管跟 Web 世界打交道,LwM2M 管管理设备本身。 成熟平台里这四个往往同时在跑。

6.1 主题命名:现在多花 5 分钟,以后省 5 天

{产品}/{设备ID}/{方向}/{用途}
agri/gw01/up/telemetry 上行:周期遥测
agri/gw01/up/event 上行:事件/告警
agri/gw01/up/reply 上行:命令执行结果(闭环!)
agri/gw01/down/cmd 下行:命令
agri/gw01/status 状态(配合 retained + 遗嘱)

订阅侧:agri/gw01/down/#(这台的下行) agri/+/up/telemetry(所有设备遥测)

四条规矩:① 不以 / 开头(会产生空层级);② 主题里不放动态值(时间戳、随机数一律进 payload,否则主题树爆炸);③ 全小写 + 短横线,别混大小写;④ 主题里不放敏感信息,它是明文的,鉴权靠用户名/密码或证书。


七、动手:半小时搭一个最小端边云

这套我自己在笔记本上跑通过,不需要买云、不需要公网 IP,全在本机 Docker 里。

第 1 步:起一个本地 Broker(EMQX)

docker run -d –name emqx \\
-p 1883:1883 \\ # MQTT over TCP
-p 8083:8083 \\ # MQTT over WebSocket
-p 8084:8084 \\ # MQTT over WSS
-p 8883:8883 \\ # MQTT over TLS
-p 18083:18083 \\ # Dashboard(Web 管理页)
emqx/emqx:latest

docker logs -f emqx # 看日志确认起来了

浏览器打开 http://localhost:18083,默认账号密码 admin / public,首次登录会要求改掉默认密码。

⚠️ 后面让 ESP32 连这个 Broker 时,地址不能填 localhost 或 127.0.0.1——那是 ESP32 自己。要用电脑在局域网里的 IP(ifconfig / ipconfig 查)。这是"ESP32 连不上 EMQX"的头号原因,第二号是防火墙没放行 1883。

第 2 步:先用命令行验证 Broker 通了

sudo apt install -y mosquitto-clients # macOS: brew install mosquitto

# 终端 A:订阅(模拟"云/应用"一侧)
mosquitto_sub -h 192.168.1.100 -t 'agri/#' -v
# 终端 B:发布(模拟"设备"一侧)
mosquitto_pub -h 192.168.1.100 -t 'agri/gw01/up/telemetry' \\
-m '{"temp":26.5,"humi":61,"ts":1756000000}' -q 1

终端 A 应立刻打印出这一条。意义:先把云侧打通再调设备,这样设备联不上时你能确定问题在设备侧。

第 3 步:ESP32 上报(最小可用版)

/* ============ ESP32 / ESP-IDF v5.x:最小 MQTT 上报 ============
* 前置:Wi-Fi 已连接并拿到 IP(esp_wifi 或 example_connect 均可)
* 配置细节见本系列下一篇《MQTT 深度实战》
*/

#include <stdbool.h>
#include <string.h>
#include "mqtt_client.h"
#include "esp_log.h"

static const char *TAG = "app";
static esp_mqtt_client_handle_t s_client = NULL;

static void mqtt_event_handler(void *handler_args, esp_event_base_t base,
int32_t event_id, void *event_data)
{
esp_mqtt_event_handle_t event = (esp_mqtt_event_handle_t)event_data;

switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "broker 已连接");
esp_mqtt_client_subscribe(event->client, "agri/gw01/down/cmd", 1);
break;

case MQTT_EVENT_DATA: {
/* ⚠️ event->topic / event->data 不以 '\\0' 结尾,必须按长度拷贝 */
char topic[64];
int tlen = event->topic_len;
if (tlen >= (int)sizeof(topic)) tlen = (int)sizeof(topic) – 1;
memcpy(topic, event->topic, (size_t)tlen);
topic[tlen] = '\\0';

ESP_LOGI(TAG, "收到 [%s] qos=%d : %.*s",
topic, event->qos, event->data_len, event->data);
/* 执行完记得往 …/up/reply 回报一次,形成闭环 */
break;
}

case MQTT_EVENT_DISCONNECTED:
ESP_LOGW(TAG, "连接断开,esp-mqtt 默认会自动重连");
break;

default: break;
}
}

void mqtt_app_start(void)
{
const esp_mqtt_client_config_t cfg = {
.broker.address.uri = "mqtt://192.168.1.100", /* 换成你的局域网 IP */
.credentials.client_id = "esp32-gw01", /* 同 Broker 内必须唯一 */
.session.keepalive = 60, /* 秒 */
.network.reconnect_timeout_ms = 5000,
.network.timeout_ms = 10000,
};

s_client = esp_mqtt_client_init(&cfg);
if (s_client == NULL) { ESP_LOGE(TAG, "mqtt init 失败"); return; }
esp_mqtt_client_register_event(s_client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
esp_mqtt_client_start(s_client);
}

/* 上报一包遥测(在采集任务里调用) */
bool telemetry_publish(float temp, float humi, int64_t ts_ms)
{
if (s_client == NULL) return false;

char payload[128];
int n = snprintf(payload, sizeof(payload),
"{\\"temp\\":%.1f,\\"humi\\":%.1f,\\"ts\\":%lld}",
(double)temp, (double)humi, (long long)ts_ms);
if (n <= 0 || n >= (int)sizeof(payload)) return false; /* 格式化失败或截断 */

/* QoS 1:要等 PUBACK。返回 >=0 的 msg_id 才算进了发送队列 */
int msg_id = esp_mqtt_client_publish(s_client, "agri/gw01/up/telemetry",
payload, n, 1, 0);
if (msg_id < 0) {
ESP_LOGW(TAG, "publish 失败: %d(-2 = outbox 满,发的比网络快)", msg_id);
return false;
}
return true;
}

第 4 步:用 Node-RED 当那个"云上应用"

npm install -g node-red && node-red # 打开 http://localhost:1880
# 或:docker run -d -p 1880:1880 –name nodered nodered/node-red

拖四个节点连成一条线,这就是云层在干的事:解析 → 存储 → 展示。

┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐
│ mqtt in │──>│ json │──>│ function │──>│ debug / │
│ agri/# │ │ 解析字符串 │ │ 提取字段 │ │ chart │
└──────────┘ └──────────┘ └──────────┘ └─────────┘

mqtt in 节点填 Server 192.168.1.100:1883、Topic agri/#、QoS 1;function 节点只写一行:

// Node-RED function 节点内(JavaScript)
msg.payload = { value: msg.payload.temp, ts: msg.payload.ts };
return msg;

点 Deploy,再用 mosquitto_pub 发一次,debug 面板应立刻出现数据。到这一步你已跑通完整的"端 → 云 → 应用"链路——只不过"边"目前是空的。

第 5 步:把"边"加回来,做对比实验

  • 不聚合:ESP32 每 2 秒发一包,去 EMQX Dashboard 看消息速率;
  • 加上边:在 ESP32 里做 10 秒滑动窗口,只有"温度变化超 0.5 ℃ 或超过 30 秒没发"才上报;
  • 对比 Dashboard 上的「消息数 / 分钟」。
  • 你会看到一个数量级的差别,且数据几乎没有信息损失——这就是 4.1 那笔账的实物版。


    八、新手必踩的 8 个坑

    #坑现象 / 后果正确做法
    1 所有设备直连云,不考虑网关 连接数爆炸、流量费高、电池撑不过一周 先问"有没有市电、数量多少",10 个以上电池节点就该考虑边
    2 ESP32 里 Broker 地址填 localhost / 127.0.0.1 连不上,日志一片超时 填电脑的局域网 IP;确认防火墙放行 1883
    3 断网时直接丢数据 网络一抖,这段时间数据永久缺失 本地队列 + 采样时打时间戳 + 队列有上限 + 补传限速
    4 时间戳在上传时打,不是采样时打 补传的历史数据全挤同一时刻,曲线是假的 采样那一刻就打;或维护序号由平台还原
    5 所有消息塞进一个主题 云端规则写不动、没法过滤、retained 用不了 按 {产品}/{设备}/{方向}/{用途} 分层,一用途一主题
    6 主题以 / 开头,或把时间戳拼进主题 多出空层级;主题树爆炸撑爆 Broker 内存 不以 / 开头;主题只放稳定标识,动态值进 payload
    7 下行命令发出去就不管 App 显示"已发送",不知设备有没有执行 设备执行完回报 …/up/reply,形成闭环
    8 边这层硬件选型拍脑袋 树莓派做电池场景几小时没电;ESP32 硬扛一周缓存撑不住 先算"缓存多大、要不要跑容器、功耗预算多少"再选

    九、动手练一练

    按顺序做。第 3 步和第 5 步是故意搞破坏——只有亲眼见过故障现象,以后才认得出它。

    练习 1:把本机端边云跑通(30 分钟)

    按第七章做完。验收标准:ESP32 上电后 Node-RED 的 debug 面板持续收到数据,EMQX Dashboard 的 Clients 页能看到 esp32-gw01 在线。

    练习 2:用命令行手动模拟"设备"和"应用"

    不开 ESP32,只用两个终端互发。要求:你能说出这一包从"发布者 → Broker → 订阅者"经过哪些环节,并指出 Broker 在里面的作用。

    练习 3(故意试错):掐断网络,看数据会不会丢

    让 ESP32 正常上报,然后直接关掉电脑 Wi-Fi(或 docker stop emqx),等 30 秒再恢复。没有本地队列的话,这 30 秒的数据不见了,而且日志里可能什么都看不出来。然后加一个最简单的队列(哪怕只是内存里的环形数组 + 补传),再试一次。

    意义:这是"能演示的 demo"和"能交付的系统"之间的分水岭。

    练习 4:改主题结构,体会过滤的威力

    先把所有数据都发到 agri/data,在 Node-RED 里写过滤逻辑;再改成 agri/gw01/up/telemetry 的分层结构,用 agri/+/up/telemetry 订阅。对比两种写法下 Node-RED 流程的复杂度,你就明白为什么要分层。

    练习 5(故意试错):把 Broker 地址写错,学会看错误

    把 .broker.address.uri 改成 mqtt://192.168.1.999 重新烧录,看串口日志里 MQTT_EVENT_ERROR 的 error_type,然后对比两种情况:IP 不存在是传输层(TCP)失败且反复重试;IP 存在但端口没开(如填 1884)是连接被拒,重连间隔由 reconnect_timeout_ms 决定。

    意义:以后遇到"设备离线",你能第一时间分清是"网络不通"还是"Broker 不认我",而不是盲目重启。


    小结

    • 端-边-云是三次分工:端接触物理世界,边就地解决本地该解决的事,云负责全局和记忆。
    • 边的价值能折算成钱和可靠性:省带宽(聚合)、省电(重活从电池节点拿走)、断网续传(数据不丢)、本地联动(断网也能控)。每条都能讲出一个具体场景。
    • 协议是分段的:端↔边常常根本不是 IP 网络,边↔云才是 MQTT 的主场。别问"MQTT 和 CoAP 哪个好",要问"这一段用哪个"。
    • 主题设计要趁早:{产品}/{设备}/{方向}/{用途},一用途一主题,动态值进 payload。现在偷懒,以后要还。
    • 下行必须有回报,否则你的系统永远只有开环。

    参考:MQTT 3.1.1 / 5.0 协议规范(OASIS);EMQX 官方文档(Docker 部署与 Dashboard 端口);乐鑫 ESP-IDF 编程指南中 esp-mqtt 组件的配置说明。文中协议开销与流量估算为典型值,实际请以抓包(Wireshark)或 Broker 侧统计为准。

    下一篇:MQTT 深度实战——QoS、保留消息、遗嘱与订阅树,ESP32 对接 Broker

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » IoT 系统架构全景:从传感器到云,一张图讲清“端-边-云“
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!