From c677e60715d12d3a6ecd8a3d019b101f1fb436fe Mon Sep 17 00:00:00 2001
From: chenyc <501753378@qq.com>
Date: 星期一, 11 五月 2026 17:01:47 +0800
Subject: [PATCH] 提交部署
---
DEPLOY.md | 418 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 418 insertions(+), 0 deletions(-)
diff --git a/DEPLOY.md b/DEPLOY.md
new file mode 100644
index 0000000..6583d44
--- /dev/null
+++ b/DEPLOY.md
@@ -0,0 +1,418 @@
+# JMS 透析机 TCP 联机服务 — 实施部署文档
+
+## 1. 系统概述
+
+JMS 联机服务用于管理与监控多台 **GC-110N 透析设备**。通过持久 TCP 长连接 + 定时 K 指令轮询,实时采集 32 项治疗参数,经 MQTT / 阿里云 IoT 上传至云端,并提供本地 Web 监控大屏。
+
+```
+┌──────────┐ TCP:10001 ┌─────────────────┐ MQTT ┌──────────────┐
+│ GC-110N │←──────────────→│ jms-connection │───────────→│ MQTT Broker │
+│ 透析机 1 │ K 轮询 (10s) │ -service │ └──────────────┘
+└──────────┘ │ │
+ ··· │ dashboard:3100 │ HTTP ┌──────────────┐
+┌──────────┐ │ ← 浏览器访问 │───────────→│ 阿里云 IoT │
+│ GC-110N │←──────────────→│ │ postProps │ (三元组API) │
+│ 透析机 N │ └─────────────────┘ └──────────────┘
+```
+
+## 2. 环境要求
+
+| 项目 | 要求 |
+|------|------|
+| **操作系统** | 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 端口 |
+
+### 2.1 检查 Node.js 版本
+
+```bash
+node -v # 应输出 v18.x 或 v20.x
+npm -v # 应输出 9.x 或 10.x
+```
+
+### 2.2 安装 Node.js(如未安装)
+
+**Ubuntu/Debian:**
+```bash
+curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
+sudo apt-get install -y nodejs
+```
+
+**CentOS/RHEL:**
+```bash
+curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
+sudo yum install -y nodejs
+```
+
+**Windows:**
+从 https://nodejs.org 下载 LTS 安装包,勾选「Add to PATH」。
+
+## 3. 部署步骤
+
+### 3.1 获取代码
+
+```bash
+# 将部署包解压或从 Git 拉取
+cd /opt
+tar -xzf jms-connection-service.tar.gz -C /opt/
+# 或: git clone <repo-url> /opt/jms-connection-service
+
+cd /opt/jms-connection-service
+```
+
+### 3.2 安装依赖
+
+```bash
+npm install --production
+```
+
+> 仅安装生产依赖(`dependencies`),不安装 devDependencies。
+
+### 3.3 配置
+
+复制并修改配置文件:
+
+```bash
+# 如无可直接编辑 config.json(已内置在部署包中)
+vi config.json
+```
+
+详细配置项说明见 [第 4 节](#4-配置说明)。
+
+### 3.4 验证连通性
+
+在启动服务前,确认服务器能连通 GC-110N 设备:
+
+```bash
+# 测试 TCP 端口(替换为实际 IP 和端口)
+nc -zv 192.168.160.1 10001
+# 或 Windows:
+# Test-NetConnection -ComputerName 192.168.160.1 -Port 10001
+```
+
+### 3.5 启动服务
+
+```bash
+# 前台运行(调试用)
+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
+```
+
+### 3.6 访问监控面板
+
+浏览器打开 `http://<服务器IP>:3100`,可看到设备连接状态、实时数据和上传状态。
+
+## 4. 配置说明
+
+配置文件为根目录下的 `config.json`,格式如下:
+
+```jsonc
+{
+ // ── 全局参数 ──
+ "pollIntervalMs": 10000, // K 轮询间隔(毫秒),默认 10000 = 10s
+ "connectTimeoutMs": 5000, // TCP 握手超时(毫秒)
+ "reconnectBaseMs": 3000, // 重连退避基数(毫秒)
+ "reconnectMaxMs": 60000, // 重连退避上限(毫秒),实际延迟 = min(base*2^(n-1), max)
+ "logDir": "./logs", // 日志目录(相对路径基于项目根目录)
+ "logRetentionDays": 30, // 日志保留天数
+ "dashboardPort": 3100, // 监控大屏 HTTP 端口
+
+ // ── MQTT 上传(可选) ──
+ "mqtt": {
+ "enabled": false, // 是否启用 MQTT 上传
+ "brokerUrl": "mqtt.ihemodialysis.com", // MQTT Broker 地址(不含协议前缀)
+ "port": 62283, // MQTT 端口
+ "username": "data", // 认证用户名
+ "password": "data#2018", // 认证密码
+ "reconnectPeriod": 5000, // MQTT 重连间隔(毫秒)
+ "clientCode": "CLIENT9227100800901fcKB", // 客户端标识
+ "defaultTopicPrefix": "touxiji", // 默认 Topic 前缀,发布 topic = {prefix}/{deviceNo}
+ "qos": 1 // MQTT QoS 级别
+ },
+
+ // ── 阿里云 IoT 上传(可选) ──
+ "aliyun": {
+ "enabled": true, // 是否启用阿里云上传
+ "autoRegister": true, // 是否自动注册设备(三元组不存在时自动创建)
+ "tupleApiBaseUrl": "https://things.icoldchain.cn/", // 三元组 API 地址
+ "tupleApiPath": "device/info/getAliyunDeviceSecret", // 三元组 API 路径
+ "tupleRetryCooldownMs": 60000 // 三元组请求失败后冷却时间(毫秒)
+ },
+
+ // ── 设备列表 ──
+ "devices": [
+ {
+ "ip": "192.168.160.1", // 设备 IP 地址(必填)
+ "port": 10001, // 设备 TCP 端口(必填,GC-110N 默认 10001)
+ "serialNumber": "xy123", // 设备序列号(必填,用于上传标识)
+ "enabled": true // 是否启用(false 则跳过此设备)
+ }
+ // 可添加多台设备...
+ ]
+}
+```
+
+### 4.1 重连退避说明
+
+服务使用指数退避策略处理断线重连:
+
+| 断开次数 | 延迟时间(base=3000, max=60000) |
+|----------|--------------------------------|
+| 第 1 次 | 3s |
+| 第 2 次 | 6s |
+| 第 3 次 | 12s |
+| 第 4 次 | 24s |
+| 第 5 次 | 48s |
+| 第 6 次+ | 60s(达到上限) |
+
+连接成功后计数器重置。
+
+### 4.2 设备配置示例
+
+```json
+"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 }
+]
+```
+
+## 5. 运行管理
+
+### 5.1 PM2 常用命令
+
+```bash
+pm2 status # 查看进程状态
+pm2 logs jms-connection-service # 查看实时日志
+pm2 restart jms-connection-service # 重启服务
+pm2 stop jms-connection-service # 停止服务
+pm2 delete jms-connection-service # 从 PM2 移除
+```
+
+### 5.2 日志查看
+
+日志文件位于 `logDir` 配置的目录中(默认 `./logs`),按天滚动:
+
+```
+logs/
+├── service.2026-05-10.log
+├── service.2026-05-11.log
+└── service.2026-05-12.log # 最多保留 30 天
+```
+
+日志中的关键符号:
+
+| 符号 | 含义 |
+|------|------|
+| `→` | 发送 K 请求 |
+| `←` | 收到 K 响应(含原始报文) |
+| `✓` | TCP 连接成功 / 上传通道连接成功 |
+| `✂` | TCP 断开 |
+| `↻` | 计划重连 |
+| `↑` | 上传成功 |
+| `✗` | 错误 |
+| `!` | 警告 |
+
+### 5.3 优雅停止
+
+```bash
+# PM2 方式
+pm2 stop jms-connection-service
+
+# 直接进程方式(发送 SIGINT)
+kill -2 $(pgrep -f "node index.js")
+```
+
+服务会依次关闭:设备连接 → 上传模块 → Dashboard → 日志清理定时器。
+
+## 6. 网络与防火墙
+
+### 6.1 出站连接
+
+服务作为 TCP 客户端,需要访问以下目标:
+
+| 目标 | 协议 | 端口 | 用途 |
+|------|------|------|------|
+| GC-110N 设备 IP | TCP | 10001(可配置) | K 指令轮询 |
+| MQTT Broker | TCP | 62283(可配置) | MQTT 上传 |
+| 阿里云 IoT SDK | TCP | 443 (TLS) | 阿里云属性上报 |
+| 三元组 API | HTTPS | 443 | 获取设备三元组 |
+
+### 6.2 入站连接
+
+| 来源 | 协议 | 端口 | 用途 |
+|------|------|------|------|
+| 浏览器(局域网) | HTTP | 3100(可配置) | 监控大屏 |
+| 浏览器(局域网) | WebSocket | 3100(同 HTTP) | 实时数据推送 |
+
+### 6.3 防火墙配置示例(Linux iptables)
+
+```bash
+# 允许 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
+
+# 出站一般默认为 ACCEPT,无需额外配置
+```
+
+### 6.4 Windows 防火墙
+
+```powershell
+# 允许 Dashboard 端口入站
+New-NetFirewallRule -DisplayName "JMS Dashboard" -Direction Inbound -Protocol TCP -LocalPort 3100 -Action Allow
+```
+
+## 7. 监控面板使用
+
+### 7.1 面板概览
+
+访问 `http://<服务器IP>:3100` 进入监控大屏:
+
+- **顶部状态栏**:协议版本、WebSocket 连接状态、轮询间隔
+- **汇总卡片**:设备总数、在线数、数据正常数、异常数、MQTT/阿里云上传状态、最近上传结果
+- **设备列表**:每台设备的 IP、序列号、连接状态、最后数据时间、最后上传时间、字段数、重连次数、错误信息
+
+### 7.2 查看设备详情
+
+点击设备行可展开详情面板,显示:
+
+- 32 项治疗参数的实时值(字段 ID、中文名称、数值、单位)
+- 原始 K 格式报文(如 `K0000A00010B00005...`)
+
+再次点击收起。
+
+### 7.3 状态指示灯
+
+| 颜色 | 含义 |
+|------|------|
+| 🟢 绿色 | 在线 / 正常 |
+| 🟡 黄色 | 连接中 |
+| 🔵 蓝色 | 等待轮询 |
+| 🔴 红色 | 断线 / 异常 |
+| ⚫ 灰色 | 已禁用 / 等待 |
+
+## 8. 常见问题排查
+
+### 8.1 设备显示「断线」
+
+1. **检查网络连通性**:`ping <设备IP>` 和 `nc -zv <设备IP> <端口>`
+2. **检查设备是否开机**:GC-110N 设备需处于治疗或待机状态
+3. **检查防火墙**:确认服务器到设备的 TCP 端口未被拦截
+4. **查看日志**:`logs/service.YYYY-MM-DD.log` 搜索 `✂` 和 `✗`
+
+### 8.2 收不到数据 / 字段数为 0
+
+1. 确认设备已进入治疗状态(待机状态下 K 指令返回数据可能有限)
+2. 查看日志中 `←` 行,检查原始报文格式是否正确(应以 `K` 开头 + 4 位状态码)
+3. 确认设备固件支持 K 格式协议
+
+### 8.3 阿里云上传失败
+
+1. **三元组获取失败**:检查 `aliyun.tupleApiBaseUrl` 能否从服务器访问(`curl <url>`)
+2. **属性上报超时**:检查服务器到阿里云 IoT 的 443 端口连通性
+3. **设备未注册**:设置 `aliyun.autoRegister: true` 自动注册,或先在阿里云 IoT 平台创建设备
+4. **冷却期**:三元组请求失败后进入 60s 冷却期,期间不重试,查看日志 `tuple` 事件
+
+### 8.4 MQTT 上传不工作
+
+1. 确认 `mqtt.enabled: true`
+2. 检查 MQTT Broker 地址和端口是否可达
+3. 确认用户名密码正确
+4. Dashboard 的 MQTT 卡片会显示当前连接状态
+
+### 8.5 Dashboard 打不开
+
+1. 确认 `dashboardPort` 未被占用:`netstat -tlnp | grep 3100`
+2. 确认防火墙允许对应端口入站
+3. 确认服务已正常启动(查看控制台输出)
+
+### 8.6 日志文件过大
+
+服务内置了日志清理机制,每小时检查一次并删除超过保留天数的日志。如需手动清理:
+
+```bash
+# 删除 30 天前的日志
+find ./logs -name "*.log" -mtime +30 -delete
+```
+
+## 9. 目录结构
+
+```
+jms-connection-service/
+├── index.js # 入口文件
+├── config.json # 配置文件 ★
+├── package.json # 依赖声明
+├── lib/
+│ ├── logger.js # 日志模块(按天滚动,控制台彩色 + 文件纯文本)
+│ ├── data-cache.js # 内存数据缓存(Map<ip, deviceData>)
+│ ├── device-manager.js # 设备管理(遍历 config.devices 创建连接)
+│ ├── device-connection.js # 单设备 TCP 长连接 + K 轮询 + 重连
+│ ├── protocol.js # GC-110N K 格式解析器
+│ └── 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 # 监控大屏单页
+```
+
+## 10. 附录:GC-110N K 格式字段表
+
+| 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 |
--
Gitblit v1.8.0