【从零搭建物联网智能充电桩系统】系列导读:从硬件到小程序的完整链路
本文是这个系列的总纲。我从零开始,用 Java + Spring Boot + Netty + MQTT + IoTDB 逐步搭建了一套智能充电桩系统,覆盖「硬件设备 → 云端 → 小程序/管理后台」全链路。没有现成团队和代码可抄,每一步都是自己查资料、写代码、踩坑、重构走过来的。这里整理了项目全景、模块划分与一条由浅入深的学习路线,后续每篇详解一个模块,把每个环节"为什么这么做、怎么落地的"讲清楚。
一、项目是什么
一套从「硬件设备 → 云端 → 小程序/管理后台」全链路的智能充电桩系统,单人全栈开发。
业务闭环:用户在小程序发起充电 → 云端下发指令给充电桩 → 桩上报实时状态 → 云端三路分发(实时推送小程序 / Redis 缓存 / IoTDB 历史存储)→ 充电结束结算扣费。
二、模块地图(代码仓库结构)
yeseesion-smart-charge-station/
├── pom.xml Maven 父工程(聚合 6 个 Java 模块)
├── charge-protocol/ 私有二进制协议(24 字节定长帧)
├── charge-mqtt-client/ MQTT 客户端(对接 EMQX,消息分发核心)
├── charge-netty-server/ Netty WebSocket 服务(对接小程序)
├── charge-user/ 用户/订单/钱包/管理后台 API(MySQL)
├── charge-iotdb/ 时序数据存储(IoTDB)
├── charge-demo/ 学习示例(非生产,端口与生产冲突)
├── charge-admin/ Vue 3 + Element Plus 管理后台
├── Yeseesion-ClientSide-MiniApp/ uni-app 微信小程序
└── yeseesion-ESP8266-ACS712/ ESP8266 硬件固件(接入真实桩)
端口分配:
| 服务 | HTTP 端口 | 其他端口 |
|---|---|---|
| charge-mqtt-client | 8080 | MQTT over WS: 8083 |
| charge-netty-server | 8085 | WebSocket: 8989 |
| charge-user | 8086 | --- |
| charge-iotdb | 8087 | IoTDB Session: 6667 |
| charge-demo | 8085(仅调试用) | Netty 1919 |
三、两条核心数据链路
链路 1:上行(设备 → 云端 → 用户)
ESP8266 充电桩
│ MQTT 发布 charge/stat(24 字节 hex 报文)
▼
EMQX Broker
│ MQTT 订阅
▼
charge-mqtt-client (InBoundMessageRev)
│ ChargeStatData.fromHexString() 解析 24 字节帧
│ buildStatJson() 组装业务 JSON
▼
RabbitMQ Fanout 广播 (charge.stat.exchange)
├─→ 队列① TTL 10s → charge-netty-server /netty/push → 小程序 WebSocket
├─→ 队列② TTL 30s → Redis SET charge:stat:{id} (TTL 24h)
└─→ 队列③ TTL 60s → charge-iotdb /iotdb/charge/stat → IoTDB
链路 2:下行(用户 → 设备)
小程序 WebSocket JSON 指令 (START/STOP/RESUME)
│ ws://netty:8989/ws
▼
charge-netty-server (JsonCmdHandler)
│ ChargeStatPushRegistry 注册 chargeId→Channel 映射
│ RabbitMQ Topic (charge.cmd.exchange)
▼
charge-mqtt-client (ChargeCmdConsumer)
│ MQTT publish charge/cmd
▼
EMQX → 充电桩执行
注意:上下行协议刻意采用两套方案 ------上行(设备→云端)用 24 字节真·二进制省流量;下行(用户→设备)从小程序发起,用「对象 JSON 序列化 → hex」的格式,是为了前端调试时能直接看清请求参数(若用二进制,小程序侧很难直观看到发出去的是什么)。这是"按场景选技术"的设计取舍,不是失误(真实代码如此)。
四、数据库(10 张 MySQL 表)
| 表名 | 用途 | 关键点 |
|---|---|---|
| cs_user | 用户(openid/手机号) | 微信登录 |
| cs_wallet | 钱包 | @Version 乐观锁字段 |
| cs_wallet_log | 钱包流水 | 冻结/解冻/充值 |
| cs_order | 充电订单 | 生命周期 |
| cs_recharge_order | 充值订单 | 支付 |
| cs_charge_record | 充电记录 | 与协议 chargeRecordId 对应 |
| cs_station | 充电站 | 列表 |
| cs_station_price | 分时电价 | 单价 |
| cs_connector | 充电枪 | 站点从属 |
| cs_alarm | 告警 | 运营监控 |
五、系列学习路线(按依赖顺序,共 8 篇)
| 顺序 | 主题 | 对应文章 | 读完能掌握 |
|---|---|---|---|
| 0 | 技术选型篇 | 00-技术选型篇-为什么用这些技术.md | 每项技术"为什么选/不用会怎样" |
| 1 | 系统架构与数据链路 | 01-系统架构与两条数据链路.md | 画清两条链路 |
| 2 | 私有二进制协议 | 02-24字节二进制协议详解.md | 24 字节帧字段布局 |
| 3 | MQTT 客户端 | 03-MQTT客户端设备接入.md | InBoundMessageRev 分发逻辑 |
| 4 | Netty WebSocket | 04-Netty实时推送服务.md | ChannelPipeline 装配 |
| 5 | 消息架构(RabbitMQ) | 05-RabbitMQ消息分发架构.md | 三路 TTL 设计 & 毒药消息 |
| 6 | 用户服务与钱包 | 06-用户服务与钱包系统.md | 乐观锁 + 事务 |
| 7 | IoTDB 与前端 | 07-IoTDB时序库与双端前端.md | schema 膨胀问题 |
每篇末尾都有「常见问题与解答」小结,覆盖该模块读者最关心的疑问。