架构设计
概述
ModbusLink 采用**现代分层架构**设计,严格遵循**单一职责原则**和**开闭原则**,确保代码的可维护性、可扩展性和可测试性。
整体架构图
┌─────────────────────────────────────────────────────────────┐
│ 应用层 (Application Layer) │
│ 用户代码和业务逻辑 │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ 客户端层 (Client Layer) │
│ ModbusClient, AsyncModbusClient │
│ • 高级API封装 • 数据类型转换 • 错误处理 │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ 协议层 (Protocol Layer) │
│ Modbus协议实现 │
│ • PDU构造 • 功能码处理 • 数据验证 │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ 传输层 (Transport Layer) │
│ TCP, RTU, ASCII传输实现 │
│ • 连接管理 • 数据帧处理 • 校验计算 │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ 物理层 (Physical Layer) │
│ 以太网 / 串口 / 其他 │
└─────────────────────────────────────────────────────────────┘
核心设计原则
分层架构 (Layered Architecture) - 每层只与相邻层交互 - 上层依赖于下层,下层不依赖上层 - 便于独立测试和替换
依赖注入 (Dependency Injection) - 客户端通过构造函数接收传输层实例 - 降低耦合度,提高可测试性
面向接口编程 (Interface-Oriented Programming) - 使用抽象基类定义接口 - 具体实现可插拔替换
策略模式 (Strategy Pattern) - 不同传输方式作为不同策略 - 运行时切换传输策略
传输层设计
传输层架构
BaseTransport (ABC)
├── TcpTransport
├── RtuTransport
└── AsciiTransport
AsyncBaseTransport (ABC)
├── AsyncTcpTransport
├── AsyncRtuTransport
└── AsyncAsciiTransport
核心接口
同步传输接口
class BaseTransport(ABC):
@abstractmethod
def connect(self) -> None:
"""建立连接"""
@abstractmethod
def disconnect(self) -> None:
"""断开连接"""
@abstractmethod
def send_and_receive(self, data: bytes) -> bytes:
"""发送数据并接收响应"""
异步传输接口
class AsyncBaseTransport(ABC):
@abstractmethod
async def connect(self) -> None:
"""异步建立连接"""
@abstractmethod
async def disconnect(self) -> None:
"""异步断开连接"""
@abstractmethod
async def send_and_receive(self, data: bytes) -> bytes:
"""异步发送数据并接收响应"""
传输实现细节
TCP传输 (Modbus TCP)
MBAP Header (7 bytes) + PDU
┌──────┬──────┬──────┬──────┬──────────┬─────────────┐
│ TID │ PID │ Length │ Unit ID │ Function │
│ (2) │ (2) │ (2) │ (1) │ Code + Data │
└──────┴──────┴──────┴──────┴──────────┴─────────────┘
TID: 事务标识符,用于匹配请求响应
PID: 协议标识符,Modbus为0
Length: 后续字节长度
Unit ID: 单元标识符(从站地址)
RTU传输 (Modbus RTU)
RTU Frame
┌─────────┬─────────────┬─────────────┐
│ Address │ Function │ CRC-16 │
│ (1) │ Code + Data │ (2) │
└─────────┴─────────────┴─────────────┘
Address: 从站地址 (1-247)
CRC-16: 循环冗余校验,使用Modbus多项式
帧间隔: 至少3.5个字符时间
ASCII传输 (Modbus ASCII)
ASCII Frame
┌───┬─────────┬─────────────┬─────┬─────┬───┐
│ : │ Address │ Function │ LRC │ CR │ LF│
│ │ (2) │ Code + Data │ (2) │ │ │
└───┴─────────┴─────────────┴─────┴─────┴───┘
Start: 冒号字符 ‘:’
LRC: 纵向冗余校验
End: 回车换行 (CR LF)
客户端层设计
客户端架构
┌─────────────────────────────────────┐
│ 高级数据类型API │
│ read_float32, write_string, etc. │
└─────────────────────────────────────┘
│
┌─────────────────────────────────────┐
│ 标准Modbus API │
│ read_holding_registers, etc. │
└─────────────────────────────────────┘
│
┌─────────────────────────────────────┐
│ 协议处理层 │
│ PDU构造, 响应解析, 异常处理 │
└─────────────────────────────────────┘
│
┌─────────────────────────────────────┐
│ 传输层接口 │
│ BaseTransport/AsyncBaseTransport │
└─────────────────────────────────────┘
设计模式应用
模板方法模式
class ModbusClient:
def _execute_request(self, slave_id: int, function_code: int,
data: bytes) -> bytes:
"""模板方法:定义请求执行流程"""
# 1. 构造PDU
pdu = self._build_pdu(function_code, data)
# 2. 发送并接收
response = self._transport.send_and_receive(pdu)
# 3. 验证响应
self._validate_response(response, function_code)
# 4. 解析数据
return self._parse_response(response)
装饰器模式
def connection_required(func):
"""确保连接存在的装饰器"""
def wrapper(self, *args, **kwargs):
if not self._transport.is_connected():
raise ConnectionError("Not connected")
return func(self, *args, **kwargs)
return wrapper
服务器层设计
服务器架构
┌─────────────────────────────────────┐
│ 协议处理器 │
│ 请求解析、响应构造、异常处理 │
└─────────────────────────────────────┘
│
┌─────────────────────────────────────┐
│ 数据存储层 │
│ 线圈、寄存器的读写操作 │
└─────────────────────────────────────┘
│
┌─────────────────────────────────────┐
│ 传输服务器 │
│ TCP/RTU/ASCII服务器实现 │
└─────────────────────────────────────┘
数据存储设计
class ModbusDataStore:
"""线程安全的Modbus数据存储"""
def __init__(self, coils_size: int = 65536,
discrete_inputs_size: int = 65536,
holding_registers_size: int = 65536,
input_registers_size: int = 65536):
self._coils = [False] * coils_size
self._discrete_inputs = [False] * discrete_inputs_size
self._holding_registers = [0] * holding_registers_size
self._input_registers = [0] * input_registers_size
self._lock = threading.RLock() # 可重入锁
工具层设计
工具组件
CRC计算器 - 实现Modbus标准CRC-16算法 - 支持表查找优化
数据编码器 - 大小端字节序转换 - 各种数据类型编解码
日志系统 - 协议级调试信息 - 可配置日志级别
错误处理架构
异常层次结构
ModbusLinkError (基础异常)
├── ConnectionError (连接相关)
│ ├── ConnectionTimeoutError
│ └── ConnectionRefusedError
├── ProtocolError (协议相关)
│ ├── CRCError
│ ├── InvalidResponseError
│ └── FunctionCodeError
└── DataError (数据相关)
├── AddressError
└── ValueRangeError
异常处理策略
传输层异常: 网络、串口通信错误
协议层异常: Modbus协议格式错误
应用层异常: 业务逻辑错误
性能优化设计
连接池
class ModbusConnectionPool:
"""Modbus连接池,支持连接复用"""
def __init__(self, max_connections: int = 10):
self._pool = asyncio.Queue(maxsize=max_connections)
self._connections = set()
async def acquire(self) -> AsyncModbusClient:
"""获取连接"""
async def release(self, client: AsyncModbusClient):
"""释放连接"""
批量操作优化
async def batch_read_registers(self, requests: List[ReadRequest]) -> List[List[int]]:
"""批量读取寄存器,自动优化为最少请求数"""
# 合并连续地址的请求
optimized_requests = self._optimize_requests(requests)
# 并发执行
tasks = [self._read_registers(**req) for req in optimized_requests]
return await asyncio.gather(*tasks)
扩展性设计
插件架构
class ModbusPlugin(ABC):
"""Modbus插件基类"""
@abstractmethod
def on_request(self, request: ModbusRequest) -> ModbusRequest:
"""请求预处理"""
@abstractmethod
def on_response(self, response: ModbusResponse) -> ModbusResponse:
"""响应后处理"""
自定义传输层
class WebSocketTransport(AsyncBaseTransport):
"""WebSocket传输层示例"""
async def connect(self):
self._websocket = await websockets.connect(self._uri)
async def send_and_receive(self, data: bytes) -> bytes:
await self._websocket.send(data)
response = await self._websocket.recv()
return response
总结
ModbusLink的架构设计具有以下优势:
清晰的分层结构,每层职责明确
高度的可扩展性,支持自定义传输层和协议扩展
优秀的性能表现,支持异步和连接池
完善的错误处理,提供详细的异常信息
良好的可测试性,每层都可以独立测试
这种设计确保了ModbusLink既能满足当前需求,又具备未来扩展的灵活性。