# MCP串口工具系统架构设计文档
## ① 总体架构设计
### 架构风格
**分层架构 + 事件驱动混合模式**
- **分层架构**:MCP层 → 服务层 → 核心引擎层 → 适配器层
- **事件驱动**:基于EventEmitter的异步URC上报机制
- **插件化扩展**:日志、监控、协议解析可插拔
### 系统核心职责
1. **串口生命周期管理**:端口发现、打开、配置、关闭
2. **数据透传**:无协议假设的字节流读写
3. **异步事件分发**:URC、错误、状态变化的实时推送
4. **可观测性**:状态查询、健康检查、日志追踪
### 关键设计原则
- **SOLID原则**:单一职责,依赖倒置(依赖抽象接口)
- **Clean Architecture**:核心业务逻辑独立于框架和外部设备
- **资源安全**:RAII模式,确保串口资源正确释放
- **错误隔离**:串口错误不级联,独立恢复
- **无状态API**:MCP层无状态,状态由引擎层管理
---
## ② 模块划分与职责说明
### 目录结构建议
```
mcp2serial/
├── config/ # 配置文件
│ ├── urc-patterns.yaml # URC模式配置
│ └── default.yaml # 默认配置
├── src/
│ ├── core/ # 核心业务逻辑
│ │ ├── SerialEngine.ts # 串口引擎(状态管理)
│ │ ├── DataProcessor.ts # 数据处理器(编码转换)
│ │ ├── EventBus.ts # 事件总线
│ │ ├── PortSession.ts # 端口会话管理(会话ID)
│ │ ├── WriteMutex.ts # 写入互斥锁(并发控制)
│ │ └── URCDetector.ts # URC识别器(配置驱动)
│ ├── adapters/ # 外部适配层
│ │ ├── SerialPortAdapter.ts # 串口硬件适配
│ │ └── PlatformAdapter.ts # 平台相关适配
│ ├── services/ # 服务层
│ │ ├── SerialService.ts # 串口服务(业务逻辑)
│ │ ├── LogService.ts # 日志服务
│ │ └── HealthService.ts # 健康检查
│ ├── mcp/ # MCP协议层
│ │ ├── handlers/ # 方法处理器
│ │ ├── notifications.ts # 通知推送
│ │ └── server.ts # MCP服务器
│ ├── utils/
│ │ ├── logger.ts # 内部日志
│ │ └── error-codes.ts # 错误码定义
│ └── types/ # TypeScript类型定义
│ ├── serial.ts # 串口相关类型
│ ├── events.ts # 事件类型
│ └── mcp.ts # MCP协议类型
├── tests/
│ ├── unit/
│ └── integration/
└── package.json
```
### 模块职责详述
#### 1. **MCP层** (`src/mcp/`)
- **职责**:JSON-RPC 2.0协议解析、请求路由、通知推送
- **对外接口**:暴露MCP标准接口(serial.*, health.*, trace.*)
- **依赖**:依赖services层,不依赖具体实现
- **关键类**:
- `MCPServer`:主服务器,处理连接生命周期
- `MethodRouter`:方法分发器
- `NotificationManager`:通知推送管理
#### 2. **服务层** (`src/services/`)
- **职责**:业务逻辑编排,事务管理
- **依赖**:依赖core层,不直接操作硬件
- **关键类**:
- `SerialService`:串口业务逻辑(打开、关闭、写入)
- `LogService`:日志存储、查询、压缩
- `HealthService`:健康状态、uptime、错误统计
#### 3. **核心引擎层** (`src/core/`)
- **职责**:状态管理、事件分发、资源管理、并发控制、会话隔离、URC识别
- **设计模式**:单例模式(SerialEngine)、观察者模式(EventBus)、互斥锁模式(WriteMutex)
- **关键类**:
- `SerialEngine`:串口实例管理、状态机
- `EventBus`:基于EventEmitter的事件总线
- `DataProcessor`:Hex ↔ Text转换、编码处理
- `WriteMutex`:端口级写入互斥锁,防止并发写入
- `PortSession`:会话管理器,防止跨请求数据污染
- `URCDetector`:URC识别器,基于配置模式匹配
#### 4. **适配器层** (`src/adapters/`)
- **职责**:硬件抽象、平台差异屏蔽
- **设计模式**:适配器模式
- **关键类**:
- `SerialPortAdapter`:封装node-serialport库
- `PlatformAdapter`:处理Windows/Linux差异(端口列表、权限)
#### 5. **工具模块** (`src/utils/`)
- **职责**:日志、错误码、配置管理
- **关键文件**:
- `error-codes.ts`:集中定义所有错误码(PORT_BUSY, TIMEOUT, NOT_OPEN等)
- `logger.ts`:结构化日志(winston)
---
## ③ 数据与通信流
### 请求处理流(同步)
```mermaid
sequenceDiagram
participant Client as MCP Client
participant MCP as MCP Server
participant Service as SerialService
participant Mutex as WriteMutex
participant Session as PortSession
participant Engine as SerialEngine
participant Adapter as SerialPortAdapter
participant Hardware as 串口设备
Client->>MCP: serial.write(params)
MCP->>Service: write(port, Buffer, timeout)
%% 获取会话ID和锁
Service->>Session: createSession(port)
Session-->>Service: sessionId
Service->>Mutex: acquire(port, timeout+1000)
Note over Mutex: 公平锁,FIFO队列
%% 写入阶段
Service->>Engine: writeWithSession(port, buffer, sessionId)
Engine->>Adapter: write(buffer)
Adapter->>Hardware: 物理写入
Note over Adapter,Hardware: Flush立即发送
%% 读响应(带会话过滤)
par 异步数据收集
loop 直到timeout
Device->>Adapter: 数据到达
Adapter->>Engine: emit('data', chunk)
Engine->>Session: filterBySession(chunk, sessionId)
Session-->>Engine: isValid
opt 本会话数据
Engine->>Engine: buffer.append(chunk)
end
end
and 超时控制
Engine->>Engine: setTimeout(timeout)
end
%% 清理
Engine->>Session: endSession(sessionId)
Engine-->>Service: {status, hex, text, sessionId}
Service->>Mutex: release(port)
Service->>MCP: 业务结果
MCP->>Client: JSON-RPC响应
```
### 主动上报流(异步)
```mermaid
sequenceDiagram
participant Hardware as 串口设备
participant Adapter as SerialPortAdapter
participant Session as PortSession
participant Engine as SerialEngine
participant EventBus as EventBus
participant Notifier as NotificationManager
participant Client as MCP Client
Hardware->>Adapter: URC数据到达
Adapter->>Engine: emit('data', buffer)
%% 检查是否有活跃会话
Engine->>Session: getActiveSession(port)
Session-->>Engine: sessionId|null
alt 无活跃会话
Engine->>EventBus: publish('serial.urc', {port, data, isURC:true})
EventBus->>Notifier: URC通知
Notifier->>Client: serial.report (type: 'urc')
else 有活跃会话
Engine->>Session: isSessionData(data, sessionId)
Session-->>Engine: isValid
alt 本会话响应数据
Engine->>Engine: 追加到响应buffer
else URC干扰数据
Engine->>EventBus: publish('serial.urc', {...})
EventBus->>Notifier: URC通知
Notifier->>Client: serial.report (type: 'urc')
end
end
```
### 状态查询流
```mermaid
flowchart LR
A[Client] -->|serial.status| B[MCP层]
B --> C[SerialService]
C --> D[SerialEngine]
D --> E[查询内存状态]
D --> F[Adapter获取信号]
F --> G[返回CTS/DSR等]
G --> D
D --> C
C --> B
B --> A[返回状态JSON]
```
### 异步机制
- **事件驱动**:基于Node.js EventEmitter,无阻塞
- **超时控制**:使用`setTimeout`+`Promise.race`实现精确超时
- **数据收集**:写入后立即切换为接收模式,持续读取直到超时
- **线程模型**:单线程事件循环,IO异步操作(适合串口场景)
### 缓存策略
- **端口列表缓存**:5秒TTL缓存(减少系统调用)
- **状态缓存**:内存实时状态(无需缓存)
- **日志缓存**:循环缓冲区(防止内存溢出)
---
## ④ 接口/API设计
### MCP标准接口
#### 1. `serial.open`
```typescript
// 请求
interface OpenRequest {
port: string;
baudrate: number;
data_bits: 5 | 6 | 7 | 8;
parity: 'none' | 'even' | 'odd';
stop_bits: 1 | 1.5 | 2;
flow_control: 'none' | 'rts_cts' | 'xon_xoff';
}
// 响应
interface OpenResponse {
status: 'ok' | 'error';
port?: string;
config?: SerialConfig;
error_code?: ErrorCode;
message?: string;
}
// 错误码
type ErrorCode =
| 'PORT_BUSY' // 端口被占用
| 'PORT_NOT_FOUND' // 端口不存在
| 'INVALID_CONFIG' // 配置参数无效
| 'PERMISSION_DENIED'; // 权限不足
```
#### 2. `serial.write`
```typescript
// 请求
interface WriteRequest {
port: string;
data: string; // hex字符串,如"48656c6c6f"
timeout_ms: number; // 推荐100-5000ms
filter_urc?: boolean; // 是否过滤URC(默认true)
}
// 响应
interface WriteResponse {
status: 'ok' | 'timeout' | 'error';
session_id: string; // 唯一会话ID,用于追踪
timeout_ms: number;
raw_hex: string; // 已排除URC的纯净响应
text: string; // UTF-8解码文本
partial: boolean; // 是否部分数据
urc_detected: boolean; // 是否检测到URC并过滤
filtered_urc?: string[]; // 被过滤的URC内容(调试用)
error_code?: WriteErrorCode;
message?: string;
}
// 错误码
type WriteErrorCode =
| 'NOT_OPEN' // 端口未打开
| 'WRITE_FAILED' // 写入失败
| 'TIMEOUT' // 超时
| 'MUTEX_TIMEOUT' // 获取锁超时
| 'SESSION_ERROR'; // 会话创建失败
```
#### 3. `serial.report` (Notification)
```typescript
// 推送格式
interface ReportNotification {
method: 'serial.report';
params: {
port: string;
timestamp: string; // ISO8601
type: 'data' | 'error' | 'status';
data: string; // UTF-8文本
};
}
// 订阅管理
interface SubscribeRequest {
port: string;
types: Array<'data' | 'error' | 'status'>;
}
```
#### 4. `trace.get_log`
```typescript
// 请求
interface GetLogRequest {
port: string;
since?: string; // ISO时间
limit_kb?: number; // 默认1024KB
compress?: boolean; // 是否gzip+base64
}
// 响应
interface GetLogResponse {
status: 'ok';
log_base64: string;
compressed: boolean;
size_kb: number;
}
```
### 内部模块接口
#### SerialEngine接口
```typescript
interface ISerialEngine {
// 端口管理
openPort(config: PortConfig): Promise<SerialPortInfo>;
closePort(port: string): Promise<void>;
getPortStatus(port: string): PortStatus;
// 数据操作(带会话隔离)
writeAndRead(
port: string,
data: Buffer,
timeout: number,
sessionId: string
): Promise<ReadResult>;
// 事件订阅
subscribe(
port: string,
types: EventType[],
listener: EventListener
): Subscription;
unsubscribe(subscriptionId: string): void;
}
```
#### EventBus接口
```typescript
interface IEventBus {
publish<T extends EventType>(
type: T,
event: EventMap[T]
): void;
subscribe<T extends EventType>(
type: T,
handler: EventHandler<T>
): string; // 返回subscriptionId
unsubscribe(subscriptionId: string): void;
}
```
#### WriteMutex接口
```typescript
interface IWriteMutex {
// 获取写入锁(公平锁,FIFO队列)
acquire(
port: string,
timeoutMs: number
): Promise<LockTicket>;
// 释放锁
release(port: string, ticket: LockTicket): void;
// 查询锁状态
getLockInfo(port: string): LockInfo;
}
interface LockTicket {
id: string; // 锁票据ID
port: string; // 端口
acquiredAt: number; // 获取时间戳
requester: string; // 请求方标识
}
interface LockInfo {
isLocked: boolean;
currentHolder?: string;
waitQueueSize: number;
maxWaitTime: number;
}
```
#### URCDetector接口(配置驱动)
```typescript
interface IURCDetector {
// 加载URC配置
loadConfig(configPath: string): Promise<void>;
// 重新加载配置(热更新)
reloadConfig(): Promise<void>;
// 判断是否URC
isURC(
line: string,
port?: string
): boolean;
// 提取URC和数据
extract(
data: Buffer,
port?: string
): { urc: string[]; data: Buffer };
// 获取当前配置
getConfig(): URCConfig;
// 添加自定义模式(运行时)
addPattern(
pattern: string | RegExp,
description?: string
): void;
}
interface URCConfig {
version: string;
patterns: URCPattern[];
options: URCOptions;
}
interface URCPattern {
id: string; // 模式ID
pattern: string; // 正则表达式字符串
description: string; // 描述
examples?: string[]; // 示例
module?: string; // 适用模块(可选)
}
interface URCOptions {
enableFilter: boolean; // 是否启用过滤
reportFiltered: boolean; // 是否上报被过滤的URC
maxLineLength: number; // 最大行长度
encoding: string; // 编码(默认utf8)
}
```
#### PortSession接口
```typescript
interface IPortSession {
// 创建会话
createSession(
port: string,
options?: SessionOptions
): SessionContext;
// 结束会话
endSession(sessionId: string): void;
// 验证数据是否属于本会话(排除URC)
isSessionData(
data: Buffer,
sessionId: string
): boolean;
// 识别并提取URC(非请求结果码)
extractURC(
data: Buffer,
port: string
): { urc: string[]; data: Buffer };
// 获取活跃会话
getActiveSession(port: string): string | null;
// 清理过期会话
cleanupExpired(): void;
}
interface SessionContext {
sessionId: string; // 唯一会话ID
port: string; // 关联端口
createdAt: number; // 创建时间
buffer: Buffer; // 本会话数据缓冲区(已过滤URC)
urcBuffer: string[]; // 收集到的URC(调试用)
}
interface SessionOptions {
timeoutMs?: number; // 会话超时
filterURC?: boolean; // 是否过滤URC(默认true)
}
```},{
---
## ⑤ 关键技术决策
### 1. **为什么选择Node.js + TypeScript?**
- **跨平台**:统一处理Windows(COM)和Linux(/dev/tty*)
- **异步IO**:事件驱动模型完美匹配串口异步数据
- **MCP生态**:已有成熟的MCP Server SDK(@modelcontextprotocol/sdk)
- **开发效率**:TypeScript提供类型安全,减少协议错误
- **性能**:单线程事件循环足够处理串口速率(最高数Mbps)
### 2. **为什么采用分层架构+事件驱动混合?**
- **分层优势**:清晰的依赖关系,测试容易(可Mock各层)
- **事件驱动优势**:解耦生产者和消费者,支持多订阅者
- **组合效果**:MCP层无状态,状态集中在Engine层,便于管理
### 3. **为什么设计SerialEngine作为单一状态源?**
- **状态一致性**:所有端口状态集中管理,避免竞态
- **资源管理**:Engine负责资源生命周期,防止泄漏
- **测试性**:可Mock Engine,测试上层逻辑
### 4. **为什么使用Adapter模式?**
- **硬件解耦**:未来可替换serialport库(如换用纯JS实现)
- **平台抽象**:Windows和Linux的差异封装在Adapter
- **可测试**:可Mock Adapter,无需真实串口
### 5. **为什么write采用"超时收集"模式?**
- **协议无关**:不假设AT指令结构,纯粹字节流
- **灵活性**:LLM自行判断响应完整性
- **简单性**:避免复杂的terminator匹配逻辑
- **可靠性**:timeout保证不会无限等待
### 6. **为什么需要EventBus?**
- **解耦**:Adapter → Engine → Service → MCP,层层解耦
- **多播**:一个URC可同时推送给日志服务和MCP通知
- **可扩展**:未来可接入消息队列(如Redis)实现多进程
### 7. **为什么需要WriteMutex(写入互斥锁)?**
- **串口特性**:串口是半双工通信,物理上不支持并发写入
- **响应错乱**:并发写入会导致响应交错,无法匹配请求
- **公平性**:FIFO队列保证请求按顺序处理,防止饥饿
- **死锁预防**:超时机制防止永久等待
- **可观测性**:可监控锁等待时间,发现性能瓶颈
**锁的实现策略**:
```typescript
// 每个端口一个独立锁
const portLocks = new Map<string, Mutex>();
// 公平队列实现
class Mutex {
private queue: Array<{
resolve: (ticket: LockTicket) => void;
reject: (error: Error) => void;
timestamp: number;
}> = [];
async acquire(timeoutMs: number): Promise<LockTicket> {
// 如果有等待队列或已锁定,加入队列
// 使用Promise实现异步锁
}
}
```
### 8. **URC判断机制与配置化设计**
**URC判断原理**:
系统通过**正则表达式模式匹配**判断一行数据是否为URC。所有URC模式存储在配置文件中,支持热更新。
**判断流程**:
```
数据到达 → 按行分割 → 逐行匹配URC模式 →
├─ 匹配成功 → 标记为URC → 立即上报 → 丢弃
└─ 匹配失败 → 标记为响应数据 → 追加到会话buffer
```
**配置文件格式**(`config/urc-patterns.yaml`):
```yaml
version: "1.0"
patterns:
- id: csq
pattern: "^\\+CSQ:\\s*\\d+,\\d+"
description: "信号强度报告"
examples: ["+CSQ: 23,99", "+CSQ: 15,0"]
module: "通用"
- id: cmt
pattern: "^\\+CMT:\\s*\"[^\"]*\",\"[^\"]*\""
description: "短信到达通知"
examples: ['+CMT: "+8613800138000","","23/11/15,10:30:00+32"']
module: "短信"
- id: creg
pattern: "^\\+CREG:\\s*\\d+(,\"[0-9A-Fa-f]+",\"[0-9A-Fa-f]+")?"
description: "网络注册状态"
examples: ["+CREG: 2", "+CREG: 1,\"0010\",\"0001\""]
module: "网络"
- id: ring
pattern: "^RING$"
description: "来电振铃"
examples: ["RING"]
module: "通话"
- id: custom_1
pattern: "^\\+MYURC:\\s*\\d+"
description: "自定义URC示例"
examples: ["+MYURC: 123"]
module: "自定义"
options:
enableFilter: true
reportFiltered: true
maxLineLength: 1024
encoding: "utf8"
```
**配置加载机制**:
```typescript
class URCDetector implements IURCDetector {
private patterns: URCPattern[] = [];
private compiledPatterns: Map<string, RegExp> = new Map();
async loadConfig(configPath: string): Promise<void> {
const content = await fs.readFile(configPath, 'utf8');
const config = yaml.parse(content) as URCConfig;
this.patterns = config.patterns;
this.compiledPatterns.clear();
// 预编译正则表达式
for (const pattern of this.patterns) {
try {
this.compiledPatterns.set(
pattern.id,
new RegExp(pattern.pattern)
);
} catch (error) {
logger.warn(`Invalid URC pattern: ${pattern.id}`, error);
}
}
logger.info(`Loaded ${this.patterns.length} URC patterns`);
}
isURC(line: string, port?: string): boolean {
if (!line || line.trim() === '') return false;
// 逐行匹配所有模式
for (const [id, regex] of this.compiledPatterns) {
if (regex.test(line.trim())) {
logger.debug(`URC detected: ${id} - ${line.trim()}`);
return true;
}
}
return false;
}
}
```
**热更新支持**:
```typescript
// 监听配置文件变化
const watcher = fs.watch(configPath, async (eventType) => {
if (eventType === 'change') {
logger.info('URC config changed, reloading...');
try {
await urcDetector.reloadConfig();
logger.info('URC config reloaded successfully');
} catch (error) {
logger.error('Failed to reload URC config', error);
}
}
});
```
**扩展机制**:
```typescript
// 运行时添加自定义模式(无需重启)
urcDetector.addPattern(
"^\\+MYSTATUS:\\s*\\w+",
"自定义状态URC"
);
```
**会话隔离+URC过滤流程**:
```typescript
// 在Engine层处理数据到达
onDataReceived(port: string, chunk: Buffer) {
const sessionId = this.portSession.getActiveSession(port);
if (sessionId) {
// 有活跃会话,优先判断是否为URC
const { urc, data } = this.portSession.extractURC(chunk, port);
if (data.length > 0) {
// 非URC数据,追加到本会话buffer
const session = this.portSession.getSession(sessionId);
session.buffer = Buffer.concat([session.buffer, data]);
}
if (urc.length > 0) {
// 记录URC到会话(调试用)
session.urcBuffer.push(...urc);
}
} else {
// 无活跃会话,直接作为URC上报
const lines = chunk.toString().split('\r\n');
for (const line of lines) {
if (line.trim()) {
this.eventBus.publish('serial.urc', {
port,
timestamp: new Date().toISOString(),
data: line
});
}
}
}
}
```
### 9. **错误处理策略**
- **错误码标准化**:集中定义所有错误码,避免魔法字符串
- **错误链**:底层错误包装后向上传递,保留原始信息
- **恢复机制**:端口错误自动关闭,防止资源泄漏
- **监控**:HealthService记录错误统计,便于告警
### 10. **为什么PortSession需要集成URC过滤?**
- **实时性**:在数据到达时立即识别URC,避免延迟
- **准确性**:会话期间精确区分响应数据和URC
- **调试支持**:filtered_urc字段记录被过滤的内容,便于问题排查
- **性能**:避免后续重复解析,一次识别终身受益
- **扩展性**:URC模式可配置,支持不同模块的URC格式
---
## ⑥ 扩展性、性能与安全性
### 扩展性设计
#### 1. **水平扩展**
- **多实例部署**:每个实例管理不同串口集合
- **服务发现**:通过配置中心分配端口
- **无状态MCP层**:可部署多个MCP Server,负载均衡
#### 2. **垂直扩展**
- **插件机制**:协议解析、日志存储可插拔
```typescript
interface ProtocolPlugin {
parse(data: Buffer): ProtocolMessage[];
}
```
- **中间件**:支持AOP切面(如自动重试、限流)
#### 3. **功能扩展**
- **新增命令**:只需在Service层添加方法,MCP层自动暴露
- **新增事件类型**:扩展EventType枚举,EventBus自动支持
- **多协议支持**:通过Adapter模式支持TCP/UDP转串口
### 性能优化
#### 1. **IO优化**
- **流式处理**:使用Node.js Stream API处理大数据
- **背压控制**:防止内存溢出(Buffer大小限制)
- **零拷贝**:Buffer直接传递,避免不必要转换
#### 2. **并发优化**
- **端口隔离**:每个串口独立事件流,互不阻塞
- **异步批量**:支持批量写入(未来扩展)
- **连接池**:高频操作的端口保持长连接
#### 3. **资源优化**
- **日志轮转**:自动清理旧日志,防止磁盘满
- **内存限制**:单个端口Buffer上限(如1MB)
- **GC优化**:及时清理闭包,避免内存泄漏
#### 4. **性能指标**
- **响应延迟**:write操作< 10ms(不含timeout等待)
- **吞吐量**:支持115200波特率连续收发
- **并发端口**:单进程支持50+串口(取决于硬件)
### 安全性设计
#### 1. **访问控制**
- **端口白名单**:配置允许访问的端口(防止扫描)
```typescript
const ALLOWED_PORTS = ['COM3', 'COM4'];
```
- **权限检查**:Linux下检查用户是否在dialout组
- **API密钥**:MCP层支持API Key认证(可选)
#### 2. **输入验证**
- **参数校验**:所有输入严格验证类型和范围
- **SQL注入防护**:无SQL,但防止命令注入(如port参数)
- **缓冲区溢出**:Node.js Buffer自动边界检查
#### 3. **资源安全**
- **超时机制**:所有IO操作必须带超时
- **资源配额**:限制单个端口的日志大小、Buffer大小
- **优雅关闭**:SIGINT/SIGTERM信号捕获,释放所有端口
#### 4. **数据安全**
- **日志脱敏**:配置敏感数据过滤(如IMEI)
```typescript
const SENSITIVE_PATTERNS = [/IMEI:\d{15}/g];
```
- **加密传输**:MCP over TLS(生产环境)
- **审计日志**:记录所有open/close/write操作
### 可维护性设计
#### 1. **可观测性**
- **结构化日志**:JSON格式,支持ELK收集
- **Metrics**:Prometheus指标(端口数、错误率、延迟、锁等待时间)
- **Tracing**:OpenTelemetry分布式追踪(包含sessionId追踪)
- **URC监控**:统计URC频率和类型,发现异常模块
#### 2. **测试策略**
- **单元测试**:每层独立测试,覆盖率>80%
- **集成测试**:模拟串口(使用虚拟串口对)
- **URC模拟测试**:注入各种URC模式,验证过滤正确性
- **契约测试**:MCP接口契约验证
- **模糊测试**:随机数据测试鲁棒性
- **并发测试**:多客户端并发写入,验证锁机制
#### 3. **文档化**
- **API文档**:自动生成OpenAPI/Swagger
- **架构决策记录**:ADR记录所有重大决策(包括URC处理策略)
- **故障手册**:常见错误排查SOP
- **URC模式库**:维护常见模块的URC模式列表
#### 4. **部署友好**
- **Docker化**:多阶段构建,镜像<100MB
- **配置即代码**:环境变量+配置文件
- **健康检查**:`/health`端点供K8s探针
- **热更新**:支持URC模式热更新,无需重启
---
## ⑦ 架构图(Mermaid)
### 系统架构图
```mermaid
graph TB
subgraph "MCP Client Layer"
A[Claude Desktop] -->|JSON-RPC| B[MCP Server]
C[Other AI IDE] -->|JSON-RPC| B
end
subgraph "MCP Protocol Layer"
B --> D[Method Router]
D --> E[Request Handler]
E --> F[Notification Manager]
F -->|Push| A
end
subgraph "Service Layer"
E --> G[Serial Service]
E --> H[Log Service]
E --> I[Health Service]
G --> J[Serial Engine]
H --> J
I --> J
end
subgraph "Core Engine Layer"
J --> K[Event Bus]
J --> L[State Manager]
K --> M[Data Processor]
L --> M
end
subgraph "Adapter Layer"
M --> N[Serial Port Adapter]
N --> O[node-serialport]
O --> P[Hardware Serial]
end
subgraph "External Systems"
H --> Q[Log Storage]
I --> R[Metrics]
F --> A
end
style B fill:#4a90e2
style J fill:#f5a623
style K fill:#7ed321
style N fill:#50e3c2
```
### 数据流序列图
```mermaid
sequenceDiagram
participant Client
participant MCP
participant Service
participant Engine
participant Adapter
participant Device
%% 写请求
Client->>MCP: serial.write({port, hex, timeout})
MCP->>Service: write(port, Buffer, timeout)
Service->>Engine: acquirePort(port)
Engine->>Adapter: write(buffer)
Adapter->>Device: 物理写入
Note over Adapter,Device: Flush立即发送
%% 读响应
par 异步数据收集
loop 直到timeout
Device->>Adapter: 数据到达
Adapter->>Engine: emit('data', chunk)
Engine->>Engine: buffer.append(chunk)
end
and 超时控制
Engine->>Engine: setTimeout(timeout)
end
Engine->>Service: {status, hex, text}
Service->>MCP: 业务结果
MCP->>Client: JSON-RPC响应
%% 主动上报
Device->>Adapter: URC数据
Adapter->>Engine: emit('data')
Engine->>Engine: EventBus.publish()
Engine->>MCP: Notification推送
MCP->>Client: serial.report
```
### 状态机图
```mermaid
stateDiagram-v2
[*] --> Closed: 初始状态
state Closed {
[*] --> Detecting: 扫描端口
Detecting --> Detected: 发现端口
Detected --> [*]: 返回列表
}
Closed --> Opening: serial.open()
Opening --> Opened: 成功
Opening --> Closed: 失败(PORT_BUSY等)
state Opened {
[*] --> Idle: 就绪
Idle --> Writing: serial.write()
Writing --> Reading: 写入完成
Reading --> Idle: timeout到达
Reading --> Reading: 持续收数据
state Reading {
[*] --> Receiving: 启动timer
Receiving --> Partial: 收到部分数据
Receiving --> Timeout: timer触发
Partial --> Timeout: timer触发
Timeout --> [*]: 返回结果
}
Idle --> Error: 硬件错误
Error --> Idle: 自动恢复
}
Opened --> Closing: serial.close()
Closing --> Closed: 资源释放
Opened --> [*]: 进程退出
```
---
## 总结
本架构设计具备以下特点:
1. **高内聚低耦合**:各层职责清晰,依赖单向
2. **可测试性强**:每层可独立Mock测试
3. **生产就绪**:包含完整的错误处理、监控、安全机制
4. **易于扩展**:插件化设计,支持新功能快速接入
5. **跨平台**:适配器层屏蔽平台差异
**防坑点提醒**:
- 串口操作必须加锁,防止并发写入
- Windows下COM端口大于COM9需用`\\.\COM10`格式
- Linux下需检查udev规则,否则非root用户无法访问
- 数据事件可能高频触发,注意Buffer拼接性能
- 进程退出时务必关闭所有串口,否则可能残留锁文件