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

JHM 服务生产实施部署文档

1. 目标

本文档用于指导 JHM 服务在生产环境中的打包、部署、配置、联调和验收。

当前服务能力包括:

  • 透析机 EE 55 固定帧协议解析
  • 血压计 AA 55 变长协议解析
  • MQTT 上报
  • 阿里云物模型上报
  • 批量聚合发送
  • 血压触发的整包立即发送

2. 打包产物

在项目根目录执行:

npm run build

如果只需要 Windows 包:

npm run build:win

如果只需要 Linux 包:

npm run build:linux

打包完成后生成目录:

dist/
  生产实施部署文档.md
  win-x64/
    jhm-service.exe
    生产实施部署文档.md
    runtime/
      config.json
      alModel.json
      生产实施部署文档.md
    logs/
    service/
      install-service.ps1
      uninstall-service.ps1
  linux-x64/
    jhm-service
    生产实施部署文档.md
    runtime/
      config.json
      alModel.json
      生产实施部署文档.md
    logs/
    service/
      install-service.sh
      uninstall-service.sh
      jhm-service.service.tpl

说明:

  • runtime/ 是现场主要维护目录。
  • logs/ 为运行日志目录。
  • service/ 为系统服务安装脚本模板。
  • 打包脚本会先清理旧的 build/dist/ 目录。

3. 部署前检查

部署前确认以下信息已准备完成:

  • 目标服务器操作系统和架构是否正确
  • 目标服务器开放了业务监听端口
  • 透传盒子目标 TCP 地址和端口已配置正确
  • devices[].ip 与服务端实际看到的设备来源 IP 一致
  • MQTT 或阿里云连接参数已确认可用
  • alModel.json 与平台物模型保持一致
  • 现场是否需要血压时间字段 M
  • 现场是否需要“血压触发整包立即发送”

4. 配置文件说明

主要配置文件:

runtime/config.json

推荐配置结构如下:

{
  "send": {
    "mode": "batch",
    "flushIntervalMs": 60000,
    "alignToMinute": true,
    "includeDeviceIdField": true,
    "deviceIdField": "n",
    "publishOnShutdown": true,
    "channels": ["aliyun"]
  },
  "logging": {
    "enabled": true,
    "console": true,
    "dir": "./logs",
    "filePrefix": "jhm-service",
    "level": "info"
  },
  "tcp": {
    "host": "0.0.0.0",
    "port": 9000,
    "maxConnections": 100,
    "socketTimeoutMs": 120000,
    "keepAlive": true,
    "keepAliveDelayMs": 10000,
    "noDelay": true,
    "backlog": 128,
    "maxBufferBytes": 8192
  },
  "mqtt": {
    "protocol": "mqtt",
    "host": "mqtt.ihemodialysis.com",
    "port": 62283,
    "username": "data",
    "password": "data#2018",
    "defaultTopicPrefix": "touxiji"
  },
  "aliyun": {
    "enabled": true,
    "tupleApiBaseUrl": "https://things.icoldchain.cn",
    "tupleApiPath": "/device/info/getAliyunDeviceSecret",
    "autoRegister": true,
    "registerRetryMs": 60000,
    "connectTimeoutMs": 15000
  },
  "protocol": {
    "alModelPath": "./alModel.json",
    "bloodPressure": {
      "publishTime": true,
      "flushImmediately": true
    }
  },
  "devices": [
    {
      "deviceId": "JHM-001",
      "ip": "169.254.233.58",
      "name": "1号透析机"
    }
  ]
}

4.1 send

  • mode:发送模式,支持 batchimmediate
  • flushIntervalMs:批量发送周期,单位毫秒,当前推荐 60000
  • alignToMinute:是否按整分钟对齐发送
  • includeDeviceIdField:发送时是否在 payload 中带设备编号字段
  • deviceIdField:设备编号字段名,当前默认 n
  • publishOnShutdown:停机前是否补发一次缓存数据
  • channels:发送通道,可选 mqttaliyun

常见组合:

  • 只发 MQTT:["mqtt"]
  • 只发阿里云:["aliyun"]
  • 双通道发送:["mqtt", "aliyun"]

4.2 logging

  • enabled:是否写本地日志文件
  • console:是否输出控制台日志
  • dir:日志目录
  • filePrefix:日志文件名前缀
  • level:日志级别,支持 debuginfowarnerror

4.3 tcp

  • host:监听地址,生产推荐 0.0.0.0
  • port:TCP 监听端口
  • maxConnections:最大连接数
  • socketTimeoutMs:连接空闲超时时间
  • keepAlive:是否启用 KeepAlive
  • keepAliveDelayMs:KeepAlive 首次探测延迟
  • noDelay:是否关闭 Nagle 算法
  • backlog:监听队列长度
  • maxBufferBytes:单连接解码缓冲区上限

4.4 mqtt

  • protocol:通常填写 mqtt
  • host:Broker 地址
  • port:Broker 端口
  • username:用户名
  • password:密码
  • defaultTopicPrefix:Topic 前缀
  • topicTemplate:如使用模板模式,可替代默认前缀模式

默认 Topic 规则:

{defaultTopicPrefix}/{deviceId}

4.5 aliyun

  • enabled:是否启用阿里云
  • tupleApiBaseUrl:三元组接口基础地址
  • tupleApiPath:三元组接口路径
  • autoRegister:是否允许自动注册
  • registerRetryMs:三元组请求失败后的冷却重试时间
  • connectTimeoutMs:阿里云设备连接超时时间

4.6 protocol

  • alModelPath:物模型文件路径
  • bloodPressure.publishTime:是否上报血压时间字段 M
  • bloodPressure.flushImmediately:血压报文到达后是否立即触发一次整包发送

publishTime 规则:

  • true:上报 N/O/P/M
  • false:仅上报 N/O/P
  • 未配置时默认 true

flushImmediately 规则:

  • true:血压到达后,先缓存 N/O/P/M,再立即发送当前设备缓存中的整包物模型
  • false:血压仅进入缓存,继续等待定时批量发送
  • 未配置时默认 true

如果平台不接收血压时间字段,可配置:

{
  "protocol": {
    "alModelPath": "./alModel.json",
    "bloodPressure": {
      "publishTime": false,
      "flushImmediately": true
    }
  }
}

如果现场明确要求“只按分钟发送,不要血压即时触发”,可配置:

{
  "protocol": {
    "alModelPath": "./alModel.json",
    "bloodPressure": {
      "publishTime": true,
      "flushImmediately": false
    }
  }
}

4.7 devices

每台设备至少配置:

  • deviceId
  • ip
  • name

注意事项:

  • ip 必须与服务端实际看到的客户端来源 IP 完全一致
  • 如果经过 NAT,需要填写 NAT 后服务端可见的来源 IP
  • 如果现场使用备注字段,也建议同步补齐 name,便于日志识别

5. 发送行为说明

5.1 普通透析机指标

透析机指标默认先进入聚合器缓存,在批量模式下按 flushIntervalMs 周期整包发送。

5.2 血压报文

血压报文示例:

AA 55 0E BA 00 78 50 59 08 08 08 08 08 10

解析结果:

  • 00 78:收缩压 N
  • 50:舒张压 O
  • 59:脉搏 P
  • 后 5 个时间字节:时间 M

publishTime=true 时,血压指标示例:

{
  "N": 120,
  "O": 80,
  "P": 89,
  "M": "2026-04-15 09:30"
}

publishTime=false 时,血压指标示例:

{
  "N": 120,
  "O": 80,
  "P": 89
}

flushImmediately=true 时,行为如下:

  1. 血压数据先写入缓存。
  2. 立即触发一次当前设备的整包物模型发送。
  3. 原有 1 分钟批量发送机制继续保留,不冲突。

这样做的好处:

  • 血压结果更快到平台
  • 平台收到的仍然是完整物模型,不是单独的血压字段
  • 定时发送继续兜底,避免其他指标长时间不落地

6. 模拟与联调

项目内置 TCP 模拟器:

npm run start:simulator -- --host 127.0.0.1 --port 9000

说明:

  • 当前 start:simulator 默认会带透析机报文和血压报文混合发送
  • 如仅需发送血压,可执行 npm run start:simulator:bp

自定义血压参数示例:

npm run start:simulator -- --bp-systolic 135 --bp-diastolic 88 --bp-pulse 76

7. Windows 部署

建议目录:

C:\services\jhm\win-x64

试运行:

cd C:\services\jhm\win-x64
.\jhm-service.exe --config .\runtime\config.json

如需安装为服务,可使用:

cd .\service
.\install-service.ps1

卸载服务:

cd .\service
.\uninstall-service.ps1

8. Linux 部署

建议目录:

/opt/jhm/linux-x64

试运行:

cd /opt/jhm/linux-x64
chmod +x ./jhm-service
./jhm-service --config ./runtime/config.json

如需安装为 systemd 服务,可参考:

cd ./service
chmod +x ./install-service.sh ./uninstall-service.sh
./install-service.sh

9. 运行日志说明

当前服务运行日志统一输出中文,默认写入:

runtime/logs 或配置中的 logging.dir

重点关注以下日志:

  • TCP 监听成功
  • 设备连接和断开
  • 收到指标
  • 血压报文触发整包立即发送
  • MQTT 发布成功或失败
  • 阿里云属性上报成功或失败

10. 验收建议

部署完成后建议执行:

npm test
npm run verify:commands

现场重点确认:

  • TCP 监听正常
  • 设备接入 IP 匹配正常
  • 透析机 EE 55 报文解析正常
  • 血压计 AA 55 报文解析正常
  • 血压到达后是否按预期立即整包发送
  • 1 分钟批量发送是否仍正常执行
  • MQTT 或阿里云上报结果正常
  • 日志文件持续输出正常