李工ROBOT架构之硬件驱动或数据存储的详细代码

我将提供基于 .NET 8.0-windows7.0 的半导体可靠性测试机上位机系统的 硬件驱动 和 数据存储 模块的详细代码实现。代码将与之前的 UI 框架(WPF、Prism、MVVM、MaterialDesignThemes、LiveCharts 2)无缝集成,涵盖硬件驱动的抽象接口、不同协议(串口、TCP/UDP、Modbus)支持,以及数据存储的 CSV、SQLite 和 MySQL 实现。以下内容包含详细的代码示例、中文注释和实现说明,确保模块化、可扩展和高性能,满足半导体测试场景的需求。


一、硬件驱动设计

1.1 设计目标

  • 抽象化:通过接口和抽象类定义硬件通用操作(初始化、开启、关闭、设置、读取),支持不同厂商硬件(如 Tektronix 电源、自定义温箱)。

  • 多协议支持:实现串口(COM)、TCP/UDP 和 Modbus 协议,兼容主流通信方式。

  • 可扩展性:使用依赖注入(Autofac)和反射动态加载驱动,支持硬件切换。

  • 事件驱动:硬件状态变化触发事件,通知 UI 或其他模块。

  • 异步操作:使用 async/await 确保高性能,适合高频数据采集。

1.2 项目结构

SemiconductorTestSystem/
├── SemiconductorTestSystem.Hardware/
│   ├── Interfaces/
│   │   ├── IHardwareDevice.cs
│   │   ├── ICommunication.cs
│   ├── Drivers/
│   │   ├── TektronixPowerSupply.cs
│   │   ├── CustomOven.cs
│   │   ├── ModbusDevice.cs
│   ├── Communication/
│   │   ├── SerialPortCommunication.cs
│   │   ├── TcpCommunication.cs
│   │   ├── UdpCommunication.cs
│   │   ├── ModbusCommunication.cs
│   ├── Services/
│   │   ├── HardwareService.cs
│   ├── HardwareModule.cs

1.3 硬件抽象接口

IHardwareDevice.cs

定义硬件设备的通用接口。

csharp

using System;

namespace SemiconductorTestSystem.Hardware.Interfaces
{
    public interface IHardwareDevice : IDisposable
    {
        string DeviceId { get; }
        string DeviceName { get; }
        DeviceStatus Status { get; }

        Task InitializeAsync();
        Task StartAsync();
        Task StopAsync();
        Task SetParameterAsync(string parameter, object value);
        Task ReadParameterAsync(string parameter);

        event EventHandler StatusChanged;
    }

    public class DeviceStatusChangedEventArgs : EventArgs
    {
        public DeviceStatus Status { get; set; }
        public string Message { get; set; }
    }

    public enum DeviceStatus
    {
        Idle,
        Running,
        Error,
        Disconnected
    }
} 
  

说明:

  • 属性:DeviceId 唯一标识设备,DeviceName 显示名称,Status 表示当前状态。

  • 方法:异步操作(InitializeAsync、StartAsync 等)确保非阻塞。

  • 事件:StatusChanged 通知状态变化,供 UI 或日志模块订阅。

ICommunication.cs

定义通信协议的通用接口。

csharp

namespace SemiconductorTestSystem.Hardware.Interfaces
{
    public interface ICommunication : IDisposable
    {
        Task ConnectAsync();
        Task DisconnectAsync();
        Task SendAsync(string command);
        Task ReceiveAsync();
    }
}

说明:

  • 抽象通信层,支持串口、TCP/UDP、Modbus 等协议。

  • 异步方法确保高性能通信。

1.4 通信协议实现

SerialPortCommunication.cs(串口通信)

csharp

using System.IO.Ports;
using System.Threading.Tasks;
using SemiconductorTestSystem.Hardware.Interfaces;

namespace SemiconductorTestSystem.Hardware.Communication
{
    public class SerialPortCommunication : ICommunication
    {
        private readonly SerialPort _serialPort;

        public SerialPortCommunication(string portName, int baudRate = 9600)
        {
            _serialPort = new SerialPort(portName, baudRate)
            {
                ReadTimeout = 5000,
                WriteTimeout = 5000
            };
        }

        public async Task ConnectAsync()
        {
            await Task.Run(() =>
            {
                if (!_serialPort.IsOpen)
                {
                    _serialPort.Open();
                }
            });
        }

        public async Task DisconnectAsync()
        {
            await Task.Run(() =>
            {
                if (_serialPort.IsOpen)
                {
                    _serialPort.Close();
                }
            });
        }

        public async Task SendAsync(string command)
        {
            await Task.Run(() => _serialPort.WriteLine(command));
        }

        public async Task ReceiveAsync()
        {
            return await Task.Run(() => _serialPort.ReadLine());
        }

        public void Dispose()
        {
            _serialPort?.Dispose();
        }
    }
}

说明:

  • 使用 System.IO.Ports.SerialPort 实现串口通信。

  • 异步方法避免阻塞,适合高频数据采集。

TcpCommunication.cs(TCP 通信)

csharp

using System.Net.Sockets;
using System.Text;

namespace SemiconductorTestSystem.Hardware.Communication
{
    public class TcpCommunication : ICommunication
    {
        private readonly TcpClient _client;
        private NetworkStream _stream;

        public TcpCommunication(string ipAddress, int port)
        {
            _client = new TcpClient();
            _client.ReceiveTimeout = 5000;
            _client.SendTimeout = 5000;
            IpAddress = ipAddress;
            Port = port;
        }

        public string IpAddress { get; }
        public int Port { get; }

        public async Task ConnectAsync()
        {
            await _client.ConnectAsync(IpAddress, Port);
            _stream = _client.GetStream();
        }

        public async Task DisconnectAsync()
        {
            await Task.Run(() =>
            {
                _stream?.Close();
                _client?.Close();
            });
        }

        public async Task SendAsync(string command)
        {
            byte[] data = Encoding.ASCII.GetBytes(command + "\r\n");
            await _stream.WriteAsync(data, 0, data.Length);
        }

        public async Task ReceiveAsync()
        {
            byte[] buffer = new byte[1024];
            int bytesRead = await _stream.ReadAsync(buffer, 0, buffer.Length);
            return Encoding.ASCII.GetString(buffer, 0, bytesRead).Trim();
        }

        public void Dispose()
        {
            _stream?.Dispose();
            _client?.Dispose();
        }
    }
}

说明:

  • 使用 TcpClient 实现 TCP 通信,异步方法确保高效。

  • 支持配置 IP 地址和端口,适配不同设备。

ModbusCommunication.cs(Modbus 通信)

csharp

using Modbus.Device;
using System.Net.Sockets;
using System.Threading.Tasks;
using SemiconductorTestSystem.Hardware.Interfaces;

namespace SemiconductorTestSystem.Hardware.Communication
{
    public class ModbusCommunication : ICommunication
    {
        private readonly string _ipAddress;
        private readonly int _port;
        private ModbusIpMaster _master;
        private TcpClient _client;

        public ModbusCommunication(string ipAddress, int port = 502)
        {
            _ipAddress = ipAddress;
            _port = port;
        }

        public async Task ConnectAsync()
        {
            _client = new TcpClient();
            await _client.ConnectAsync(_ipAddress, _port);
            _master = ModbusIpMaster.CreateIp(_client);
        }

        public async Task DisconnectAsync()
        {
            await Task.Run(() =>
            {
                _master?.Dispose();
                _client?.Close();
            });
        }

        public async Task SendAsync(string command)
        {
            // 示例:写入寄存器
            ushort address = ushort.Parse(command.Split(':')[0]);
            ushort value = ushort.Parse(command.Split(':')[1]);
            await _master.WriteSingleRegisterAsync(1, address, value);
        }

        public async Task ReceiveAsync()
        {
            // 示例:读取寄存器
            ushort[] registers = await _master.ReadHoldingRegistersAsync(1, 0, 1);
            return registers[0].ToString();
        }

        public void Dispose()
        {
            _master?.Dispose();
            _client?.Dispose();
        }
    }
}

说明:

  • 使用 Modbus.Device(需安装 NuGet 包 NModbus)实现 Modbus TCP 协议。

  • 支持读写寄存器,适配工业设备。

1.5 具体驱动实现

TektronixPowerSupply.cs(电源驱动)

csharp

using System.Threading.Tasks;
using SemiconductorTestSystem.Hardware.Interfaces;
using SemiconductorTestSystem.Hardware.Communication;

namespace SemiconductorTestSystem.Hardware.Drivers
{
    public class TektronixPowerSupply : IHardwareDevice
    {
        private readonly ICommunication _communication;
        private DeviceStatus _status;

        public TektronixPowerSupply(ICommunication communication)
        {
            _communication = communication;
            DeviceId = Guid.NewGuid().ToString();
            DeviceName = "Tektronix Power Supply";
            _status = DeviceStatus.Disconnected;
        }

        public string DeviceId { get; }
        public string DeviceName { get; }
        public DeviceStatus Status => _status;
        public event EventHandler StatusChanged;

        public async Task InitializeAsync()
        {
            try
            {
                await _communication.ConnectAsync();
                _status = DeviceStatus.Idle;
                RaiseStatusChanged("Initialized successfully");
            }
            catch (Exception ex)
            {
                _status = DeviceStatus.Error;
                RaiseStatusChanged($"Initialization failed: {ex.Message}");
            }
        }

        public async Task StartAsync()
        {
            try
            {
                await _communication.SendAsync("OUTPUT ON");
                _status = DeviceStatus.Running;
                RaiseStatusChanged("Started");
            }
            catch (Exception ex)
            {
                _status = DeviceStatus.Error;
                RaiseStatusChanged($"Start failed: {ex.Message}");
            }
        }

        public async Task StopAsync()
        {
            try
            {
                await _communication.SendAsync("OUTPUT OFF");
                _status = DeviceStatus.Idle;
                RaiseStatusChanged("Stopped");
            }
            catch (Exception ex)
            {
                _status = DeviceStatus.Error;
                RaiseStatusChanged($"Stop failed: {ex.Message}");
            }
        }

        public async Task SetParameterAsync(string parameter, object value)
        {
            try
            {
                if (parameter == "Voltage")
                {
                    await _communication.SendAsync($"VOLT {value}");
                }
                else if (parameter == "Current")
                {
                    await _communication.SendAsync($"CURR {value}");
                }
            }
            catch (Exception ex)
            {
                _status = DeviceStatus.Error;
                RaiseStatusChanged($"Set parameter failed: {ex.Message}");
            }
        }

        public async Task ReadParameterAsync(string parameter)
        {
            try
            {
                if (parameter == "Voltage")
                {
                    await _communication.SendAsync("MEAS:VOLT?");
                    return await _communication.ReceiveAsync();
                }
                else if (parameter == "Current")
                {
                    await _communication.SendAsync("MEAS:CURR?");
                    return await _communication.ReceiveAsync();
                }
                return null;
            }
            catch (Exception ex)
            {
                _status = DeviceStatus.Error;
                RaiseStatusChanged($"Read parameter failed: {ex.Message}");
                return null;
            }
        }

        private void RaiseStatusChanged(string message)
        {
            StatusChanged?.Invoke(this, new DeviceStatusChangedEventArgs
            {
                Status = _status,
                Message = message
            });
        }

        public void Dispose()
        {
            _communication?.Dispose();
        }
    }
} 
  

说明:

  • 支持串口或 TCP 通信,通过注入 ICommunication 实现。

  • 异步操作确保高效,事件通知状态变化。

CustomOven.cs(温箱驱动)

csharp

using System.Threading.Tasks;
using SemiconductorTestSystem.Hardware.Interfaces;
using SemiconductorTestSystem.Hardware.Communication;

namespace SemiconductorTestSystem.Hardware.Drivers
{
    public class CustomOven : IHardwareDevice
    {
        private readonly ICommunication _communication;
        private DeviceStatus _status;

        public CustomOven(ICommunication communication)
        {
            _communication = communication;
            DeviceId = Guid.NewGuid().ToString();
            DeviceName = "Custom Oven";
            _status = DeviceStatus.Disconnected;
        }

        public string DeviceId { get; }
        public string DeviceName { get; }
        public DeviceStatus Status => _status;
        public event EventHandler StatusChanged;

        public async Task InitializeAsync()
        {
            try
            {
                await _communication.ConnectAsync();
                _status = DeviceStatus.Idle;
                RaiseStatusChanged("Initialized successfully");
            }
            catch (Exception ex)
            {
                _status = DeviceStatus.Error;
                RaiseStatusChanged($"Initialization failed: {ex.Message}");
            }
        }

        public async Task StartAsync()
        {
            try
            {
                await _communication.SendAsync("START");
                _status = DeviceStatus.Running;
                RaiseStatusChanged("Started");
            }
            catch (Exception ex)
            {
                _status = DeviceStatus.Error;
                RaiseStatusChanged($"Start failed: {ex.Message}");
            }
        }

        public async Task StopAsync()
        {
            try
            {
                await _communication.SendAsync("STOP");
                _status = DeviceStatus.Idle;
                RaiseStatusChanged("Stopped");
            }
            catch (Exception ex)
            {
                _status = DeviceStatus.Error;
                RaiseStatusChanged($"Stop failed: {ex.Message}");
            }
        }

        public async Task SetParameterAsync(string parameter, object value)
        {
            try
            {
                if (parameter == "Temperature")
                {
                    await _communication.SendAsync($"TEMP {value}");
                }
            }
            catch (Exception ex)
            {
                _status = DeviceStatus.Error;
                RaiseStatusChanged($"Set parameter failed: {ex.Message}");
            }
        }

        public async Task ReadParameterAsync(string parameter)
        {
            try
            {
                if (parameter == "Temperature")
                {
                    await _communication.SendAsync("MEAS:TEMP?");
                    return await _communication.ReceiveAsync();
                }
                return null;
            }
            catch (Exception ex)
            {
                _status = DeviceStatus.Error;
                RaiseStatusChanged($"Read parameter failed: {ex.Message}");
                return null;
            }
        }

        private void RaiseStatusChanged(string message)
        {
            StatusChanged?.Invoke(this, new DeviceStatusChangedEventArgs
            {
                Status = _status,
                Message = message
            });
        }

        public void Dispose()
        {
            _communication?.Dispose();
        }
    }
} 
  

说明:

  • 温箱驱动示例,支持温度设置和读取。

  • 使用相同的 ICommunication 接口,支持协议切换。

1.6 硬件服务(动态加载)

HardwareService.cs

csharp

using System.Reflection;
using Microsoft.Extensions.Configuration;
using Autofac;
using SemiconductorTestSystem.Hardware.Interfaces;
using SemiconductorTestSystem.Hardware.Communication;

namespace SemiconductorTestSystem.Hardware.Services
{
    public class HardwareService : IHardwareService
    {
        private readonly IConfiguration _configuration;
        private readonly ILifetimeScope _scope;
        private readonly Dictionary _devices;

        public HardwareService(IConfiguration configuration, ILifetimeScope scope)
        {
            _configuration = configuration;
            _scope = scope;
            _devices = new Dictionary();
            LoadDevices();
        }

        private void LoadDevices()
        {
            var hardwareConfig = _configuration.GetSection("Hardware");
            foreach (var deviceConfig in hardwareConfig.GetChildren())
            {
                var typeName = deviceConfig["Type"];
                var protocol = deviceConfig["Protocol"];
                ICommunication communication = protocol switch
                {
                    "Serial" => new SerialPortCommunication(deviceConfig["Port"], int.Parse(deviceConfig["BaudRate"] ?? "9600")),
                    "TCP" => new TcpCommunication(deviceConfig["Address"], int.Parse(deviceConfig["Port"])),
                    "Modbus" => new ModbusCommunication(deviceConfig["Address"], int.Parse(deviceConfig["Port"] ?? "502")),
                    _ => throw new ArgumentException($"Unsupported protocol: {protocol}")
                };

                var deviceType = Type.GetType($"SemiconductorTestSystem.Hardware.Drivers.{typeName}");
                if (deviceType != null)
                {
                    var device = (IHardwareDevice)Activator.CreateInstance(deviceType, communication);
                    _devices.Add(deviceConfig.Key, device);
                }
            }
        }

        public async Task> GetAllDevicesAsync()
        {
            return await Task.FromResult(_devices.Values.ToList());
        }

        public async Task GetDeviceAsync(string deviceName)
        {
            return await Task.FromResult(_devices.Values.FirstOrDefault(d => d.DeviceName == deviceName));
        }
    }

    public interface IHardwareService
    {
        Task> GetAllDevicesAsync();
        Task GetDeviceAsync(string deviceName);
    }
}

说明:

  • 通过配置文件动态加载硬件驱动和通信协议。

  • 使用 Autofac 的 ILifetimeScope 管理依赖。

  • 支持串口、TCP 和 Modbus 协议切换。

appsettings.json

json

{
  "Hardware": {
    "PowerSupply": {
      "Type": "TektronixPowerSupply",
      "Protocol": "Serial",
      "Port": "COM1",
      "BaudRate": "9600"
 

   },
    "Oven": {
      "Type": "CustomOven",
      "Protocol": "TCP",
      "Address": "192.168.1.100 молодежь
      "Port": "5020"
    },
    "ModbusDevice": {
      "Type": "ModbusDevice",
      "Protocol": "Modbus",
      "Address": "192.168.1.101",
      "Port": "502"
    }
  }
}

HardwareModule.cs(Autofac 注册)

csharp

using Autofac;
using SemiconductorTestSystem.Hardware.Interfaces;
using SemiconductorTestSystem.Hardware.Services;

namespace SemiconductorTestSystem.Hardware
{
    public class HardwareModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType().As().SingleInstance();
            builder.RegisterType().As();
            builder.RegisterType().As();
            builder.RegisterType().As();
        }
    }
}

说明:

  • Autofac 模块注册硬件服务和驱动。

  • 支持动态加载不同厂商的硬件。


二、数据存储设计

2.1 设计目标

  • 多存储支持:支持 CSV、SQLite 和 MySQL,通过配置文件切换。

  • 灵活性:CSV 支持自定义格式,通过反射实现。

  • 高性能:使用 Entity Framework Core 优化数据库操作,异步存储数据。

  • 可扩展性:抽象存储接口,方便添加新存储方式(如 PostgreSQL)。

2.2 项目结构

SemiconductorTestSystem/
├── SemiconductorTestSystem.Data/
│   ├── Interfaces/
│   │   ├── IDataStorageService.cs
│   ├── Repositories/
│   │   ├── CsvStorageProvider.cs
│   │   ├── DatabaseStorageProvider.cs
│   ├── DbContexts/
│   │   ├── TestDbContext.cs
│   ├── Models/
│   │   ├── TestData.cs
│   │   ├── Channel.cs
│   ├── DataModule.cs

2.3 数据模型

TestData.cs

csharp

namespace SemiconductorTestSystem.Data.Models
{
    public class TestData
    {
        public int Id { get; set; }
        public string ChannelId { get; set; }
        public DateTime Timestamp { get; set; }
        public double Temperature { get; set; }
        public double Voltage { get; set; }
        public double Current { get; set; }
        public string TestMode { get; set; }
    }
}

Channel.cs

csharp

namespace SemiconductorTestSystem.Data.Models
{
    public class Channel
    {
        public string Id { get; set; }
        public string ChannelName { get; set; }
        public string OvenId { get; set; }
        public string ZoneId { get; set; }
        public string Status { get; set; }
    }
}

2.4 存储接口

IDataStorageService.cs

csharp

using SemiconductorTestSystem.Data.Models;

namespace SemiconductorTestSystem.Data.Interfaces
{
    public interface IDataStorageService
    {
        Task SaveDataAsync(IEnumerable data);
        Task> QueryDataAsync(string channelId, DateTime? startTime, DateTime? endTime);
    }
}

2.5 存储实现

CsvStorageProvider.cs

csharp

using System.Reflection;
using System.IO;
using System.Threading.Tasks;
using SemiconductorTestSystem.Data.Interfaces;

namespace SemiconductorTestSystem.Data.Repositories
{
    public class CsvStorageProvider : IDataStorageService
    {
        private readonly string _filePath;
        private readonly Type _dataType;

        public CsvStorageProvider(string filePath, Type dataType)
        {
            _filePath = filePath;
            _dataType = dataType;
        }

        public async Task SaveDataAsync(IEnumerable data)
        {
            using var writer = new StreamWriter(_filePath, append: true);
            var properties = _dataType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

            // 写入表头(仅在文件为空时)
            if (new FileInfo(_filePath).Length == 0)
            {
                await writer.WriteLineAsync(string.Join(",", properties.Select(p => p.Name)));
            }

            // 写入数据
            foreach (var item in data)
            {
                var values = properties.Select(p => p.GetValue(item)?.ToString() ?? "");
                await writer.WriteLineAsync(string.Join(",", values));
            }
        }

        public async Task> QueryDataAsync(string channelId, DateTime? startTime, DateTime? endTime)
        {
            var results = new List();
            using var reader = new StreamReader(_filePath);
            var headers = (await reader.ReadLineAsync()).Split(',');

            while (!reader.EndOfStream)
            {
                var line = await reader.ReadLineAsync();
                var values = line.Split(',');
                var data = new TestData
                {
                    Id = int.Parse(values[0]),
                    ChannelId = values[1],
                    Timestamp = DateTime.Parse(values[2]),
                    Temperature = double.Parse(values[3]),
                    Voltage = double.Parse(values[4]),
                    Current = double.Parse(values[5]),
                    TestMode = values[6]
                };

                if (data.ChannelId == channelId &&
                    (!startTime.HasValue || data.Timestamp >= startTime) &&
                    (!endTime.HasValue || data.Timestamp <= endTime))
                {
                    results.Add(data);
                }
            }

            return results;
        }
    }
}

说明:

  • 使用反射动态写入和读取 CSV 文件,支持自定义格式。

  • 异步 I/O 提高性能。

DatabaseStorageProvider.cs

csharp

using Microsoft.EntityFrameworkCore;
using SemiconductorTestSystem.Data.DbContexts;
using SemiconductorTestSystem.Data.Models;
using System.Linq;

namespace SemiconductorTestSystem.Data.Repositories
{
    public class DatabaseStorageProvider : IDataStorageService
    {
        private readonly TestDbContext _dbContext;

        public DatabaseStorageProvider(TestDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        public async Task SaveDataAsync(IEnumerable data)
        {
            if (typeof(T) == typeof(TestData))
            {
                await _dbContext.TestDatas.AddRangeAsync(data.Cast());
                await _dbContext.SaveChangesAsync();
            }
        }

        public async Task> QueryDataAsync(string channelId, DateTime? startTime, DateTime? endTime)
        {
            var query = _dbContext.TestDatas.AsQueryable();

            if (!string.IsNullOrEmpty(channelId))
            {
                query = query.Where(d => d.ChannelId == channelId);
            }

            if (startTime.HasValue)
            {
                query = query.Where(d => d.Timestamp >= startTime.Value);
            }

            if (endTime.HasValue)
            {
                query = query.Where(d => d.Timestamp <= endTime.Value);
            }

            return await query.ToListAsync();
        }
    }
}

TestDbContext.cs

csharp

using Microsoft.EntityFrameworkCore;
using SemiconductorTestSystem.Data.Models;

namespace SemiconductorTestSystem.Data.DbContexts
{
    public class TestDbContext : DbContext
    {
        public DbSet TestDatas { get; set; }
        public DbSet Channels { get; set; }

        public TestDbContext(DbContextOptions options) : base(options) { }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity().HasKey(t => t.Id);
            modelBuilder.Entity().HasKey(c => c.Id);
        }
    }
}

说明:

  • 使用 EF Core 支持 SQLite 和 MySQL。

  • 异步查询和保存提高性能。

2.6 数据服务

DataService.cs

csharp

using Microsoft.Extensions.Configuration;
using SemiconductorTestSystem.Data.Interfaces;
using SemiconductorTestSystem.Data.Repositories;
using SemiconductorTestSystem.Data.DbContexts;

namespace SemiconductorTestSystem.Data.Services
{
    public class DataService : IDataStorageService
    {
        private readonly IDataStorageService _provider;

        public DataService(IConfiguration configuration, TestDbContext dbContext)
        {
            var storageType = configuration["Storage:Type"];
            var connectionString = configuration["Storage:ConnectionString"];

            _provider = storageType switch
            {
                "CSV" => new CsvStorageProvider(connectionString, typeof(TestData)),
                "SQLite" => new DatabaseStorageProvider(dbContext),
                "MySQL" => new DatabaseStorageProvider(dbContext),
                _ => throw new ArgumentException($"Unsupported storage type: {storageType}")
            };
        }

        public async Task SaveDataAsync(IEnumerable data)
        {
            await _provider.SaveDataAsync(data);
        }

        public async Task> QueryDataAsync(string channelId, DateTime? startTime, DateTime? endTime)
        {
            return await _provider.QueryDataAsync(channelId, startTime, endTime);
        }
    }
}

appsettings.json

json

{
  "Storage": {
    "Type": "SQLite",
    "ConnectionString": "Data Source=testdata.db"
  }
}

DataModule.cs(Autofac 注册)

csharp

using Autofac;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using SemiconductorTestSystem.Data.Interfaces;
using SemiconductorTestSystem.Data.Services;
using SemiconductorTestSystem.Data.DbContexts;

namespace SemiconductorTestSystem.Data
{
    public class DataModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType().As().SingleInstance();

            builder.Register(c =>
            {
                var configuration = c.Resolve();
                var connectionString = configuration["Storage:ConnectionString"];
                var optionsBuilder = new DbContextOptionsBuilder();
                optionsBuilder.UseSqlite(connectionString); // 或 UseMySql
                return new TestDbContext(optionsBuilder.Options);
            }).As().InstancePerLifetimeScope();
        }
    }
}

说明:

  • 通过配置文件动态选择存储方式(CSV、SQLite、MySQL)。

  • EF Core 提供统一的数据库操作接口。


三、集成与 UI

硬件驱动和数据存储模块与之前的 UI 模块集成如下:

  1. 硬件控制界面:通过 IHardwareService 调用硬件驱动,显示状态和操作。

  2. 首页和监控界面:通过 IDataStorageService 查询数据,展示表格和曲线。

  3. 日志界面:记录硬件状态变化(通过 StatusChanged 事件)和数据存储操作。

示例:更新硬件控制 ViewModel

在 HardwareControlViewModel.cs 中注入 IHardwareService:

csharp

public class HardwareControlViewModel : BindableBase
{
    private readonly IHardwareService _hardwareService;
    // ... 其他代码

    public HardwareControlViewModel(IHardwareService hardwareService)
    {
        _hardwareService = hardwareService;
        // ... 初始化代码
    }

    // 示例:初始化硬件
    private async void InitializeDeviceAsync()
    {
        if (SelectedDevice != null)
        {
            var device = await _hardwareService.GetDeviceAsync(SelectedDevice.DeviceName);
            await device.InitializeAsync();
            UpdateDeviceStatus(device);
        }
    }
}

示例:保存数据

在 TestController.cs 中注入 IDataStorageService:

csharp

public class TestController : ITestController
{
    private readonly IDataStorageService _dataStorageService;

    public TestController(IDataStorageService dataStorageService)
    {
        _dataStorageService = dataStorageService;
    }

    public async Task SaveTestDataAsync(List data)
    {
        await _dataStorageService.SaveDataAsync(data);
    }
}

四、测试用例

4.1 硬件驱动测试

csharp

using Moq;
using Xunit;


namespace SemiconductorTestSystem.Tests.Hardware
{
    public class TektronixPowerSupplyTests
    {
        [Fact]
        public async Task InitializeAsync_ConnectsSuccessfully()
        {
            // Arrange
            var mockComm = new Mock();
            mockComm.Setup(c => c.ConnectAsync()).Returns(Task.CompletedTask);
            var powerSupply = new TektronixPowerSupply(mockComm.Object);

            // Act
            await powerSupply.InitializeAsync();

            // Assert
            Assert.Equal(DeviceStatus.Idle, powerSupply.Status);
            mockComm.Verify(c => c.ConnectAsync(), Times.Once());
        }
    }
}

4.2 数据存储测试

csharp

using Microsoft.EntityFrameworkCore;
using SemiconductorTestSystem.Data.Models;
using SemiconductorTestSystem.Data.Repositories;
using Xunit;

namespace SemiconductorTestSystem.Tests.Data
{
    public class DatabaseStorageProviderTests
    {
        [Fact]
        public async Task SaveDataAsync_SavesCorrectly()
        {
            // Arrange
            var options = new DbContextOptionsBuilder()
                .UseInMemoryDatabase("TestDb").Options;
            var dbContext = new TestDbContext(options);
            var provider = new DatabaseStorageProvider(dbContext);
            var data = new List
            {
                new TestData { ChannelId = "1", Temperature = 25, Voltage = 5 }
            };

            // Act
            await provider.SaveDataAsync(data);

            // Assert
            Assert.Equal(1, await dbContext.TestDatas.CountAsync());
        }
    }
}

五、性能优化

  1. 硬件驱动:

    • 使用异步操作(async/await)避免阻塞。

    • 缓存通信连接,减少重复初始化。

  2. 数据存储:

    • EF Core 使用批量插入(AddRangeAsync)提高性能。

    • CSV 存储使用 StreamWriter 异步写入。

  3. 多设备支持:

    • 使用 Parallel.ForEachAsync 处理多设备通信。

    • 实现连接池管理 TCP 连接。


六、后续支持

如果需要以下内容,请提供具体需求,我会进一步补充:

  • Modbus 驱动的完整实现:支持更多寄存器操作。

  • 多设备并发管理:使用 Actor 模型(如 Akka.NET)。

  • 云端存储:集成 Azure Cosmos DB 或 AWS RDS。

  • 更详细的测试用例:覆盖复杂场景。

请确认是否需要调整其他模块(如 UI 或计算模块)或更详细的代码实现,我会继续提供!

你可能感兴趣的:(李工ROBOT架构之硬件驱动或数据存储的详细代码)