Skip to content

ThingsBoard 自定义 TCP Transport ​

正文与配图来自原稿。CE 无 PE Integration 那种现成 TCP 长连接接入时,可按 MQTT Transport 结构自研 tcp-transport,支持上报与 RPC。

1、概述 ​

现场大量设备用 TCP / MQTT 连平台。ThingsBoard PE 可用 Integration 做 TCP;CE 没有同等能力,需要自定义 Transport:长连接、自定义编解码、上报遥测、接收 RPC。

Transport 公共逻辑在 common/transport,启动类在 transport / application 侧,需按官方模块规则接入。

2、创建 tcp 模块 ​

2.1、描述 ​

仿 MQTT:在 common/transport 下建 tcp 子模块,再在依赖与配置中打开。

2.2、common 下创建模块 ​

打开 transport 下已有模块:

transport 模块目录

选中 transport → New → Module:

New Module

按图配置:

模块向导

创建结果:

创建后目录

父 POM 增加 tcp 子模块:

父 pom 子模块

拷贝 mqtt 模块 pom 到 tcp,把 artifactId 改为 tcp:

拷贝 mqtt pom

改 artifactId

pom 细节

在 src/main/java 建包 org.thingsboard.server.transport.tcp:

包结构

codec / protocol 可省略,session 必须有:

session 包

坑: IDEA 模块显示名可能与 mqtt 不一致。对模块 Refactor → Rename → Rename module,改成类似:

tcp (org.thingsboard.common.transport)

Rename

Rename module

改名参数

改名后

依赖可直接参考 mqtt(transport-api、netty-all 等):

依赖

包结构再次确认:

包结构 2

关键类(与 MQTT 对齐) ​

类作用
TcpTransportContext继承 TransportContext,条件装配 transport.tcp.enabled
TcpTransportServiceNetty ServerBootstrap 绑定 transport.tcp.bind_address/port
TcpTransportServerInitializerpipeline:编解码 + Handler
TcpTransportHandler实现 SessionMsgListener,处理上行 JSON 与下行 RPC
TcpDeviceSessionCtx继承 DeviceAwareSessionContext,会话上下文

条件注解示例(与原稿一致):

java
@ConditionalOnExpression(
  "'${service.type:null}'=='tb-transport' || "
  + "('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' "
  + "&& '${transport.tcp.enabled}'=='true')"
)

TcpTransportService 用 Netty 监听配置端口,childHandler(new TcpTransportServerInitializer(context))。

Handler 内按 JSON 字段 serviceName 分支(原稿示例协议):

text
login     → {"serviceName":"login","sign":"123","data":{"token":"<ACCESS_TOKEN>"}}
heartbeat → {"serviceName":"heartbeat","sign":"123","data":{"heartbeat":"ping"}}
inPark    → {"serviceName":"inPark","sign":"123","data":{"carNumber":"川A123456"}}
outPark   → …

登录用 Token 建会话;业务报文转遥测上报;onToDeviceRpcRequest 里编码后经 TCP 写回设备。

2.3、transport 启动工程 ​

在 transport 侧建 tcp 启动相关工程/配置(对照 mqtt-transport):

启动工程 1

启动工程 2

启动工程 3

启动工程 4

启动工程 5

yml 中增加 transport.tcp(bind、netty 线程、enabled 等),写法可抄 transport.mqtt 段:

tcp 配置示意

2.4~2.6、POM 依赖三处 ​

根 POM:

xml
<dependency>
  <groupId>org.thingsboard.common.transport</groupId>
  <artifactId>tcp</artifactId>
  <version>${project.version}</version>
</dependency>

根 pom

application 模块:

xml
<dependency>
  <groupId>org.thingsboard.common.transport</groupId>
  <artifactId>tcp</artifactId>
</dependency>

application pom

tcp 启动工程 pom:

tcp 启动 pom

3、测试 ​

TCP 工具连 TB 的 TCP 端口:

TCP 客户端连接

平台创建设备,记下 Token:

创建设备

发送登录:

json
{"serviceName":"login","sign":"123","data":{"token":"<你的设备Token>"}}

登录报文

登录成功提示:

登录成功

设备页显示在线:

设备在线

上报业务(示例停车):

json
{"serviceName":"inPark","sign":"123","data":{"carNumber":"川A123456"}}

遥测可见车牌等字段:

遥测

平台下发 RPC 后,在 onToDeviceRpcRequest 收到并写出:

RPC 下发

Handler 收 RPC

4、核心小结 ​

核心是 TcpTransportHandler 实现 SessionMsgListener:上行自定义解码进 TB,下行 RPC 自定义编码经 Channel 写出。

必做三步:

  1. common/transport 定义 tcp 模块

模块

  1. 根 POM 声明依赖

根依赖

  1. application(及启动工程)引入依赖

application 依赖

其余对照 mqtt 模块改即可。


补充(辅) ​

  • 完整类代码以原稿/你仓库为准;本文抓结构与联调协议。
  • 打开 transport.tcp.enabled=true 并配置端口,避免与 MQTT 1883 冲突。
  • 对照:MQTT Transport 源码分析。

相关文章 ​