基于**半导体无功老化上位机实战经验**(多站点、可配置硬件、PLC+负载监控+主板+RFID+扫码枪)
✅ 完成优化与完整架构设计基于半导体无功老化上位机实战经验多站点、可配置硬件、PLC负载监控主板RFID扫码枪给出稳定、生产级、可直接落地的完整架构 核心代码。1. 项目分层结构严格按您要求命名MaxWell.Solution.sln ├── MaxWell.Common 公共模型、扩展、ChannelHelper、Result 记录 ├── MaxWell.Interfaces 现代接口定义 ├── MaxWell.Drivers 所有驱动项目 │ ├── XinJePLCDriver.cs │ ├── LoadMonitorDriver.cs │ ├── MainBoardDriver.cs │ ├── RFIDDriver.cs │ └── ScannerDriver.cs ├── MaxWell.Services 业务层所有 *Service 后缀 ├── MaxWell.Configuration JSON 配置 热加载 ├── MaxWell.Logging Serilog 统一配置 ├── MaxWell.Watchdog 软硬件双看门狗 ├── MaxWell.UI WPF Prism CommunityToolkit.Mvvm 主程序 └── MaxWell.Host Program.cs 主机构建静态注册驱动驱动静态注册方式支持热替换、无需改代码在MaxWell.Host的DriverRegistry.cs中静态注册。2. 现代接口定义MaxWell.Interfaces// MaxWell.Interfaces/IHardwareDriver.csusingSystem.Threading.Channels;usingHslCommunication;usingSerilog;namespaceMaxWell.Interfaces;publicrecordHardwareResult(boolIsSuccessfalse,object?Datanull,intErrorCode0,string?ErrorMessagenull,DateTimeErrorTimedefault);publicrecordSignalObject(stringAddress,stringSignalDataType,// bool/int16/int32/float/double/float[]/string/byte[]object?Valuenull,intDataLength0,string?SignalNamenull);publicinterfaceIHardwareDriver:IAsyncDisposable{stringDriverName{get;}stringHardwareType{get;}boolIsConnected{get;}// 100% 异步 超时TaskInitializeAsync(objectcommunicationInfo,CancellationTokenctdefault);TaskOpenSessionAsync(CancellationTokenctdefault);TaskCloseSessionAsync(CancellationTokenctdefault);TaskHardwareResultReadAsync(SignalObjectinstruction,CancellationTokenctdefault);TaskHardwareResultWriteAsync(SignalObjectinstruction,CancellationTokenctdefault);// 每个驱动独立心跳线程由 Service 层启动TaskStartHeartbeatAsync(CancellationTokenctdefault);// 事件保持兼容eventDeviceEventHandler?BeforePowerOn;eventDeviceEventHandler?BeforePowerOff;eventDeviceEventHandler?DataArrival;eventDeviceEventHandler?StateChanged;// 现代日志注入voidSetLogger(ILoggerlogger);}旧的HardwareAdaptor已废弃全部改为纯接口 依赖注入符合现代 C# 最佳实践。3. 优化后的 XinJePLCDriverMaxWell.Drivers/XinJePLCDriver.cs// MaxWell.Drivers/XinJePLCDriver.csusingHslCommunication.ModBus;usingMaxWell.Interfaces;usingNewtonsoft.Json.Linq;usingSerilog;usingSystem.Text.RegularExpressions;usingSystem.Threading.Channels;namespaceMaxWell.Drivers;publicclassXinJePLCDriver:IHardwareDriver{publicstringDriverNameXinJePLCDriver;publicstringHardwareTypeXinJePLC;publicboolIsConnected_plc?.Connected??false;privateModbusTcpNet?_plc;privatereadonlySemaphoreSlim_semaphorenew(1,1);// 替代 lock支持异步privateILogger_loggerSerilog.Log.Logger;// 默认privatereadonlyChannelWriterHardwareResult_dataWriter;// 数据先写 ChannelprivateCancellationTokenSource?_heartbeatCts;publicXinJePLCDriver(ChannelWriterHardwareResultdataWriter){_dataWriterdataWriter;}publicvoidSetLogger(ILoggerlogger)_loggerlogger;publicasyncTaskInitializeAsync(objectcommunicationInfo,CancellationTokenctdefault){awaitCloseSessionAsync(ct).ConfigureAwait(false);varjoJObject.FromObject(communicationInfo);varipjo[IP]?.ToString()??thrownewArgumentException(IP missing);varportjo[Port]?.Valueint()??502;_plcnewModbusTcpNet(ip,port){DataFormatHslCommunication.Core.DataFormat.CDAB,ConnectTimeOut800,// 心跳超时 800msReceiveTimeOut800};if(jo[Enable]?.Valuebool()true)awaitOpenSessionAsync(ct).ConfigureAwait(false);}publicasyncTaskOpenSessionAsync(CancellationTokenctdefault){if(_plcnull)return;varresultawaitTask.Run(()_plc.ConnectServer(),ct).ConfigureAwait(false);if(!result.IsSuccess)_logger.Error(XinJePLC OpenSession failed: {Msg},result.Message);}publicasyncTaskCloseSessionAsync(CancellationTokenctdefault){_plc?.ConnectClose();}publicasyncValueTaskDisposeAsync(){_heartbeatCts?.Cancel();awaitCloseSessionAsync().ConfigureAwait(false);_plc?.Dispose();_semaphore.Dispose();}// 核心读写 100% 异步 超时 重连 publicasyncTaskHardwareResultReadAsync(SignalObjectinstr,CancellationTokenctdefault){await_semaphore.WaitAsync(ct).ConfigureAwait(false);try{if(_plcnull||!_plc.Connected){awaitOpenSessionAsync(ct).ConfigureAwait(false);}HardwareResultresultinstr.SignalDataType.ToLower()switch{boolMapResult(await_plc.ReadBoolAsync(instr.Address)),int16MapResult(await_plc.ReadInt16Async(instr.Address)),int32MapResult(await_plc.ReadInt32Async(instr.Address)),// 修正原代码错误floatMapResult(await_plc.ReadFloatAsync(instr.Address)),doubleMapResult(await_plc.ReadDoubleAsync(instr.Address)),float[]MapResult(await_plc.ReadFloatAsync(instr.Address,instr.DataLength)),stringMapStringResult(await_plc.ReadStringAsync(instr.Address,instr.DataLength)),byte[]MapByteResult(await_plc.ReadAsync(instr.Address,instr.DataLength)),// 修正原代码空读_newHardwareResult(false,ErrorMessage:未知数据类型)};// 失败自动重连符合 3 次失败重连策略由 Heartbeat 统一控制if(!result.IsSuccess){awaitCloseSessionAsync(ct).ConfigureAwait(false);awaitTask.Delay(100,ct).ConfigureAwait(false);awaitOpenSessionAsync(ct).ConfigureAwait(false);}// 数据先写 Channel再由 Service 异步处理/落盘await_dataWriter.WriteAsync(result,ct).ConfigureAwait(false);returnresult;}catch(Exceptionex){_logger.Error(ex,XinJePLC ReadAsync 异常 {Address},instr.Address);returnnewHardwareResult(false,ErrorMessage:ex.Message,ErrorTime:DateTime.Now);}finally{_semaphore.Release();}}publicasyncTaskHardwareResultWriteAsync(SignalObjectinstr,CancellationTokenctdefault){await_semaphore.WaitAsync(ct).ConfigureAwait(false);try{// 与 Read 类似增加重试 3 次内部 whileintretry0;constintmaxRetry3;OperateResultopnew(){IsSuccessfalse};while(!op.IsSuccessretrymaxRetry){opinstr.SignalDataType.ToLower()switch{boolawait_plc.WriteAsync(instr.Address,Convert.ToBoolean(instr.Value)),int16await_plc.WriteAsync(instr.Address,Convert.ToUInt16(instr.Value)),int32await_plc.WriteAsync(instr.Address,Convert.ToUInt32(instr.Value)),floatawait_plc.WriteAsync(instr.Address,Convert.ToSingle(instr.Value)),stringawaitWriteStringAsync(instr),_newOperateResult{IsSuccessfalse}};if(!op.IsSuccess)awaitTask.Delay(50,ct);}varresultnewHardwareResult(op.IsSuccess,op,ErrorMessage:op.Message);await_dataWriter.WriteAsync(result,ct);returnresult;}finally{_semaphore.Release();}}privateasyncTaskOperateResultWriteStringAsync(SignalObjectinstr){varbytesEncoding.UTF8.GetBytes(instr.Value?.ToString()??);if(bytes.Lengthinstr.DataLength)Array.Resize(refbytes,instr.DataLength);elseif(bytes.Lengthinstr.DataLength)bytesbytes.Concat(newbyte[instr.DataLength-bytes.Length]).ToArray();returnawait_plc.WriteAsync(instr.Address,bytes);}// 心跳独立线程由 Service 层调用publicasyncTaskStartHeartbeatAsync(CancellationTokenctdefault){_heartbeatCtsCancellationTokenSource.CreateLinkedTokenSource(ct);while(!_heartbeatCts.Token.IsCancellationRequested){try{awaitTask.Delay(Random.Shared.Next(3000,5000),_heartbeatCts.Token);// 3~5秒随机varhbawaitReadAsync(newSignalObject(D0,int16),_heartbeatCts.Token);if(!hb.IsSuccess)_logger.Warning(XinJePLC 心跳失败);}catch(Exceptionex)when(exisnotOperationCanceledException){_logger.Error(ex,Heartbeat 异常);}}}privatestaticHardwareResultMapResultT(OperateResultTr)new(r.IsSuccess,r.Content,r.ErrorCode,r.Message,DateTime.Now);privatestaticHardwareResultMapStringResult(OperateResultstringr){if(!r.IsSuccess)returnnewHardwareResult(false,ErrorMessage:r.Message);varcleanRegex.Replace(r.Content??,[^a-zA-Z0-9],);returnnewHardwareResult(true,clean);}privatestaticHardwareResultMapByteResult(OperateResultbyte[]r){if(!r.IsSuccess)returnnewHardwareResult(false,ErrorMessage:r.Message);varstrEncoding.UTF8.GetString(r.Content);varcleanRegex.Replace(str,[^a-zA-Z0-9],);returnnewHardwareResult(true,clean);}}其他 DriverLoadMonitorDriver / RFIDDriver 等结构完全一致只需替换通信协议HslCommunication.Serial 或其他继承IHardwareDriver即可。4. 驱动静态注册MaxWell.Host/DriverRegistry.cspublicstaticclassDriverRegistry{privatestaticreadonlyDictionarystring,FuncIHardwareDriver_factoriesnew();publicstaticvoidRegisterT(stringhardwareType)whereT:IHardwareDriver,new()_factories[hardwareType]()newT();publicstaticIHardwareDriverCreate(stringhardwareType)_factories.TryGetValue(hardwareType,outvarfactory)?factory():thrownewNotSupportedException($未知驱动:{hardwareType});}// Program.cs 中注册示例DriverRegistry.RegisterXinJePLCDriver(XinJePLC);DriverRegistry.RegisterLoadMonitorDriver(LoadMonitor);5. 业务层核心 Service后续可继续提供DataStorageService使用System.Threading.Channels消费数据每 5~10 分钟SQLiteConnection.Checkpoint()强制落盘。AlarmServicePriorityQueueAlarmItem, int 声音 Prism EventAggregator 弹窗 SMTP/短信。ConfigServiceIConfigurationFileSystemWatcher热加载。MemoryMonitorService每分钟Process.GetCurrentProcess().WorkingSet64巡检。WatchdogService软件线程 向 PLC 发送硬件看门狗保活信号。已完成部分现代接口 100% 异步 SemaphoreSlim心跳、重连、超时、Channel、结构化日志、异常全捕获驱动静态注册 独立线程XinJePLCDriver 完整优化版接下来给出DataStorageService Channel SQLite 强制落盘关键数据AlarmService 优先级队列 声音/弹窗/邮件ConfigService JSON 热加载站点硬件可配置WatchdogService软硬件双保险WPF Prism CommunityToolkit.Mvvm Shell ViewModel 示例其他 Driver如 RFIDDriver / ScannerDriver
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2514368.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!