很多 Java 同学第一次接触物联网项目,是在某天领导说:"这个项目要接一批设备,你来负责。"
然后你拿到一份几十页的协议文档,满屏的 0x7E、BCD[6]、DWORD,再看看自己熟悉的 Spring Boot、MySQL、Redis,感觉中间隔着一条河。
我写了 10 年 Java,2018 年开始做物联网项目。最早是物流仓管,扫码、支付这些;后来做智慧园区,停车、空气质量、视频、办公楼闸机、智慧消防都要接;再后来是环卫,从收集点的垃圾桶满溢监测、收运车辆称重,到中转站、末端处理厂,整个垃圾收运流程的数据都要上云,还有智慧公厕、智慧公园。
这些项目的设备五花八门,厂家各不相同,协议也是一家一个样。但做多了就会发现,平台这一侧的套路其实是相通的:只要硬件的数据要上云,就绕不开接入层这一关。
我第一次接设备时踩的坑,现在回头看很好笑。当时接一批停车场的设备,协议文档上车牌号字段写着"STRING",我顺手用 UTF-8 去解,结果平台上的车牌第一个字全是乱码,后面的字母数字倒是好好的。查了半天才知道,国标协议里的中文一律是 GBK。改一个字符集就好了,但我花了一下午才想到往这个方向查。
这类问题有个共同点:Java 那一套你都会,卡住你的是"设备那一侧的约定"。字节序、编码、补位、校验,文档上往往一句话带过,不知道的人就要自己踩一遍。
这个系列就是想把这条河填平。不需要硬件,不需要懂嵌入式,只要你会写 Java,跟着走一遍,就能独立完成一个设备接入项目。
第一篇先不讲代码,我们先搞清楚:一个物联网平台,到底由哪几部分组成,Java 程序员在其中负责哪一块。
从一个例子说起:公交车的实时位置
打开地图 App,能看到下一班公交车还有几站到达。这个功能背后的链路大概是这样的:
markdown
公交车上的车载终端 运营商网络 平台 你的手机
┌──────────────┐ ┌─────────┐ ┌───────────────────────┐ ┌────────┐
│ GPS 模块 │ │ │ │ 接入层 → 消息队列 → 业务层 │ │ │
│ 4G 模块 │ ───► │ 4G 基站 │ ───► │ ↑ │ ───► │ App │
│ 每 10 秒上报一次 │ │ │ │ Netty Kafka Spring │ │ │
└──────────────┘ └─────────┘ └───────────────────────┘ └────────┘
设备层 网络层 平台层 应用层
一辆车每 10 秒上报一次位置,一个城市几千辆公交车,平台每秒就要处理几百条上报。数据流向看起来很简单:设备 → 网络 → 平台 → 应用。
我们一层一层来看。
设备层:会联网的"传感器 + 单片机"
车载终端、电表、水质监测仪、智能门锁、充电桩......本质上都是一样的结构:
- 采集:GPS 模块拿到经纬度,传感器测出温度、电压
- 处理:单片机把数据按照协议规定的格式,打包成一串字节
- 通信:通过 4G 模块、WiFi 或者有线网络发出去
设备端是嵌入式工程师写的,一般用 C 语言。我们 Java 程序员不需要写设备端的代码,但需要知道它会发来什么样的数据,这就是"协议"要约定的事情。
网络层:数据怎么到达平台
设备大多是通过运营商的 4G/5G 网络、NB-IoT,或者现场的有线网络连到互联网,最终和平台的某个 IP + 端口建立连接。
这一层基本不需要我们操心,但有一个特点必须牢记:设备的网络是不可靠的。车开进隧道就断网了,电表装在地下室信号只有一格。所以平台必须能处理断线、重连、数据重复、数据乱序等各种情况。
具体有哪些联网方式、各自适合什么场景,下一篇专门讲。
平台层:Java 程序员的主战场
平台层通常分成两部分。
接入层(也叫网关)
这是整个系列的重点。它负责:
| 职责 | 说明 |
|---|---|
| 维持连接 | 成千上万台设备同时保持 TCP 长连接 |
| 协议解析 | 把设备发来的二进制字节,解析成 Java 对象 |
| 鉴权 | 判断这台设备是不是合法的,防止伪造设备接入 |
| 会话管理 | 记住"终端号 13800138000 对应的是哪一条连接" |
| 指令下发 | 平台要让设备做事(比如锁车、拍照),通过同一条连接发回去 |
| 在线检测 | 设备多久没发心跳就判定为离线 |
| 转发 | 解析后的数据推给消息队列,交给业务层处理 |
接入层几乎都是用 Netty 写的。不用担心,我们只需要掌握 Netty 中接设备需要用到的那一小部分,后面会专门讲。
业务层
这就是你熟悉的世界了:Spring Boot、MySQL、Redis、消息队列。轨迹存储、电子围栏、报警推送、统计报表......这些都是普通的业务开发。
接入层和业务层之间用消息队列解耦,这是业内的通用做法。接入层只管"收得快、解得对",业务处理慢一点也不会拖垮设备连接。
应用层
App、Web 管理后台、大屏,以及给第三方系统开放的接口。没什么特别的,这里不展开。
接入层开发,和平时写 Web 有什么不一样
这是很多 Java 程序员刚开始最不适应的地方。我总结了几个最主要的区别:
| Web 开发 | 设备接入 | |
|---|---|---|
| 连接 | HTTP 短连接,请求完就断开 | TCP 长连接,一连就是几天几个月 |
| 状态 | 无状态,哪台服务器处理都一样 | 有状态,设备连在哪台服务器上,指令就得从哪台发 |
| 谁先说话 | 客户端请求,服务端响应 | 设备主动上报,平台也会主动下发 |
| 数据格式 | JSON,肉眼可读 | 二进制,一串十六进制字节 |
| 规范 | 自己团队定接口 | 遵循国家标准、行业标准或者设备厂家的协议文档 |
| 出错时 | 返回 500,前端提示一下 | 设备不会理你的报错,只会不停重连、重发 |
| 规模 | 并发几百上千就算不少了 | 一台服务器保持几万条长连接很常见 |
看起来区别很大,但别被吓到。这些问题都有成熟的套路,这个系列会一个一个讲清楚。
Java 程序员做 IoT 的优势
最后说点鼓舞人心的。
物联网项目里,嵌入式工程师负责设备,但平台这一侧,绝大部分公司用的都是 Java。也就是说,你已经掌握了 IoT 平台开发的大半技能,缺的只是接入层这一块:
- 二进制数据处理(字节、位运算、大小端)
- Netty 网络编程的基础
- 读懂协议文档的能力
- 一些行业协议的经验(比如车联网的 JT/T 808、环保行业的 HJ212)
而这四样,恰恰是普通 Java 开发很少接触、但学起来并不难的东西。会的人少,需要的项目多,这就是机会。
系列安排
接下来的文章会按这个顺序展开:
- 物联网平台到底在做什么(本篇)
- 设备是怎么连上平台的:TCP、MQTT、HTTP、DTU
- 国内的 IoT 为什么绕不开国标协议
- 二进制基础:Java 程序员读协议的第一关
- 手把手解析第一条 JT/T 808 报文
- TCP 拆包粘包:设备接入绕不开的第一个坑
所有示例代码都在 GitHub 上开源:iot-protocol-gateway,包括一个设备模拟器,没有硬件也能把整个流程跑通。
下一篇,我们来看设备到底是怎么连上平台的。
本文是《Java 程序员的 IoT 协议入门》系列的一篇。示例代码已开源:GitHub / Gitee 搜索 iot-protocol-gateway(自带设备模拟器,没有硬件也能跑)。后续文章首发在同名公众号「小物学长」。