# JHM 服务生产实施部署文档 ## 1. 目标 本文档用于指导 JHM 服务在生产环境中的打包、部署、配置、联调和验收。 当前服务能力包括: - 透析机 `EE 55` 固定帧协议解析 - 血压计 `AA 55` 变长协议解析 - MQTT 上报 - 阿里云物模型上报 - 批量聚合发送 - 血压触发的整包立即发送 ## 2. 打包产物 在项目根目录执行: ```powershell npm run build ``` 如果只需要 Windows 包: ```powershell npm run build:win ``` 如果只需要 Linux 包: ```powershell npm run build:linux ``` 打包完成后生成目录: ```text 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. 配置文件说明 主要配置文件: ```text runtime/config.json ``` 推荐配置结构如下: ```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`:发送模式,支持 `batch` 和 `immediate` - `flushIntervalMs`:批量发送周期,单位毫秒,当前推荐 `60000` - `alignToMinute`:是否按整分钟对齐发送 - `includeDeviceIdField`:发送时是否在 payload 中带设备编号字段 - `deviceIdField`:设备编号字段名,当前默认 `n` - `publishOnShutdown`:停机前是否补发一次缓存数据 - `channels`:发送通道,可选 `mqtt`、`aliyun` 常见组合: - 只发 MQTT:`["mqtt"]` - 只发阿里云:`["aliyun"]` - 双通道发送:`["mqtt", "aliyun"]` ### 4.2 `logging` - `enabled`:是否写本地日志文件 - `console`:是否输出控制台日志 - `dir`:日志目录 - `filePrefix`:日志文件名前缀 - `level`:日志级别,支持 `debug`、`info`、`warn`、`error` ### 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 规则: ```text {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` 如果平台不接收血压时间字段,可配置: ```json { "protocol": { "alModelPath": "./alModel.json", "bloodPressure": { "publishTime": false, "flushImmediately": true } } } ``` 如果现场明确要求“只按分钟发送,不要血压即时触发”,可配置: ```json { "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 血压报文 血压报文示例: ```text 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` 时,血压指标示例: ```json { "N": 120, "O": 80, "P": 89, "M": "2026-04-15 09:30" } ``` 当 `publishTime=false` 时,血压指标示例: ```json { "N": 120, "O": 80, "P": 89 } ``` 当 `flushImmediately=true` 时,行为如下: 1. 血压数据先写入缓存。 2. 立即触发一次当前设备的整包物模型发送。 3. 原有 1 分钟批量发送机制继续保留,不冲突。 这样做的好处: - 血压结果更快到平台 - 平台收到的仍然是完整物模型,不是单独的血压字段 - 定时发送继续兜底,避免其他指标长时间不落地 ## 6. 模拟与联调 项目内置 TCP 模拟器: ```powershell npm run start:simulator -- --host 127.0.0.1 --port 9000 ``` 说明: - 当前 `start:simulator` 默认会带透析机报文和血压报文混合发送 - 如仅需发送血压,可执行 `npm run start:simulator:bp` 自定义血压参数示例: ```powershell npm run start:simulator -- --bp-systolic 135 --bp-diastolic 88 --bp-pulse 76 ``` ## 7. Windows 部署 建议目录: ```powershell C:\services\jhm\win-x64 ``` 试运行: ```powershell cd C:\services\jhm\win-x64 .\jhm-service.exe --config .\runtime\config.json ``` 如需安装为服务,可使用: ```powershell cd .\service .\install-service.ps1 ``` 卸载服务: ```powershell cd .\service .\uninstall-service.ps1 ``` ## 8. Linux 部署 建议目录: ```bash /opt/jhm/linux-x64 ``` 试运行: ```bash cd /opt/jhm/linux-x64 chmod +x ./jhm-service ./jhm-service --config ./runtime/config.json ``` 如需安装为 systemd 服务,可参考: ```bash cd ./service chmod +x ./install-service.sh ./uninstall-service.sh ./install-service.sh ``` ## 9. 运行日志说明 当前服务运行日志统一输出中文,默认写入: ```text runtime/logs 或配置中的 logging.dir ``` 重点关注以下日志: - TCP 监听成功 - 设备连接和断开 - 收到指标 - 血压报文触发整包立即发送 - MQTT 发布成功或失败 - 阿里云属性上报成功或失败 ## 10. 验收建议 部署完成后建议执行: ```powershell npm test npm run verify:commands ``` 现场重点确认: - TCP 监听正常 - 设备接入 IP 匹配正常 - 透析机 `EE 55` 报文解析正常 - 血压计 `AA 55` 报文解析正常 - 血压到达后是否按预期立即整包发送 - 1 分钟批量发送是否仍正常执行 - MQTT 或阿里云上报结果正常 - 日志文件持续输出正常