编辑 | blame | 历史 | 原始文档

山外山透析机当前通讯解码说明

本文档基于当前项目代码实现、现场抓包校验结果和 schema.json 物模型整理。

适用项目:SWS-Communication

主要对应文件:
- src/protocol.js
- src/tcpServer.js
- schema.json

1. 总体说明

当前网关通过 TCP 接收山外山透析机上报的数据帧,按帧类型拆分并解码为结构化对象,然后写入缓存、输出本地日志,并按配置转发到 MQTT / 阿里云。

当前已实现并验证的帧类型:

  • 0x1F:运行参数帧
  • 0x26:报警帧
  • 0x29:血压测量帧

2. 帧结构

2.1 公共头结构

每一帧的公共头长度固定为 20 字节:

偏移 长度 含义
0 4 帧头,固定为 55 55 55 55
4 1 机器类型
5 5 机器编号
10 1 机器运行模式
11 1 数据帧类型
12 1 协议版本
13 7 保留

2.2 机器类型

当前代码映射如下:

机型
0x01 SWS-4000
0x02 SWS-4000A
0x31 SWS-6000
0x32 SWS-6000A

2.3 机器编号

当前实现已根据现场数据确认:

  • 机器编号为 5 字节无符号整数
  • 编码方式为 小端

例如:

  • 字节:E1 73 CB 72 01
  • 解码后:6220903393

项目中对应字段:

  • n:机器编号字符串

2.4 运行模式

当前已实现的运行模式映射:

含义
0x00 待机
0x01 透析
0x02 滤过
0x03 透析滤过
0x04 序贯-透析
0x05 单纯超滤
0x06 序贯-单超
0x07 预充
0x08 清洗
0x09 清洗消毒
0x14 透析结束
0x15 清洗结束
0x16 透析滤过结束
0x17 单纯超滤结束

3. 帧长度与拆包规则

当前代码和现场抓包已对齐的长度如下:

帧类型 含义 整帧长度 数据区长度
0x1F 运行参数帧 220 字节 200 字节
0x26 报警帧 150 字节 130 字节
0x29 血压帧 150 字节 130 字节

说明:

  • 当前拆包逻辑按 20 字节公共头 + 数据区长度 计算整帧。
  • 若当前 buffer 中没有找到帧头,则只保留最后 3 字节,防止垃圾数据导致缓冲区无限增长。
  • 每个连接当前有 buffer 上限保护,避免异常设备把内存打满。

4. 字节序说明

当前项目中经过现场验证后的字节序规则如下:

4.1 运行参数帧 0x1F

  • 多字节字段按 小端 解码
  • 压力类字段按 有符号小端 16 位 解码

对应:

  • readUInt16LE
  • readUInt32LE
  • readInt16LE

4.2 报警帧 0x26

  • 报警编号:**小端**
  • 年份:**小端**
  • 月/日/时/分/秒:单字节

4.3 血压帧 0x29

  • 年份、收缩压、舒张压、脉搏、平均动脉压:均按 小端 解码

5. 运行参数帧 0x1F

5.1 当前解码字段

当前代码 parseRunParams() 中已经实现并使用的字段如下:

偏移 长度 协议含义 当前字段 当前保存方式
0 4 设置治疗时间(秒) SetTreatmentTime 转换为分钟后保存
4 4 已治疗时间(秒) K 转换为分钟后保存
8 2 血泵流量(ml/min) D 原值
10 1 血泵运行标志 xlyxbj 原值
11 1 抗凝方式 klfs 原值
12 1 肝素泵运行标志 z 原值
13 2 肝素泵流量(放大 10 倍) E 除以 10
15 2 肝素提前结束时间(min) gstqjssj 原值
17 4 超滤总量(ml) A 转换为 L,保留 3 位小数
21 4 已超滤量(ml) B 转换为 L,保留 3 位小数
25 4 超滤率(ml/h) C 原值
29 1 超滤泵运行标志 cllyxbj 原值
30 1 旁路标志 plbj 原值
31 2 透析液流量(ml/min) L 原值
33 2 透析液实际温度(放大 10 倍) F 除以 10
35 2 透析液电导值(放大 100 倍) G 除以 100
37 4 补液总量(ml) pyzl 原值
41 4 已补入置换液量(ml) ypyzhyl 原值
45 1 补液补入模式 pyprfs 原值
46 2 内毒素滤器1使用时间(h) ldslq 原值
48 2 内毒素滤器2使用时间(h) ldslq2sysj 原值
50 4 机器总运行时间(min) jqzyxsj 原值
54 2 动脉压(mmHg) o readInt16LE
56 2 静脉压(mmHg) H readInt16LE
58 2 跨膜压(mmHg) J readInt16LE
60 2 透析液压(kPa × 10) I readInt16LE 后除以 10
62 1 尿素下降率(%) lsxjl 原值
64 2 实时清除率值(放大 100 倍) ssqclz 除以 100
66 2 静脉血温(放大 10 倍) jmyxh 除以 10
68 2 动脉血温(放大 10 倍) dmyxw 除以 10
69 1 相对血容量(%) xdxrl 原值

5.2 当前业务换算说明

时间字段

协议原始值单位为“秒”,但当前项目保存为“分钟”:

  • SetTreatmentTime = Math.round(秒 / 60)
  • K = Math.round(秒 / 60)

说明:

  • 日志和上报中看到的 SetTreatmentTimeK 现在是“分钟值”。
  • schema.json 中字段名仍保留旧命名(如 已透析时间s),但当前代码语义已改为“分钟”。

超滤量字段

协议原始值单位为 ml,当前保存为 L

  • A = (ml / 1000).toFixed(3)
  • B = (ml / 1000).toFixed(3)

示例:

  • 1800 ml -> 1.800
  • 500 ml -> 0.500

5.3 压力字段说明

现场抓包已确认以下字段必须按 有符号数 解析:

  • o:动脉压
  • H:静脉压
  • J:跨膜压
  • I:透析液压

原因:

  • 动脉压、透析液压等字段可能出现负值
  • 若按无符号解析,会出现类似 65411 这样的异常大正数

6. 报警帧 0x26

当前代码 parseAlarm() 解码规则:

偏移 长度 含义 当前字段
0 2 报警编号(小端) alarmCode
2 1 报警类型(0=解除,1=产生) bjlx
3 2 年(小端) bjsj 组成部分
5 1 bjsj 组成部分
6 1 bjsj 组成部分
7 1 bjsj 组成部分
8 1 bjsj 组成部分
9 1 bjsj 组成部分

输出字段:

{
  "alarmCode": 283,
  "bjlx": 1,
  "bjsj": "2026-03-16 10:30:45"
}

当前已通过现场帧验证:

  • 报警编号需按小端读取
  • 年份需按小端读取
  • 报警产生/解除状态可以正确区分

7. 血压帧 0x29

当前代码 parseBloodPressure() 解码规则:

偏移 长度 含义 当前字段
0 1 测量模式(0/1=手动/自动) bpMode
1 1 测量结果(0/1=失败/成功) bpResult
2 2 年(小端) M 组成部分
4 1 M 组成部分
5 1 M 组成部分
6 1 M 组成部分
7 1 M 组成部分
8 1 M 组成部分
9 2 收缩压(小端) N
11 2 舒张压(小端) O
13 2 脉搏(小端) P
15 2 平均动脉压(小端) BPMPJDMY

输出字段:

{
  "bpMode": 1,
  "bpResult": 1,
  "M": "2026-03-16 10:32:15",
  "N": 143,
  "O": 98,
  "P": 80,
  "BPMPJDMY": 113
}

当前已通过现场帧验证:

  • 收缩压、舒张压、脉搏、平均压均为小端
  • 偏移为 9 / 11 / 13 / 15

8. 网关输出字段

每次成功解析后,当前统一输出的基础字段包括:

字段 含义
suedtime 网关接收时间
deviceType 机器类型
IPAddress 设备来源 IP
n 机器编号
jqyxms 机器运行模式(中文)
jqyxmsRaw 机器运行模式原始值
frameType 帧类型
protocolVersion 协议版本

然后按帧类型追加:

  • 运行参数字段
  • 报警字段
  • 血压字段

9. 日志追踪

当前项目已经接入本地日志,并可追踪以下关键链路:

  • Device connected:设备什么时间连上
  • Raw TCP data received:设备发来了什么原始十六进制数据
  • Parsed frame / Dialysis frame parsed:报文解析成功
  • Dialysis frame payload:完整解析对象
  • MQTT publish success:MQTT 上报成功
  • Aliyun postProps success:阿里云上报成功
  • Device disconnected:设备何时断开、在线多久、收了多少字节和帧

10. 当前注意事项

10.1 schema.json 与当前业务语义存在部分差异

当前代码已经做了业务换算,但 schema.json 的部分名称还是旧含义:

  • K 的名称仍写成“已透析时间s”,但当前保存值是“分钟”
  • SetTreatmentTime 当前也已经改为“分钟”
  • A/Bschema.json 中是文本类型,当前保存为升值字符串,例如 1.800

如果后续要进一步规范,建议:

  • 把时间字段名称改成“分钟”
  • A/B 改成 float/double 类型

10.2 当前文档以“现有实现”为准

本文档的目标是说明:**当前程序实际是怎么解码和上报的**,便于联调、排障、交付。

如果后续协议理解继续修正,建议同步维护:

  • src/protocol.js
  • schema.json
  • docs/current-protocol-decoding.md

11. 建议的后续维护方式

每次现场确认新字段时,建议按下面顺序更新:

  1. src/protocol.js 中补偏移和解码逻辑
  2. schema.json 中补 identifier 与字段说明
  3. 在本文档中追加“偏移 / 长度 / 含义 / 当前字段 / 单位换算”
  4. 保留一条真实抓包样例,方便后续回归验证

如果需要,我下一步还可以继续给你输出一份:

  1. 更适合交付甲方的版本(偏业务说明,少代码痕迹)
  2. 更适合开发维护的版本(带完整偏移表和字段映射)
  3. 带真实示例帧的版本(把你已经验证过的十六进制样例附进去)