JMS 联机服务用于管理与监控多台 GC-110N 透析设备。通过持久 TCP 长连接 + 定时指令轮询,实时采集 32 项治疗参数,经 MQTT / 阿里云 IoT 上传至云端,并提供本地 Web 监控大屏。
┌──────────┐ TCP:10001 ┌─────────────────┐ MQTT ┌──────────────┐
│ GC-110N │←──────────────→│ jms-connection │───────────→│ MQTT Broker │
│ 透析机 1 │ 轮询 (10s) │ -service │ └──────────────┘
└──────────┘ │ │
··· │ dashboard:3100 │ HTTP ┌──────────────┐
┌──────────┐ │ ← 浏览器访问 │───────────→│ 阿里云 IoT │
│ GC-110N │←──────────────→│ │ postProps │ (三元组API) │
│ 透析机 N │ └─────────────────┘ └──────────────┘
| 方式 | 适用场景 | 是否需要 Node.js |
|---|---|---|
| 可执行程序部署(推荐) | 实施部署、生产环境 | 不需要 |
| 源码部署 | 开发调试、需修改源码 | 需要 Node.js ≥ 18.x |
两种方式效果一致。可执行程序已将 Node.js 运行时与依赖打包,省去环境安装步骤。
| 项目 | 要求 |
|---|---|
| 操作系统 | Windows Server 2016+ / Windows 10+ 或 Linux(Ubuntu 20.04+ / CentOS 7+) |
| 内存 | ≥ 256 MB(本服务占用 ~80 MB) |
| 磁盘 | ≥ 1 GB(含日志滚动保留 30 天) |
| 网络 | 需与 GC-110N 设备在同一局域网,或能通过路由访问设备 TCP 端口 |
发布包位于项目 dist/ 目录(或由开发人员交付):
dist/
├── jms-connection-service-windows.zip # Windows 部署包(约 18 MB)
├── jms-connection-service-linux/ # Linux 部署目录(可自行 tar 打包)
└── jms-connection-service-windows/ # Windows 部署目录
Windows 实施人员:解压 jms-connection-service-windows.zip 到目标目录(如 C:\JMS\)。
Linux 实施人员:将 jms-connection-service-linux/ 目录整体拷贝到目标路径(如 /opt/jms-connection-service/)。
jms-connection-service-windows/ # Linux 对应目录类似
├── jms-connection-service-windows.exe # 主程序(Linux 无 .exe 后缀)
├── config.json # 配置文件 ★
├── logs/ # 日志目录(自动创建)
└── README.txt # 简要说明
编辑 config.json,必改项:
devices — 填写实际设备的 IP、端口、序列号mqtt.enabled / aliyun.enabled — 按需开启上传通道详细配置项说明见 第 5 节。
在启动服务前,确认服务器能连通 GC-110N 设备:
# Windows PowerShell:
Test-NetConnection -ComputerName 192.168.160.1 -Port 10001
# Linux:
nc -zv 192.168.160.1 10001
Windows(前台运行):
C:\JMS\jms-connection-service-windows.exe
Windows(注册为系统服务,开机自启,以管理员身份运行):
sc create JMSConnection binPath= "C:\JMS\jms-connection-service-windows.exe" start= auto
sc start JMSConnection
:: 停止: sc stop JMSConnection
:: 删除: sc delete JMSConnection
Linux(前台运行):
chmod +x jms-connection-service-linux
./jms-connection-service-linux
Linux(后台运行,使用 PM2):
npm install -g pm2 # PM2 本身需要 Node.js
pm2 start ./jms-connection-service-linux --name jms-connection-service
pm2 save
pm2 startup # 设置开机自启
Linux(使用 systemd,见 6.1 节)
浏览器打开 http://<服务器IP>:3100。
Ctrl + Csc stop JMSConnectionpm2 stop jms-connection-service适用于开发调试或需修改源码的场景。
| 项目 | 要求 |
|---|---|
| 操作系统 | Linux(推荐 Ubuntu 20.04+ / CentOS 7+)或 Windows Server 2016+ |
| Node.js | ≥ 18.x(推荐 20 LTS) |
| npm | ≥ 9.x(随 Node.js 附带) |
| 内存 | ≥ 256 MB(本服务占用 ~80 MB) |
| 磁盘 | ≥ 1 GB(日志滚动保留 30 天) |
| 网络 | 需与 GC-110N 设备在同一局域网,或能通过路由访问设备 TCP 端口 |
Ubuntu/Debian:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
CentOS/RHEL:
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo yum install -y nodejs
Windows: 从 https://nodejs.org 下载 LTS 安装包,勾选「Add to PATH」。
验证安装:
node -v # 应输出 v18.x 或 v20.x
npm -v # 应输出 9.x 或 10.x
cd /opt
git clone <repo-url> /opt/jms-connection-service
# 或解压源码包: tar -xzf jms-connection-service.tar.gz -C /opt/
cd /opt/jms-connection-service
npm install --production
仅安装生产依赖(
dependencies),不安装 devDependencies。
vi config.json
详细配置项说明见 第 5 节。
# 前台运行(调试用)
node index.js
# 后台运行(生产推荐,使用 PM2)
npm install -g pm2
pm2 start index.js --name jms-connection-service
pm2 save
pm2 startup
启动成功输出:
配置校验通过: 1/1 台设备启用
联机服务启动
日志目录: /opt/jms-connection-service/logs 保留: 30 天
轮询间隔: 10s 重连退避: 3s~60s
Dashboard 已启动: http://0.0.0.0:3100
联机服务已启动 → Dashboard: http://localhost:3100
浏览器打开 http://<服务器IP>:3100。
配置文件为 config.json(位于程序同目录),格式:
{
// ── 全局参数 ──
"pollIntervalMs": 10000, // 轮询间隔(毫秒),默认 10s
"connectTimeoutMs": 5000, // TCP 握手超时(毫秒)
"reconnectBaseMs": 3000, // 重连退避基数(毫秒)
"reconnectMaxMs": 60000, // 重连退避上限(毫秒)
"logDir": "./logs", // 日志目录(相对路径基于程序工作目录)
"logRetentionDays": 30, // 日志保留天数
"dashboardPort": 3100, // 监控大屏 HTTP 端口
// ── MQTT 上传(可选) ──
"mqtt": {
"enabled": false,
"brokerUrl": "mqtt.ihemodialysis.com",
"port": 62283,
"username": "data",
"password": "data#2018",
"reconnectPeriod": 5000,
"clientCode": "CLIENT9227100800901fcKB",
"defaultTopicPrefix": "touxiji",
"qos": 1
},
// ── 阿里云 IoT 上传(可选) ──
"aliyun": {
"enabled": true,
"autoRegister": true,
"tupleApiBaseUrl": "https://things.icoldchain.cn/",
"tupleApiPath": "device/info/getAliyunDeviceSecret",
"tupleRetryCooldownMs": 60000
},
// ── 设备列表 ──
"devices": [
{
"ip": "192.168.160.1", // 设备 IP(必填)
"port": 10001, // 设备端口(必填,GC-110N 默认 10001)
"serialNumber": "xy123", // 序列号(必填)
"enabled": true // 是否启用
}
]
}
断线后使用指数退避,连接成功后计数器重置:
| 断开次数 | 延迟(base=3000, max=60000) |
|---|---|
| 第 1 次 | 3s |
| 第 2 次 | 6s |
| 第 3 次 | 12s |
| 第 4 次 | 24s |
| 第 5 次 | 48s |
| 第 6 次+ | 60s(达到上限) |
"devices": [
{ "ip": "192.168.1.101", "port": 10001, "serialNumber": "D001", "enabled": true },
{ "ip": "192.168.1.102", "port": 10001, "serialNumber": "D002", "enabled": true },
{ "ip": "192.168.1.103", "port": 10001, "serialNumber": "D003", "enabled": false }
]
创建 systemd 服务文件实现开机自启和进程守护:
sudo vi /etc/systemd/system/jms-connection.service
[Unit]
Description=JMS GC-110N Dialysis Connection Service
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/jms-connection-service
ExecStart=/opt/jms-connection-service/jms-connection-service-linux
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=jms-connection
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable jms-connection
sudo systemctl start jms-connection
# 常用命令
sudo systemctl status jms-connection # 查看状态
sudo systemctl restart jms-connection # 重启
sudo systemctl stop jms-connection # 停止
journalctl -u jms-connection -f # 查看日志
:: 创建服务(管理员权限)
sc create JMSConnection binPath= "C:\JMS\jms-connection-service-windows.exe" start= auto
:: 启动 / 停止 / 查询
sc start JMSConnection
sc stop JMSConnection
sc query JMSConnection
:: 删除服务(先停止)
sc stop JMSConnection
sc delete JMSConnection
pm2 status # 查看进程状态
pm2 logs jms-connection-service # 查看实时日志
pm2 restart jms-connection-service # 重启
pm2 stop jms-connection-service # 停止
pm2 delete jms-connection-service # 移除
日志按天滚动,位于 logDir 配置的目录(默认 ./logs):
logs/
├── service.2026-05-11.log
├── service.2026-05-12.log
└── service.2026-05-13.log # 最多保留 30 天
日志符号含义:
| 符号 | 含义 |
|---|---|
→ |
发送 K 请求 |
← |
收到 K 响应 |
✓ |
TCP 连接成功 / 上传通道就绪 |
✂ |
TCP 断开 |
↻ |
计划重连 |
↑ |
上传成功 |
✗ |
错误 |
! |
警告 |
服务收到 SIGINT / SIGTERM 后会依次关闭:设备连接 → 上传模块 → Dashboard → 日志清理定时器。
# PM2
pm2 stop jms-connection-service
# systemd
sudo systemctl stop jms-connection
# 直接进程
kill -2 $(pgrep -f "jms-connection-service")
| 目标 | 协议 | 端口 | 用途 |
|---|---|---|---|
| GC-110N 设备 | TCP | 10001(可配置) | 指令轮询 |
| MQTT Broker | TCP | 62283(可配置) | MQTT 上传 |
| 阿里云 IoT | TCP | 443 (TLS) | 属性上报 |
| 三元组 API | HTTPS | 443 | 获取设备凭证 |
| 来源 | 协议 | 端口 | 用途 |
|---|---|---|---|
| 局域网浏览器 | HTTP | 3100(可配置) | 监控大屏 |
| 局域网浏览器 | WebSocket | 3100 | 实时数据推送 |
# 允许内网访问 Dashboard
iptables -A INPUT -s 192.168.0.0/16 -p tcp --dport 3100 -j ACCEPT
iptables -A INPUT -p tcp --dport 3100 -j DROP
New-NetFirewallRule -DisplayName "JMS Dashboard" -Direction Inbound -Protocol TCP -LocalPort 3100 -Action Allow
访问 http://<服务器IP>:3100:
状态指示灯:
| 颜色 | 含义 |
|---|---|
| 🟢 绿色 | 在线 / 正常 |
| 🟡 黄色 | 连接中 |
| 🔵 蓝色 | 等待轮询 |
| 🔴 红色 | 断线 / 异常 |
| ⚫ 灰色 | 已禁用 |
ping <设备IP> 和 nc -zv <设备IP> <端口> 检查连通性logs/service.YYYY-MM-DD.log 搜索 ✂ 和 ✗← 行,确认收到设备报文(混淆格式可通过 node tools/decode-log.js --stdin 解码查看)aliyun.tupleApiBaseUrl 可达性:curl <url>aliyun.autoRegister: true 自动注册设备mqtt.enabled: truenetstat -tlnp | grep 3100chmod +xconfig.json 与可执行文件在同一目录jms-connection-service/
├── index.js # 入口文件
├── config.json # 配置文件 ★
├── package.json # 依赖声明
├── scripts/
│ └── build.js # 打包构建脚本
├── lib/
│ ├── logger.js # 日志模块(按天滚动)
│ ├── data-cache.js # 内存数据缓存(Map<ip, deviceData>)
│ ├── device-manager.js # 设备管理(遍历创建连接)
│ ├── device-connection.js # 单设备 TCP 长连接 + 轮询 + 重连
│ ├── protocol.js # GC-110N 协议解析器
│ └── upload/
│ ├── index.js # 上传总控(顺序:MQTT → 阿里云)
│ ├── mqtt-uploader.js # MQTT 单例客户端
│ ├── aliyun-uploader.js # 阿里云 IoT SDK 设备实例池
│ ├── tuple-api.js # 三元组 API HTTP 请求
│ └── field-mapper.js # GC-110N ID → 阿里云 identifier 映射
└── dashboard/
├── server.js # HTTP + WebSocket 服务
└── public/
└── index.html # 监控大屏单页
如需从源码重新打包可执行程序:
# 安装开发依赖(含 pkg)
npm install
# 打包 Windows + Linux
npm run build
# 仅打包 Windows
npm run build:win
# 仅打包 Linux
npm run build:linux
打包产物输出到 dist/ 目录:
dist/
├── jms-connection-service-windows.zip # Windows 部署包
├── jms-connection-service-windows/ # Windows 部署目录
└── jms-connection-service-linux/ # Linux 部署目录
打包使用 pkg 将 Node.js 运行时与应用代码合并为独立可执行文件。首次打包需下载 Node.js 二进制(~30 MB),后续打包使用缓存。
| ID | 中文名称 | 单位 | 宽度(字节) |
|---|---|---|---|
| A | 目标除水量 | L | 5 |
| B | 当前除水量 | L | 5 |
| C | 除水速度 | L/h | 5 |
| D | 血液流量 | mL/min | 5 |
| E | 注射器泵速度 | mL/h | 5 |
| F | 透析液温度 | ℃ | 5 |
| G | 透析液浓度 | mS/cm | 5 |
| H | 静脉压 | mmHg | 5 |
| I | 透析液压 | mmHg | 5 |
| J | TMP | mmHg | 5 |
| K | 治疗经过时间 | min | 5 |
| L | 透析液流量 | mL/min | 5 |
| a | 液温报警 | — | 1 |
| b | 浓度报警 | — | 1 |
| c | 静脉压报警 | — | 1 |
| d | 液压报警 | — | 1 |
| e | TMP 报警 | — | 1 |
| f | 气泡检测报警 | — | 1 |
| g | 漏血报警 | — | 1 |
| h | 其他报警 | — | 1 |
| M | 治疗中标志 | — | 1 |
| N | 治疗模式 | — | 1 |
| O | 目标补液量 | L | 5 |
| P | 当前补液量 | L | 5 |
| Q | 补液速度 | L/h | 5 |
| R | 补液温度 | ℃ | 5 |
| S | 血压测量时刻 | HHMMSS | 6(变长) |
| T | 收缩压 | mmHg | 5 |
| U | 舒张压 | mmHg | 5 |
| V | 脉搏 | bpm | 5 |
| i | 血压报警 | — | 1 |
| W | 注射器泵累计量 | mL | 5 |