From a85e047fa3f1a04aca4aeb079f06db69a96c8838 Mon Sep 17 00:00:00 2001
From: chenyc <501753378@qq.com>
Date: 星期三, 10 十二月 2025 23:33:25 +0800
Subject: [PATCH] gx完成
---
HTTP_API_INTEGRATION_GUIDE.md | 2
index.js | 17
Strholp.js | 5
mqtt.json | 2
aliyun.json | 2
convert_to_word.py | 220 ++++++++++++++
配置文件说明.md | 593 +++++++++++++++++++++++++++++++++++++++
chenyc.ps | 27 +
httpConfig.json | 2
homeConfig.json | 4
10 files changed, 863 insertions(+), 11 deletions(-)
diff --git a/HTTP_API_INTEGRATION_GUIDE.md b/HTTP_API_INTEGRATION_GUIDE.md
index de1acd8..3019aec 100644
--- a/HTTP_API_INTEGRATION_GUIDE.md
+++ b/HTTP_API_INTEGRATION_GUIDE.md
@@ -76,8 +76,6 @@
# 获取原始格式数据
curl "http://localhost:8080/api/device/data?deviceNumber=D001"
-# 获取映射格式数据(推荐)
-curl "http://localhost:8080/api/device/data?deviceNumber=D001&mapped=true"
```
**响应示例(映射格式)**:
diff --git a/Strholp.js b/Strholp.js
index d13ab15..a54fdfe 100644
--- a/Strholp.js
+++ b/Strholp.js
@@ -10,7 +10,7 @@
var s = time.getSeconds();
return y + '-' + add0(m) + '-' + add0(d) + ' ' + add0(h) + ':' + add0(mm) + ':' + add0(s);
}
-function strToObj(str) {
+function strToObj(str, ipAddress) {
var data = {
A: str.substring(6, 11),
B: str.substring(12, 17),
@@ -68,7 +68,8 @@
C54: str.substring(259, 264),
C55: str.substring(265, 266),
suedtime: format(new Date().getTime()),
- deviceType: '东丽'
+ deviceType: '东丽',
+ IPAddress: ipAddress || ''
}
return data
}
diff --git a/aliyun.json b/aliyun.json
index 0e642af..de12da8 100644
--- a/aliyun.json
+++ b/aliyun.json
@@ -1,4 +1,4 @@
{
- "enabled": false,
+ "enabled": true,
"autoRegister": true
}
\ No newline at end of file
diff --git a/chenyc.ps b/chenyc.ps
new file mode 100644
index 0000000..a3431c7
--- /dev/null
+++ b/chenyc.ps
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# 设置变量
+user="chenyc"
+start_date="2025-01-01T00:00:00"
+end_date="2025-12-30T23:59:59"
+
+# 检查当前目录是否是Git仓库
+if ! git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
+ echo "当前目录不是一个Git仓库。请在Git仓库的根目录下运行此脚本。"
+ exit 1
+fi
+
+# 获取提交次数
+commit_count=$(git log --author="$user" --since="$start_date" --until="$end_date" --pretty=oneline | wc -l)
+
+# 获取代码行数的变化
+lines_info=$(git log --author="$user" --since="$start_date" --until="$end_date" --pretty=tformat: --numstat | awk '{ add += $1; del += $2; net += $1 - $2 } END { printf "%s,%s,%s", add, del, net }')
+IFS=',' read lines_added lines_deleted lines_changed <<< "$lines_info"
+
+# 输出结果
+echo "日期: $start_date ~ $end_date"
+echo "用户: $user"
+echo "提交次数: $commit_count"
+echo "增加的代码行数: $lines_added"
+echo "删除的代码行数: $lines_deleted"
+echo "净变化的代码行数: $lines_changed"
diff --git a/convert_to_word.py b/convert_to_word.py
new file mode 100644
index 0000000..2159589
--- /dev/null
+++ b/convert_to_word.py
@@ -0,0 +1,220 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+将Markdown文档转换为Word格式
+"""
+
+import os
+from pathlib import Path
+
+try:
+ from docx import Document
+ from docx.shared import Pt, RGBColor, Inches
+ from docx.enum.text import WD_ALIGN_PARAGRAPH
+ from docx.oxml.ns import qn
+ from docx.oxml import OxmlElement
+except ImportError:
+ print("正在安装必要的库...")
+ os.system("pip install python-docx -q")
+ from docx import Document
+ from docx.shared import Pt, RGBColor, Inches
+ from docx.enum.text import WD_ALIGN_PARAGRAPH
+ from docx.oxml.ns import qn
+ from docx.oxml import OxmlElement
+
+import re
+from datetime import datetime
+
+class MarkdownToWord:
+ def __init__(self):
+ self.doc = Document()
+ self.setup_styles()
+
+ def setup_styles(self):
+ """设置文档样式"""
+ style = self.doc.styles['Normal']
+ style.font.name = '宋体'
+ style.font.size = Pt(11)
+
+ def add_heading(self, text, level=1):
+ """添加标题"""
+ self.doc.add_heading(text, level=level)
+
+ def add_paragraph(self, text=''):
+ """添加段落"""
+ if text:
+ p = self.doc.add_paragraph(text)
+ p_format = p.paragraph_format
+ p_format.space_before = Pt(6)
+ p_format.space_after = Pt(6)
+ p_format.line_spacing = 1.5
+
+ def add_table_from_markdown(self, lines, index):
+ """从Markdown表格创建Word表格"""
+ table_lines = []
+ i = index
+
+ # 收集表格行
+ while i < len(lines):
+ line = lines[i].strip()
+ if not line.startswith('|'):
+ break
+ table_lines.append(line)
+ i += 1
+
+ if len(table_lines) < 3:
+ return index
+
+ # 解析表头
+ header = table_lines[0].split('|')[1:-1]
+ header = [h.strip() for h in header]
+
+ # 创建表格
+ table = self.doc.add_table(rows=1, cols=len(header))
+ table.style = 'Light Grid Accent 1'
+
+ # 添加表头
+ hdr_cells = table.rows[0].cells
+ for i, cell_text in enumerate(header):
+ hdr_cells[i].text = cell_text
+ # 设置表头样式
+ for paragraph in hdr_cells[i].paragraphs:
+ for run in paragraph.runs:
+ run.font.bold = True
+ run.font.name = '宋体'
+
+ # 添加数据行(跳过分隔符行)
+ for line in table_lines[2:]:
+ cells = line.split('|')[1:-1]
+ cells = [c.strip() for c in cells]
+ row_cells = table.add_row().cells
+ for i, cell_text in enumerate(cells):
+ row_cells[i].text = cell_text
+ for paragraph in row_cells[i].paragraphs:
+ for run in paragraph.runs:
+ run.font.name = '宋体'
+
+ return i
+
+ def add_code_block(self, language, code):
+ """添加代码块"""
+ p = self.doc.add_paragraph()
+ p.paragraph_format.left_indent = Inches(0.25)
+ p.paragraph_format.space_before = Pt(6)
+ p.paragraph_format.space_after = Pt(6)
+
+ # 代码块背景
+ shading_elm = OxmlElement('w:shd')
+ shading_elm.set(qn('w:fill'), 'E8E8E8')
+ p._element.get_or_add_pPr().append(shading_elm)
+
+ # 添加语言标记
+ if language:
+ run = p.add_run(f'# {language}\n')
+ run.font.italic = True
+ run.font.size = Pt(9)
+
+ # 添加代码
+ run = p.add_run(code)
+ run.font.name = 'Courier New'
+ run.font.size = Pt(9)
+
+ def convert_markdown_file(self, input_path, output_path):
+ """转换Markdown文件为Word"""
+ print(f"正在读取: {input_path}")
+
+ with open(input_path, 'r', encoding='utf-8') as f:
+ lines = f.readlines()
+
+ print(f"文件包含 {len(lines)} 行")
+
+ i = 0
+ code_block = False
+ code_language = ''
+ code_lines = []
+
+ while i < len(lines):
+ line = lines[i].rstrip()
+
+ # 处理代码块
+ if line.startswith('```'):
+ if code_block:
+ # 结束代码块
+ self.add_code_block(code_language, '\n'.join(code_lines))
+ code_block = False
+ code_language = ''
+ code_lines = []
+ else:
+ # 开始代码块
+ code_block = True
+ code_language = line[3:].strip()
+ i += 1
+ continue
+
+ if code_block:
+ code_lines.append(line)
+ i += 1
+ continue
+
+ # 处理表格
+ if line.strip().startswith('|'):
+ self.add_table_from_markdown(lines, i)
+ # 跳过表格行
+ while i < len(lines) and lines[i].strip().startswith('|'):
+ i += 1
+ continue
+
+ # 处理标题
+ if line.startswith('###### '):
+ self.add_heading(line[7:], 6)
+ elif line.startswith('##### '):
+ self.add_heading(line[6:], 5)
+ elif line.startswith('#### '):
+ self.add_heading(line[5:], 4)
+ elif line.startswith('### '):
+ self.add_heading(line[4:], 3)
+ elif line.startswith('## '):
+ self.add_heading(line[3:], 2)
+ elif line.startswith('# '):
+ self.add_heading(line[2:], 1)
+
+ # 跳过分隔符
+ elif line.strip() in ['---', '***', '___']:
+ self.add_paragraph() # 空行
+
+ # 处理普通段落
+ elif line.strip():
+ self.add_paragraph(line)
+ else:
+ self.add_paragraph() # 空行
+
+ i += 1
+
+ # 保存Word文档
+ print(f"正在保存到: {output_path}")
+ self.doc.save(output_path)
+ print(f"✓ 转换完成!")
+
+ # 返回文件大小
+ if os.path.exists(output_path):
+ size = os.path.getsize(output_path) / 1024 # KB
+ print(f"✓ 文件大小: {size:.1f} KB")
+ return output_path
+
+ return None
+
+def main():
+ workspace = r"d:\gitData\dongli_SocketServer"
+
+ # 转换HTTP集成指南
+ converter = MarkdownToWord()
+ input_file = os.path.join(workspace, "HTTP_API_INTEGRATION_GUIDE.md")
+ output_file = os.path.join(workspace, "HTTP_API_INTEGRATION_GUIDE.docx")
+
+ if os.path.exists(input_file):
+ converter.convert_markdown_file(input_file, output_file)
+ else:
+ print(f"错误: 未找到文件 {input_file}")
+
+if __name__ == '__main__':
+ main()
diff --git a/homeConfig.json b/homeConfig.json
new file mode 100644
index 0000000..7a39df2
--- /dev/null
+++ b/homeConfig.json
@@ -0,0 +1,4 @@
+{
+ "socketPort": 10963,
+ "description": "Socket服务器监听端口"
+}
diff --git a/httpConfig.json b/httpConfig.json
index fe9d697..1033188 100644
--- a/httpConfig.json
+++ b/httpConfig.json
@@ -1,5 +1,5 @@
{
- "enabled": true,
+ "enabled": false,
"port": 8080,
"host": "0.0.0.0",
"cors": {
diff --git a/index.js b/index.js
index 0bcbd9e..9c2bac5 100644
--- a/index.js
+++ b/index.js
@@ -10,10 +10,12 @@
const mqttConfigPath = path.join(appPath, 'mqtt.json');
const aliyunConfigPath = path.join(appPath, 'aliyun.json');
const httpConfigPath = path.join(appPath, 'httpConfig.json');
+const homeConfigPath = path.join(appPath, 'homeConfig.json');
const mqttConfig = JSON.parse(fs.readFileSync(mqttConfigPath, 'utf8'));
-const aliyunConfig=JSON.parse(fs.readFileSync(aliyunConfigPath, 'utf8'))
+const aliyunConfig = JSON.parse(fs.readFileSync(aliyunConfigPath, 'utf8'));
const httpConfig = JSON.parse(fs.readFileSync(httpConfigPath, 'utf8'));
+const homeConfig = JSON.parse(fs.readFileSync(homeConfigPath, 'utf8'));
console.log(aliyunConfig)
@@ -67,7 +69,12 @@
}
handleDevice(socket) {
- const deviceId = socket.remoteAddress + ':' + socket.remotePort;
+ // 处理 IPv6 映射 IPv4 地址 (::ffff:127.0.0.1 -> 127.0.0.1)
+ let remoteAddress = socket.remoteAddress;
+ if (remoteAddress.startsWith('::ffff:')) {
+ remoteAddress = remoteAddress.slice(7); // 移除 ::ffff: 前缀
+ }
+ const deviceId = remoteAddress + ':' + socket.remotePort;
logger.info(`建立新连接: ${deviceId}`);
const deviceInfo = {
@@ -190,9 +197,11 @@
deviceInfo.lastAck = Date.now();
try {
- const masData = toModel(message);
+ const ipAddress = deviceId
+ const masData = toModel(message, ipAddress);
deviceInfo.iotDeviceNo = masData.n;
deviceInfo.masData = masData;
+
// ✅【新增】缓存数据到内存(按设备序号)
dataCache.setDeviceData(masData.n, masData);
@@ -325,7 +334,7 @@
manager.handleDevice(socket);
});
-const PORT = process.env.PORT || 10961;
+const PORT = homeConfig.socketPort || 10961;
server.listen(PORT, () => {
logger.info(`Socket 服务已启动,监听超级端口: ${PORT}`);
});
diff --git a/mqtt.json b/mqtt.json
index 787dc44..f9d4cbb 100644
--- a/mqtt.json
+++ b/mqtt.json
@@ -1,5 +1,5 @@
{
- "enabled": false,
+ "enabled": true,
"brokerUrl": "mqtt.ihemodialysis.com",
"port": 62283,
"username": "data",
diff --git "a/\351\205\215\347\275\256\346\226\207\344\273\266\350\257\264\346\230\216.md" "b/\351\205\215\347\275\256\346\226\207\344\273\266\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..29a5c98
--- /dev/null
+++ "b/\351\205\215\347\275\256\346\226\207\344\273\266\350\257\264\346\230\216.md"
@@ -0,0 +1,593 @@
+# 配置文件说明文档
+
+**版本**: v1.1.0
+**最后更新**: 2025-12-10
+
+---
+
+## 📋 目录
+
+1. [概述](#概述)
+2. [homeConfig.json](#homeconfigjson)
+3. [mqtt.json](#mqttjson)
+4. [httpConfig.json](#httpconfigjson)
+5. [aliyun.json](#aliyunjson)
+6. [schema.json](#schemajson)
+7. [常见问题](#常见问题)
+
+---
+
+## 概述
+
+系统使用多个 JSON 配置文件来管理不同模块的参数。所有配置文件都应该放在应用程序的根目录中。
+
+### 配置文件加载优先级
+
+```
+当前工作目录 (开发环境)
+ ↓
+可执行文件所在目录 (pkg 打包环境)
+ ↓
+硬编码默认值
+```
+
+### 环境变量覆盖
+
+某些配置可以通过环境变量覆盖:
+
+```bash
+# Socket 服务端口
+PORT=10961 npm start
+
+# HTTP 服务端口
+HTTP_PORT=8080 npm start
+```
+
+---
+
+## homeConfig.json
+
+**用途**: Socket 服务器和主服务配置
+
+**位置**: 应用程序根目录
+
+**优先级**: 环境变量 > homeConfig.json > 默认值
+
+### 完整配置示例
+
+```json
+{
+ "socketPort": 10961,
+ "description": "Socket服务器监听端口"
+}
+```
+
+### 配置字段说明
+
+| 字段 | 类型 | 默认值 | 说明 | 示例 |
+|------|------|--------|------|------|
+| `socketPort` | number | 10961 | Socket服务器监听的端口号 | 10961 |
+| `description` | string | - | 配置文件描述(可选) | Socket服务器监听端口 |
+
+### 使用方式
+
+```javascript
+// 在 index.js 中
+const homeConfig = JSON.parse(fs.readFileSync(homeConfigPath, 'utf8'));
+const PORT = process.env.PORT || homeConfig.socketPort || 10961;
+```
+
+### 修改示例
+
+```json
+{
+ "socketPort": 9999,
+ "description": "自定义Socket服务器监听端口"
+}
+```
+
+---
+
+## mqtt.json
+
+**用途**: MQTT 消息队列服务配置
+
+**位置**: 应用程序根目录
+
+**依赖包**: `mqtt@5.13.3`
+
+### 完整配置示例
+
+```json
+{
+ "enabled": true,
+ "brokerUrl": "mqtt://127.0.0.1:1883",
+ "clientId": "dialysis-server-01",
+ "username": "admin",
+ "password": "admin123",
+ "keepalive": 60,
+ "reconnectPeriod": 5000,
+ "defaultTopicPrefix": "device/data",
+ "qos": 1,
+ "retain": false
+}
+```
+
+### 配置字段说明
+
+| 字段 | 类型 | 默认值 | 说明 | 示例 |
+|------|------|--------|------|------|
+| `enabled` | boolean | true | 是否启用 MQTT 功能 | true/false |
+| `brokerUrl` | string | mqtt://127.0.0.1:1883 | MQTT Broker 服务器地址 | mqtt://192.168.1.100:1883 |
+| `clientId` | string | dialysis-server-01 | MQTT 客户端 ID(需唯一) | device-server-01 |
+| `username` | string | admin | MQTT 连接用户名 | mqtt_user |
+| `password` | string | admin123 | MQTT 连接密码 | secure_password_123 |
+| `keepalive` | number | 60 | 心跳间隔(秒) | 60 |
+| `reconnectPeriod` | number | 5000 | 重连间隔(毫秒) | 5000 |
+| `defaultTopicPrefix` | string | device/data | MQTT 主题前缀 | device/dialysis |
+| `qos` | number | 1 | QoS 级别(0/1/2) | 1 |
+| `retain` | boolean | false | 消息是否保留 | false |
+
+### 使用方式
+
+```javascript
+// 在 index.js 中
+const mqttConfig = JSON.parse(fs.readFileSync(mqttConfigPath, 'utf8'));
+
+if (mqttConfig.enabled) {
+ const topic = `${mqttConfig.defaultTopicPrefix}/${deviceNo}`;
+ publishMessage(topic, payload);
+}
+```
+
+### 常见场景
+
+#### 场景1:禁用 MQTT
+```json
+{
+ "enabled": false
+}
+```
+
+#### 场景2:使用云端 MQTT(如阿里云)
+```json
+{
+ "enabled": true,
+ "brokerUrl": "mqtt://mqtt.aliyuncs.com:1883",
+ "username": "xxxxx@instance123|securemode=2,signmethod=hmacsha256",
+ "password": "your_password",
+ "clientId": "device_client_id"
+}
+```
+
+---
+
+## httpConfig.json
+
+**用途**: HTTP API 服务器配置
+
+**位置**: 应用程序根目录
+
+### 完整配置示例
+
+```json
+{
+ "port": 8080,
+ "host": "0.0.0.0",
+ "cors": {
+ "enabled": true,
+ "origin": "*"
+ },
+ "rateLimit": {
+ "enabled": true,
+ "singleDeviceInterval": 5000,
+ "allDevicesInterval": 60000
+ },
+ "propertyMapping": {
+ "enabled": true,
+ "useEmbeddedSchema": true
+ },
+ "cache": {
+ "enabled": true
+ }
+}
+```
+
+### 配置字段说明
+
+#### 基础配置
+
+| 字段 | 类型 | 默认值 | 说明 | 示例 |
+|------|------|--------|------|------|
+| `port` | number | 8080 | HTTP 服务器监听端口 | 8080 |
+| `host` | string | 0.0.0.0 | 服务器绑定地址(0.0.0.0 表示所有网卡) | 127.0.0.1 |
+
+#### CORS 配置
+
+| 字段 | 类型 | 默认值 | 说明 | 示例 |
+|------|------|--------|------|------|
+| `cors.enabled` | boolean | true | 是否启用 CORS 跨域 | true |
+| `cors.origin` | string | * | 允许的来源(* 表示所有) | https://example.com |
+
+#### 限流配置
+
+| 字段 | 类型 | 默认值 | 说明 | 备注 |
+|------|------|--------|------|------|
+| `rateLimit.enabled` | boolean | true | 是否启用限流 | 生产环境建议启用 |
+| `rateLimit.singleDeviceInterval` | number | 5000 | 单个设备查询限流间隔(毫秒) | 同一设备 5 秒最多 1 次 |
+| `rateLimit.allDevicesInterval` | number | 60000 | 全局查询限流间隔(毫秒) | 所有设备 60 秒最多 1 次 |
+
+#### 属性映射配置
+
+| 字段 | 类型 | 默认值 | 说明 | 备注 |
+|------|------|--------|------|------|
+| `propertyMapping.enabled` | boolean | true | 是否启用属性映射 | 推荐启用 |
+| `propertyMapping.useEmbeddedSchema` | boolean | true | 是否使用内嵌 schema | false 时使用 schema.json |
+
+#### 缓存配置
+
+| 字段 | 类型 | 默认值 | 说明 | 备注 |
+|------|------|--------|------|------|
+| `cache.enabled` | boolean | true | 是否启用数据缓存 | 建议启用以提升性能 |
+
+### 使用方式
+
+```javascript
+// 在 httpServer.js 中
+const httpConfig = JSON.parse(fs.readFileSync(httpConfigPath, 'utf8'));
+const server = http.createServer((req, res) => {
+ if (httpConfig.cors.enabled) {
+ res.setHeader('Access-Control-Allow-Origin', httpConfig.cors.origin);
+ }
+});
+```
+
+### 修改示例
+
+#### 仅本地访问
+```json
+{
+ "port": 8080,
+ "host": "127.0.0.1",
+ "cors": {
+ "enabled": false
+ }
+}
+```
+
+#### 生产环境高性能配置
+```json
+{
+ "port": 8080,
+ "host": "0.0.0.0",
+ "cors": {
+ "enabled": true,
+ "origin": "https://your-domain.com"
+ },
+ "rateLimit": {
+ "enabled": true,
+ "singleDeviceInterval": 5000,
+ "allDevicesInterval": 60000
+ },
+ "cache": {
+ "enabled": true
+ }
+}
+```
+
+---
+
+## aliyun.json
+
+**用途**: 阿里云 IoT 平台集成配置
+
+**位置**: 应用程序根目录
+
+**依赖包**: `aliyun-iot-device-sdk`
+
+### 完整配置示例
+
+```json
+{
+ "enabled": true,
+ "region": "cn-shanghai",
+ "productKey": "your_product_key",
+ "description": "阿里云IoT设备连接配置(需从阿里云控制台获取)"
+}
+```
+
+### 配置字段说明
+
+| 字段 | 类型 | 默认值 | 说明 | 示例 |
+|------|------|--------|------|------|
+| `enabled` | boolean | true | 是否启用阿里云功能 | true/false |
+| `region` | string | cn-shanghai | 阿里云服务区域 | cn-shanghai, cn-beijing |
+| `productKey` | string | - | 阿里云产品 Key(从控制台获取) | a1xxxxxxxxxxxxb |
+| `description` | string | - | 配置说明(可选) | 阿里云IoT配置 |
+
+### 使用方式
+
+```javascript
+// 在 index.js 中
+const aliyunConfig = JSON.parse(fs.readFileSync(aliyunConfigPath, 'utf8'));
+
+if (aliyunConfig.enabled) {
+ // 连接到阿里云 IoT 平台
+ const device = aliyunIot.device({
+ ProductKey: aliyunConfig.productKey,
+ DeviceName: deviceName,
+ DeviceSecret: deviceSecret
+ });
+}
+```
+
+### 禁用阿里云
+
+```json
+{
+ "enabled": false
+}
+```
+
+### 注意事项
+
+⚠️ **安全提示**:
+- 不要将真实的 `productKey` 提交到公开代码仓库
+- 生产环境建议使用环境变量替代敏感信息
+- 确保配置文件的访问权限受限
+
+---
+
+## schema.json
+
+**用途**: 设备属性 TSL(Thing Specification Language)定义
+
+**位置**: 应用程序根目录
+
+**备注**: 68 个属性的完整定义,与 propertyMapper.js 中的定义同步
+
+### 完整配置示例(部分)
+
+```json
+{
+ "version": "1.0.0",
+ "properties": [
+ {
+ "identifier": "A",
+ "name": "脱水目标量",
+ "dataType": "float",
+ "accessMode": "r",
+ "unit": "kg",
+ "description": "患者脱水目标量"
+ },
+ {
+ "identifier": "B",
+ "name": "脱水量",
+ "dataType": "float",
+ "accessMode": "r",
+ "unit": "kg",
+ "description": "当前已脱水的量"
+ },
+ {
+ "identifier": "R",
+ "name": "收缩压下限",
+ "dataType": "int",
+ "accessMode": "r",
+ "unit": "mmHg",
+ "description": "血压收缩压下限"
+ },
+ {
+ "identifier": "IPAddress",
+ "name": "IP地址",
+ "dataType": "string",
+ "accessMode": "r",
+ "description": "设备连接的IP地址"
+ }
+ ]
+}
+```
+
+### 属性字段说明
+
+| 字段 | 类型 | 说明 | 示例 |
+|------|------|------|------|
+| `identifier` | string | 属性唯一标识符(A-Z, a-z, C53-C55 等) | A, B, C, IPAddress |
+| `name` | string | 属性中文名称(用户可读) | 脱水目标量 |
+| `dataType` | string | 数据类型(int, float, string, bool) | float |
+| `accessMode` | string | 访问模式(r 读, w 写, rw 读写) | r |
+| `unit` | string | 单位(可选) | kg, mmHg, bpm |
+| `description` | string | 属性描述(可选) | 患者脱水目标量 |
+
+### 完整属性列表(68 个)
+
+详见 `schema.json` 文件的完整内容。主要分类:
+
+- **A-Z** (26 个): 基本生命体征和治疗参数
+- **a-z** (26 个): 扩展参数
+- **C53-C55** (3 个): 特殊参数
+- **特殊字段** (13 个): deviceName, IPAddress, deviceType 等
+
+---
+
+## 常见问题
+
+### Q1: 启动时报错 "找不到配置文件"
+
+**A**: 确保以下文件存在于应用程序同目录:
+- `homeConfig.json` ✅
+- `mqtt.json` ✅
+- `httpConfig.json` ✅
+- `aliyun.json` ✅
+- `schema.json` ✅
+
+### Q2: 我想禁用某个功能,应该怎么做?
+
+**A**: 在对应的配置文件中设置 `enabled: false`:
+
+```json
+// 禁用 MQTT
+{ "enabled": false }
+
+// 禁用阿里云
+{ "enabled": false }
+
+// 禁用 CORS
+{ "cors": { "enabled": false } }
+```
+
+### Q3: 配置文件修改后需要重启吗?
+
+**A**: **是的**,需要重启应用程序才能加载新的配置:
+
+```bash
+npm run pkg # 重新打包
+npm start # 重新启动
+```
+
+### Q4: 环境变量如何设置?
+
+**A**: 在启动命令前设置环境变量:
+
+```bash
+# Windows PowerShell
+$env:PORT=10961; npm start
+
+# Windows CMD
+set PORT=10961 && npm start
+
+# Linux/Mac
+PORT=10961 npm start
+```
+
+### Q5: MQTT 连接失败怎么办?
+
+**A**: 检查以下内容:
+1. Broker URL 是否正确
+2. 用户名和密码是否正确
+3. 防火墙是否允许 MQTT 端口(通常 1883)
+4. MQTT Broker 服务是否运行
+
+```json
+{
+ "brokerUrl": "mqtt://your_broker_ip:1883",
+ "username": "your_username",
+ "password": "your_password"
+}
+```
+
+### Q6: 如何修改 HTTP 服务端口?
+
+**A**: 修改 `httpConfig.json`:
+
+```json
+{
+ "port": 8080,
+ "host": "0.0.0.0"
+}
+```
+
+或使用环境变量:
+
+```bash
+HTTP_PORT=9000 npm start
+```
+
+### Q7: 限流规则是什么?
+
+**A**: 在 `httpConfig.json` 中配置:
+
+```json
+{
+ "rateLimit": {
+ "enabled": true,
+ "singleDeviceInterval": 5000, // 单个设备 5 秒内最多 1 次
+ "allDevicesInterval": 60000 // 全部设备 60 秒内最多 1 次
+ }
+}
+```
+
+### Q8: 如何在生产环境中安全地使用配置文件?
+
+**A**: 建议做法:
+
+1. **敏感信息使用环境变量**:
+ ```bash
+ MQTT_PASSWORD=xxx ALIYUN_KEY=xxx npm start
+ ```
+
+2. **配置文件不提交敏感信息**:
+ ```json
+ {
+ "password": "${MQTT_PASSWORD}"
+ }
+ ```
+
+3. **限制文件权限**:
+ ```bash
+ chmod 600 homeConfig.json mqtt.json
+ ```
+
+4. **定期更新密码**
+
+### Q9: 多个实例如何使用不同的配置?
+
+**A**: 使用环境变量覆盖:
+
+```bash
+# 实例 1
+PORT=10961 HTTP_PORT=8080 npm start
+
+# 实例 2
+PORT=10962 HTTP_PORT=8081 npm start
+```
+
+---
+
+## 快速参考表
+
+### 配置文件概览
+
+| 文件名 | 用途 | 必需 | 可禁用 |
+|--------|------|:----:|:------:|
+| homeConfig.json | Socket 端口配置 | ✅ | ❌ |
+| mqtt.json | MQTT 服务配置 | ✅ | ✅ |
+| httpConfig.json | HTTP API 配置 | ✅ | ❌ |
+| aliyun.json | 阿里云 IoT 配置 | ✅ | ✅ |
+| schema.json | 属性定义 | ✅ | ❌ |
+
+### 服务启动流程
+
+```
+启动应用
+ ↓
+读取 homeConfig.json → 启动 Socket 服务
+ ↓
+读取 mqtt.json → 初始化 MQTT(若启用)
+ ↓
+读取 httpConfig.json → 启动 HTTP 服务
+ ↓
+读取 aliyun.json → 连接阿里云(若启用)
+ ↓
+读取 schema.json → 初始化属性映射
+ ↓
+系统运行 ✅
+```
+
+---
+
+## 更新日志
+
+### v1.1.0 (2025-12-10)
+- 新增 `homeConfig.json` Socket 端口配置
+- 更新所有配置文件说明
+- 添加常见问题解答
+- 增加安全建议
+
+### v1.0.0 (2025-12-08)
+- 初始版本
+
+---
+
+**最后更新**: 2025-12-10
+**版本**: v1.1.0
+**维护者**: 技术团队
--
Gitblit v1.8.0