跳至主要內容

Tcp协议设备接入

fastbee2024年9月27日大约 10 分钟

一、开启TCP服务

TCP开启在application.yml文件中控制。

提示

tcp.enabled: 开启后, TCP服务器启动连接设备

openws: 开启后,配合TCP服务,推送设备消息至前端实时更新

二、TCP设备连接

1. 注册包:

由于TCP设备连接,需要识别设备,因此TCP客户端连接时,上报的第一个报文为客户端的注册包。

例如:7e80D4AD203F3A1C7e

其中 7e 是包头包尾

80是注册包的标识位

D4AD203F3A1C 是设备编号

客户端上报注册包后,更新设备状态为在线

2. 心跳包:

TCP需要主动发送消息来维持设备的心跳保持,上图中 keep-alive 是心跳超时的判定时间 70s,因此设备的心跳需要维持在70s以下。

心跳包例如: 7e817e 7e 是包头包尾,81是标识位 (心跳包只是维持TCP长连接,一般无其他实际意义)

3. 特殊的注册,心跳 数据包:

在有些设备客户端,会把设备的注册包,心跳包,数据包,定时上报,一方面是包含了设备编号,也可以维持了心跳,数据包还包含了设备上报的信息,这种情况系统也是可以支持的。

三、TCP模拟客户端测试

模拟客户端放在如下文件

1. 模拟客户端上线

发送注册包:配置好后,点击链接,发送注册包,如下 7e80D4AD203F3A1C7e

这个时候,看下本地启动服务可以看到

查看前端页面展示: webSocket 推送设备上线消息,实时更新前端显示

2. 模拟TCP客户端断电或 断开

断电需要等待设备心跳超时(70S), 断开连接是,是实时上报设备状态

断开连接是,打印信息如下,更新设备上下线状态,新增设备事件记录,前端ws推送实时更新

同样模拟客户端断电,需要等待客户端超过心跳超时时间 (70s),更新动作跟设备断开一致。

四、TCP客户端前端连接展示

新建产品,传输协议选择TCP,通讯协议可以选择 JSON、ModbusTcpOverRtu协议、ModbusRtu协议

新建产品后,选中产品新建设备即可。

五、TCP + MODBUS

  1. MBAP 报文头(Modbus Application Protocol Header)
    • 事务标识符(Transaction Identifier):用于匹配请求和响应,通常由客户端生成。
    • 协议标识符(Protocol Identifier):固定为 0,表示 Modbus 协议。
    • 长度(Length):后续数据的字节长度,包括单元标识符和 PDU (Protocol Data Unit)。
    • 单元标识符(Unit Identifier):用于标识从站设备。
  2. PDU(Protocol Data Unit)
    • 功能码(Function Code):指示要执行的操作,如读取、写入等。
    • 数据(Data):根据功能码的不同,包含相应的操作数据。

云端轮询,用模拟设备可以看到下发到设备的读指令,如下:

六、TCP+JSON

这里采用动态倾角监测仪(通讯协议)2023-3-1 103136 设备通讯协议进行演示。(应答机制)

详情

A. 设备监测数据报文

  • 报文说明

动态倾角仪处于低功耗的时候、按照平台设定的采集间隔和发送间隔通讯、监测站每一个通讯间隔向平台发送一次监测数据,数据采用HTTP以POST方式发送、数据格式为标准的JSON键值对。如果平台在2倍间隔时没有收到监测数据、可判定为设备离线。

  • 报文示例
{
      "dev_ty":4000,
      "pro_ty":"rf_epmt_qjdt_1105",
      "use_id":0,
      "dev_id":2302180001,
      "pcb_ver":221214,
      "bot_ver":2023021700,
      "app_ver":2023030100,
      "net_ty":1,
      "link_ty":0,
      "pak_ty":"up_data",
      "mk_id":"",
      "ka_id":"",
      "rssi":0,
      "snr":0,
      "x_jsd":0.0492592602968216,
      "y_jsd":0.0070370370522141457,
      "z_jsd":4.4122223854064941,
      "temp_c_val":14.195767402648926,
      "x_jd":0.63720703125,
      "y_jd":0.0933837890625,
      "z_jd":89.3463134765625,
      "cj_s":300,
      "up_s":3600,
      "xt_s":3600,
      "run_s":70,
      "in_v":0.00880800001323223,
      "bat_v":6.4534401893615723,
      "gn_wd":0,
      "gn_jd":0,
      "gn_hb":521,
      "mem_sx":19276,
      "tm_sm":"000101001046"
}
  • JSON键值说明
键名数据类型说明备注
dev_tyU16设备类型厂家研发编码、用户无需在意
pro_tyString产品类型rf_epmt_qjdt_1105=动态倾角仪
use_idU16用户ID厂家对用户的编码
dev_idU32设备唯一ID设备厂家对设备的唯一编号
pcb_verU32电路板版本号设备电路板版本号
bot_verU32启动程序版本远程启动程序版本号
app_verU32功能程序版本功能程序版本号
net_tyU8网络类型1=CAT1、5=NBIOT、6=RJ45、8=北斗短报文
link_tyU8连接类型0=短连接=设备发送完数据等待5秒主动断开连接、1=长连接=设备发送完毕数据不断开连接。
pak_tyString数据包类型"up_data"=上报监测数据
mk_idString无线模块号模块号IMEI=15-20个字符串组成
ka_idString流量卡号物联网卡号IMSI=15-20个字符串组成
rssiS16信号强度现场网络信号的强度
snrS16信号质量现场网络信号的质量
x_jsdfloatX轴加速度重力加速度、单位g
y_jsdfloatY轴加速度重力加速度、单位g
z_jsdfloatZ轴加速度重力加速度、单位g
temp_c_valfloat温度设备内部温度、单位℃
x_jdfloatX轴角度倾角度、单位°
y_jdfloatY轴角度倾角度、单位°
z_jdfloatZ轴角度倾角度、单位°
cj_sU32采集数据间隔设备每cj_s秒采集并和阈值对比一次传感器数据
up_sU32上报数据间隔设备每到up_s秒向平台发送一次数据报文、平台收到以后尽快向设备回馈报文、超过2倍up_s时间没有收到平台回馈,设备会重启当前连接。
xt_sU32设备心跳数据预留键值对、暂时未使用
run_sU32设备运行时间设备从上电到现在的工作时间、单位秒
in_vfloat太阳能或输入电压太阳能或市电AC-DC适配器输入的电压
bat_vfloat蓄电池电压蓄电池电压
gn_wdfloat定位纬度GNSS当前定位-纬度
gn_jdfloat定位经度GNSS当前定位-经度
gn_hbfloat定位海拔GNSS当前定位-海拔高度
mem_sxU32剩余内存设备操作系统的剩余内存
err_cdU16错误代码当前设备的错误代码0=无错误、其它的参考后面的错误代码定义
tm_sm//预留键值对、暂时未使用

B、平台回馈报文

  • 报文说明

平台收到倾角仪的监测数据以后、需尽快通过SET报文,向倾角仪发送参数设置信息。考虑信号不好的网络延迟和平台服务响应时间在内、如果在10秒内没有收到平台的ACK回馈,倾角仪在预定的重传次数内(固定为5次)、向平台重传数据保证通讯的可靠性。

  • 报文示例
{
      "pak_ty":"set_inf",
      "cj_s":null,
      "up_s":3600,
      "xt_s":3600,
      "x_yz":500,
      "y_yz":500,
      "z_yz":500,
      "nian":2022,
      "yue":3,
      "ri":25,
      "shi":12,
      "fen":23,"miao":33
}
  • JSON键值说明
键名数据类型说明备注
pack_tyString数据包类型"set_inf"=设置报文
cj_sU32数据采集间隔平台设置设备的数据采集间隔
up_sU32上报数据间隔平台设置设备的数据上报间隔
xt_sU32设备心跳间隔平台设置设置的心跳上报间隔、默认不使用
x_yzFloatX轴增量阈值设置X轴的增量阈值,1.2为±1.2的变动
y_yzFloatY轴增量阈值设置Y轴的增量阈值,1.2为±1.2的变动
z_yzFloatX轴增量阈值设置Z轴的增量阈值,1.2为±1.2的变动
nianU8下发同步=年平台下发设备同步时间=年=2022=22
yueU8下发同步=月
riU8下发同步=日
shiU8下发同步=时
fenU8下发同步=分
miaoU8下发同步=秒
err_cdU16错误代码错误代码0=无错误、其它的参考后面的错误代码定义

设备上报报文: (设备数据,注册包,心跳包组合)

{
      "dev_ty":4000,
      "pro_ty":"rf_epmt_qjdt_1105",
      "use_id":0,
      "dev_id":2302180001,
      "pcb_ver":221214,
      "bot_ver":2023021700,
      "app_ver":2023030100,
      "net_ty":1,
      "link_ty":0,
      "pak_ty":"up_data",
      "mk_id":"",
      "ka_id":"",
      "rssi":0,
      "snr":0,
      "x_jsd":0.0492592602968216,
      "y_jsd":0.0070370370522141457,
      "z_jsd":4.4122223854064941,
      "temp_c_val":14.195767402648926,
      "x_jd":0.63720703125,
      "y_jd":0.0933837890625,
      "z_jd":89.3463134765625,
      "cj_s":300,
      "up_s":3600,
      "xt_s":3600,
      "run_s":70,
      "in_v":0.00880800001323223,
      "bat_v":6.4534401893615723,
      "gn_wd":0,
      "gn_jd":0,
      "gn_hb":521,
      "mem_sx":19276,
      "tm_sm":"000101001046"
}

服务端收到设备上报消息,应答设备:

{
      "pak_ty":"set_inf",
      "cj_s":null,
      "up_s":3600,
      "xt_s":3600,
      "x_yz":500,
      "y_yz":500,
      "z_yz":500,
      "nian":2022,
      "yue":3,
      "ri":25,
      "shi":12,
      "fen":23,
      "miao":33
}

模拟TCP客户端示例:

七、TCP客户端指令下发

如下图所示:

查看模拟模拟客户端可以看到,写指令下发成功,如下图所示:

八、TCP数据包,粘包,分包处理

TCP粘包拆包发生场景

对于粘包和拆包问题,常见的解决方案有四种:

  1. 发送端将每个包都封装成固定的长度,比如100字节大小。如果不足100字节可通过补0或空等进行填充到指定长度;
  2. 发送端在每个包的末尾使用固定的分隔符,例如\r\n。如果发生拆包需等待多个包发送过来之后再找到其中的\r\n进行合并;例如,FTP协议;
  3. 将消息分为头部和消息体,头部中保存整个消息的长度,只有读取到足够长度的消息之后才算是读到了一个完整的消息;
  4. 通过自定义协议进行粘包和拆包的处理

Netty对粘包和拆包问题的处理

Netty对解决粘包和拆包的方案做了抽象,提供了一些解码器(Decoder)来解决粘包和拆包的问题。如:

FastBee的TCP服务端,解决粘包,分包问题

  1. 固定分隔符

DelimiterBasedFrameDecoder 类定义了分割符处理粘包,分包问题

TCP服务器启动处理客户端消息配置中,第二个处理类配置了粘包,分包处理在TCP启动时候,添加分隔符号

  1. 固定长度

LengthFieldAndDelimiterFrameDecoder ,固定长度配置在TCP启动时候,配置如下做固定长度处理粘包,分包问题