1. 项目概述
作为一名从事上位机和网关开发多年的工程师,我深知多协议对接的痛苦。每次新项目都要为不同协议(Modbus、MQTT、EtherCAT等)编写重复代码,不仅效率低下,还导致系统耦合度极高。更糟的是,产线设备频繁上下电时,缺乏热插拔支持会导致程序崩溃和数据丢失。市面上的解决方案要么过于简单(只实现基础连通),要么封装过度难以二次开发。
基于这些痛点,我决定将过去三年项目中积累的经验整理成一个通用框架。这个框架的核心目标是:
- 统一不同协议的调用方式
- 原生支持设备热插拔
- 内置生产环境必需的健壮性功能(心跳检测、自动重连等)
- 易于集成到各种.NET应用中
2. 环境准备
2.1 开发环境配置
要使用这个框架,你需要准备以下环境:
- Visual Studio 2022(推荐)或2019
- .NET 6+(建议使用LTS版本)
- NuGet包管理器
安装必要的NuGet包:
bash复制Install-Package System.IO.Ports
Install-Package M2Mqtt
Install-Package TwinCAT.Ads
2.2 项目结构规划
建议采用分层架构:
code复制- HardwareCommunication
├── Core/ # 核心抽象和基础实现
├── Protocols/ # 各协议具体实现
├── Managers/ # 设备管理相关
├── Extensions/ # 扩展方法
└── Samples/ # 示例代码
3. 框架设计
3.1 核心抽象层
首先定义统一的设备接口:
csharp复制public interface IDevice
{
string DeviceId { get; }
DeviceStatus Status { get; }
Task ConnectAsync();
Task DisconnectAsync();
Task<byte[]> SendReceiveAsync(byte[] data);
event EventHandler<DeviceEventArgs> StatusChanged;
}
3.2 通信基类实现
抽象基类提供通用功能:
csharp复制public abstract class CommunicationBase : IDevice
{
protected readonly ILogger _logger;
protected readonly ExponentialBackoff _retryPolicy;
protected CommunicationBase(ILogger logger)
{
_logger = logger;
_retryPolicy = new ExponentialBackoff(
minDelay: TimeSpan.FromSeconds(1),
maxDelay: TimeSpan.FromSeconds(30),
retryCount: 5);
}
// 实现接口方法...
}
4. 协议适配实现
4.1 Modbus实现
csharp复制public class ModbusDevice : CommunicationBase
{
private SerialPort _serialPort;
public override async Task ConnectAsync()
{
await _retryPolicy.ExecuteAsync(async () =>
{
_serialPort = new SerialPort(portName, baudRate);
_serialPort.Open();
// 初始化逻辑...
});
}
// 其他方法实现...
}
4.2 MQTT实现
csharp复制public class MqttDevice : CommunicationBase
{
private MqttClient _client;
protected override async Task InternalConnectAsync()
{
_client = new MqttClient(brokerAddress);
await _client.ConnectAsync(clientId);
// 订阅主题等逻辑...
}
}
5. 设备管理
5.1 设备管理器
核心设备管理类:
csharp复制public class DeviceManager
{
private readonly ConcurrentDictionary<string, IDevice> _devices = new();
public void AddDevice(IDevice device)
{
device.StatusChanged += OnDeviceStatusChanged;
_devices.TryAdd(device.DeviceId, device);
}
private void OnDeviceStatusChanged(object sender, DeviceEventArgs e)
{
// 处理设备状态变化
}
}
5.2 热插拔实现
csharp复制public class HotPlugService : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
await ScanForNewDevices();
await Task.Delay(5000, stoppingToken);
}
}
private async Task ScanForNewDevices()
{
// 扫描新设备并添加到DeviceManager
}
}
6. 生产环境优化
6.1 性能调优
- 连接池管理:为频繁通信的设备维护连接池
- 批量读取:对支持批量读写的协议优化传输
- 异步处理:确保所有IO操作都是异步的
6.2 错误处理策略
csharp复制public class ResilientCommunicationPolicy
{
public async Task<T> ExecuteWithRetryAsync<T>(Func<Task<T>> operation)
{
// 实现带退避的重试逻辑
}
}
7. 框架集成
7.1 DI容器集成
csharp复制services.AddSingleton<IDeviceManager, DeviceManager>();
services.AddHostedService<HotPlugService>();
services.AddTransient<ModbusDevice>();
services.AddTransient<MqttDevice>();
7.2 业务层调用示例
csharp复制public class ProductionLineService
{
private readonly IDeviceManager _deviceManager;
public ProductionLineService(IDeviceManager deviceManager)
{
_deviceManager = deviceManager;
}
public async Task ReadSensorData(string deviceId)
{
if (_deviceManager.TryGetDevice(deviceId, out var device))
{
var data = await device.SendReceiveAsync(...);
// 处理数据...
}
}
}
8. 实战经验
8.1 常见问题排查
-
设备无响应:
- 检查物理连接
- 验证协议参数(波特率、从机地址等)
- 确认设备供电正常
-
间歇性断开:
- 调整心跳间隔
- 优化重试策略参数
- 检查网络稳定性
8.2 性能优化技巧
- 批量读取:尽可能使用批量读写代替单点操作
- 缓存策略:对不常变化的数据实施缓存
- 连接复用:避免频繁建立/断开连接
9. 扩展方向
- 协议扩展:添加OPC UA、Profinet等协议支持
- 云端集成:对接Azure IoT Hub等云平台
- 数据分析:集成实时数据分析功能
这个框架已经在多个生产环境中稳定运行,显著提高了开发效率和系统稳定性。通过统一抽象层,新协议的集成时间从原来的2-3周缩短到2-3天。热插拔功能使得设备维护时不再需要重启应用,大大提高了产线可用性。
