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

透析机 Socket 服务器

概述

这是一个 Node.js Socket 服务器,用于接收和处理透析机数据。程序直接打开即可运行,无需额外配置环境。

一、系统目标

  • 通过 TCP Socket 接入多台透析机设备,稳定接收设备实时数据报文。
  • 将原始报文按协议解析为结构化数据,并在内存中维护“最新一帧”数据。
  • 按配置将数据分发到三类上游通道:
  • 对内/对第三方系统的 HTTP 接口;
  • 消息中间件(MQTT);
  • 云平台(阿里云物联网平台)。
  • 支持灵活配置:可独立启用/禁用 HTTP、MQTT、阿里云三通道,以及各自的端口、地址、主题等参数。

二、运行环境与外部依赖

  • 运行环境:Node.js(可通过 pkg 打包成独立可执行文件)。
  • 外部依赖:
  • TCP 网络(设备通过固定 IP+端口连接到网关)。
  • 可选:MQTT Broker(如 EMQX、Mosquitto 等)。
  • 可选:阿里云物联网平台(需产品和设备三元组管理服务)。
  • 可选:后端 HTTP API,用于根据设备序列号获取阿里云设备三元组。

三、模块划分与功能

1. TCP 通讯模块(Socket 服务)

  • 职责:
  • 监听配置端口,接受透析机 TCP 连接。
  • 处理粘包、拆包:按照协议从流式数据中截取完整报文。
  • 维护设备连接状态、心跳、重试和超时清理。
  • 功能点:
  • 监听端口由配置文件指定,支持 IPv4 / IPv6 映射地址。
  • 为每个连接维护:
    • socket
    • lastAck(最近一次收到有效数据的时间戳)
    • statuspendingvalidregistered
    • 设备编号、最近一帧完整数据等。

2. 设备管理模块(DeviceManager)

  • 职责:
  • 统一管理所有在线设备连接和状态。
  • 负责启动/停止设备级定时任务(重试、保活)。
  • 负责全局超时清理。
  • 功能点:
  • 接收到新连接时,创建设备实例并发起初始握手信号。
  • 全局超时清理定时器
    • 固定周期(例如每 5 分钟)遍历所有设备;
    • 若当前时间减去 lastAck 超过配置的超时时间(如 2 分钟),判定为超时;
    • 自动断开连接、释放资源、移出设备列表并记录日志。

3. 协议解析模块

  • 职责:
  • 对透析机发送的数据切片解析。
  • 将每个字段转换为具有业务含义的键值对,并附加元信息。
  • 功能点:
  • 按字节/字符位置解析各字段(A~Z、a~z、C53~C55 等)。
  • 生成结构化对象,包括:
    • 协议字段(例如:机器运行模式、动脉压、IP地址 )。
    • 元字段:
    • suedtime:网关接收到数据的时间(格式:YYYY-MM-DD HH:mm:ss)。
    • deviceType:机器类型标识。
    • IPAddress:该设备 TCP 连接的远端 IP 地址。

4. 数据缓存模块(DataCache)

  • 职责:
  • 以“设备序列号”为主键,缓存该设备“最新一帧”解析后的数据。
  • 提供查询、统计、空闲检测等能力给 HTTP 接口和监控使用。
  • 功能点:
  • setDeviceData(deviceNumber, data):写入/更新指定设备数据,并记录缓存时间。
  • getDeviceData(deviceNumber):按设备号返回最新缓存。
  • getAllDeviceData():返回所有设备的当前缓存快照。
  • getDeviceList():返回设备列表(设备号 + 最后缓存时间)。
  • getStats():统计设备数量、估算内存占用,返回详细设备列表。
  • getIdleDevices(timeoutMs):返回在指定时间内未更新的“空闲设备”,可用于排查设备掉线或通讯异常。

5. 属性映射与物模型模块(PropertyMapper)

  • 职责:
  • 将内部字段标识符(如 A/B/C、a/b/c、C53 等)映射为对业务友好的属性名称。
  • 为 HTTP/MQTT/阿里云三通道提供统一的数据结构。
  • 功能点:
  • 从外部配置(如 schema.json)加载物模型定义,若失败则使用内置默认物模型。
  • 提供方法:
    • mapData(rawData):将原始对象转换为属性数组 [ {identifier, name, value}, ... ]
    • transformForHTTP(rawData, deviceNumber):专用于 HTTP 返回结构。
    • transformForMQTT(rawData, deviceNumber):专用于 MQTT 消息负载。
    • transformForAliyun(rawData):用于阿里云属性上报(直接以 identifier 作为物模型属性 ID)。

      6. HTTP 接口服务模块

  • 职责:

  • 提供 REST 风格 HTTP 接口,供第三方系统查询透析机实时/近实时数据。
  • 提供缓存与限流的管理能力。
  • 核心接口(示例):
  • GET /api/device/data?deviceNumber={n}[&mapped=true]
    • 返回指定设备最新数据,支持:
    • raw 格式:内部原始字段;
    • mapped 格式:基于物模型映射后的属性数组。
    • 按设备号做访问限流(例如 5 秒内重复查询返回 429)。
  • GET /api/device/all[?mapped=true]
    • 返回所有有数据设备的快照,可按配置和参数决定是否做属性映射。
    • 使用统一 Key(如 __all_devices__)做全局访问限流(例如 1 分钟一次)。
  • GET /api/device/list
    • 返回设备号 + 最后更新时间列表。
  • GET /api/cache/stats
    • 返回缓存统计信息。
  • POST/GET /api/cache/clear
    • 清空所有缓存数据。
  • GET /api/device/idle?timeout={ms}
    • 返回指定超时时间内未更新的设备。
  • GET /api/ratelimit/stats / POST /api/ratelimit/clear
    • 查询和清空限流统计。
  • GET /api/health
    • 健康检查接口。
  • 配置能力:
  • 是否启用 HTTP 服务;
  • 监听地址和端口;
  • CORS 开关与允许域;
  • 单设备请求和全设备请求的限流间隔;
  • 属性映射是否默认启用、是否包含原始数据。

7. 限流模块(RateLimiter)

  • 职责:
  • 防止外部系统高频访问导致网关负载过高或设备查询过于频繁。
  • 功能点:
  • 为每个“限流 Key”(如设备号或 __all_devices__)记录最近访问时间。
  • 提供 checkLimit(key, interval) 方法:
    • 若距离上一次访问小于设定间隔,则拒绝请求并返回需要等待的剩余时间;
    • 否则更新访问时间并允许请求。

8. MQTT 通讯模块

  • 职责:
  • 按配置与 MQTT Broker 建立连接;
  • 在接收到透析机数据后,将数据发布到配置的 Topic。
  • 功能点:
  • 连接参数(地址、端口、用户名密码、重连间隔等)全部可配置。
  • 通过 enabled 标志控制是否启用 MQTT 功能。
  • 主题规则:{前缀}/{设备序列号},前缀可配置。
  • 消息内容包含:
    • 解析后的完整数据对象;
    • 设备 ID(如 IP:Port);
    • 发送时间戳。

9. 阿里云物联网对接模块(可选)

  • 职责:
  • 根据设备序列号从后端服务获取阿里云设备三元组;
  • 使用阿里云 SDK 建立到物联网平台的连接;
  • 在设备状态有效后,按阿里云物模型上报属性。
  • 功能点:
  • 通过配置中的 enabled 控制是否启用阿里云对接。
  • 仅当设备握手完成并收到有效数据时才发起三元组获取与阿里云连接。
  • 支持错误处理与重试日志记录。

10. 日志与监控模块

  • 职责:
  • 统一记录系统运行日志,便于问题排查与运行监控。
  • 功能点:
  • 记录:
    • 设备连接/断开;
    • 报文接收情况(原始数据、完整报文、异常数据);
    • 缓存读写操作;
    • HTTP 请求、限流事件;
    • MQTT/阿里云连接状态与错误。
  • 支持按天滚动日志文件(可选)。

四、配置与可定制项

1. 通讯与服务配置

  • TCP 监听端口、IP。
  • HTTP 服务开关、端口、地址、CORS 设置。
  • MQTT 连接参数、主题前缀、开关。
  • 阿里云接入参数和开关。

2. 业务与安全策略

  • 心跳间隔、重试间隔、设备超时时间。
  • HTTP 单设备与全设备查询的限流间隔。
  • 属性映射默认开关、是否包含原始数据。

3. 物模型与字段映射

  • 通过物模型配置文件(如 schema.json)统一定义:
  • 每个内部字段(A/B/C 等)的含义、名称、类型等;
  • 可扩展字段(例如增加 IP、警告信息等)。

五、并发压测(50 台透析机)

可使用内置脚本模拟 50 台设备并发连接并持续发送 0x1F/0x26/0x29 三类报文,用于提前验证网关稳定性。

1)启动网关

npm run start

2)执行 50 台并发压测(默认 120 秒)

npm run stress:50

3)可选参数(环境变量)

$env:DEVICE_COUNT="50"
$env:DURATION_SEC="180"
$env:INTERVAL_MS="1000"
$env:TCP_HOST="127.0.0.1"
$env:TCP_PORT="19000"
npm run stress:50

参数说明:
- DEVICE_COUNT:并发设备数(默认 50
- DURATION_SEC:压测持续时间秒数(默认 120
- INTERVAL_MS:每台设备发送运行参数帧间隔(默认 1000ms
- ALARM_EVERY:每 N 个发送周期插入报警帧(默认 30
- BP_EVERY:每 N 个发送周期插入血压帧(默认 15

六、本地日志审计(Winston)

项目已接入 winston + 按天滚动日志,默认日志目录由 config.log.dir 控制(默认 ../logs)。

日志文件:
- gateway-YYYY-MM-DD.log:全量业务日志(连接、原始报文、解析、上报)
- gateway-error-YYYY-MM-DD.log:错误日志

关键追踪事件:
- Device connected:记录连接时间与 ip:port
- Device identified:将连接绑定到机器编号(deviceNumber
- Raw TCP data received:记录原始十六进制报文
- Dialysis frame parsed / Dialysis frame payload:记录解析结果
- MQTT publish success / Aliyun postProps success:记录上报成功
- Device disconnected:记录断开时间、在线时长、总收包字节、总帧数

Windows 下按机器号查询示例:

Get-Content .\logs\gateway-$(Get-Date -Format yyyy-MM-dd).log | Select-String "6220903393"