using Abp.Dependency; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net.NetworkInformation; using System.Threading.Tasks; using ToolLibrary.LogHelper; using Yunda.ISAS.DataMonitoringServer.DataAnalysis; using Yunda.SOMS.DataMonitoringServer.TcpSocket.Server; using YunDa.ISAS.Redis.Repositories; using YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionDeviceInfoDto; namespace Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle { public class ProtectionDeviceDataCenter: ISingletonDependency { public static List _devices; WebApiRequest _webApiRequest; ProtectionDeviceDZDataHandle _protectionDeviceDZDataHandle; ProtectionDeviceVersionHandle _protectionDeviceVersionHandle; ProtectionDeviceIOInfoHandle _protectionDeviceIOInfoHandle; ProtectionDeviceRunInfoHandle _protectionDeviceRunInfoHandle; ProtectionDeviceSelfCheckHandle _protectionDeviceSelfCheckHandle; ProtectionDeviceBCodeHandle _protectionDeviceBCodeHandle; IRedisRepository _deviceBoardStatesRedis; DotNettyTcpServer _dotNettyTcpServer; string deviceBoardStatesRedisKey = "deviceBoardStates"; ConcurrentBag _processes = new ConcurrentBag(); public ProtectionDeviceDataCenter(WebApiRequest webApiRequest , ProtectionDeviceDZDataHandle protectionDeviceDZDataHandle , ProtectionDeviceVersionHandle protectionDeviceVersionHandle , ProtectionDeviceIOInfoHandle protectionDeviceIOInfoHandle , DotNettyTcpServer dotNettyTcpServer , ProtectionDeviceSelfCheckHandle protectionDeviceSelfCheckHandle , ProtectionDeviceRunInfoHandle protectionDeviceRunInfoHandle ,ProtectionDeviceBCodeHandle protectionDeviceBCodeHandle , IRedisRepository deviceBoardStatesRedis ) { _webApiRequest = webApiRequest; _protectionDeviceDZDataHandle = protectionDeviceDZDataHandle; _protectionDeviceVersionHandle = protectionDeviceVersionHandle; _protectionDeviceIOInfoHandle = protectionDeviceIOInfoHandle; _dotNettyTcpServer = dotNettyTcpServer; _protectionDeviceRunInfoHandle = protectionDeviceRunInfoHandle; _deviceBoardStatesRedis = deviceBoardStatesRedis; _protectionDeviceSelfCheckHandle = protectionDeviceSelfCheckHandle; } public void InitDevices() { try { _devices = _webApiRequest.GetProtectionDeviceCommInfos("神池南"); } catch (Exception ex) { Log4Helper.Error(this.GetType(), "初始化装置IO错误", ex); } } public List ProtectionDeviceComms { get; set; } public async Task InitProtectionDeviceComms() { MonitoringEventBus.LogHandler("开始启动103客户端", "装置定值"); await Task.Run(async () => { List devices = _webApiRequest.GetProtectionDeviceCommInfos("神池南"); if (devices == null) { MonitoringEventBus.LogHandler("没有获取到装置数据", "获取信息"); return; } _protectionDeviceDZDataHandle.Init(devices); MonitoringEventBus.LogHandler($"共获取{devices.Count}条装置数据", "装置定值"); string currentDirectory = AppDomain.CurrentDomain.BaseDirectory; string sourceDirectory = Path.Combine(currentDirectory, "DeviceComm"); string destDirectoryBase = Path.Combine(currentDirectory, "DeviceComms", "DeviceComm"); // 定义一个并行处理每个设备的过程 Parallel.ForEach(devices, device => { try { var online = IsDeviceOnline(device.GatewayIP1); if (online) { string destDirectory = $"{destDirectoryBase}_{device.DeviceAddr}"; CopyDirectory(sourceDirectory, destDirectory); string configFilePath = Path.Combine(destDirectory, "cfg", "scmgateway.ini"); ModifyDeviceAddrInConfig(configFilePath, device.GatewayIP1, device.DeviceAddr); string exePath = Path.Combine(destDirectory, "scmgateway.exe"); var process = StartExe(exePath); if (process != null) { MonitoringEventBus.LogHandler($"装置地址:{device.DeviceAddr},ip:{device.GatewayIP1} 启动成功", "装置定值"); _processes.Add(process); } } else { MonitoringEventBus.LogHandler($"装置地址:{device.DeviceAddr},ip:{device.GatewayIP1} {(online ? "在线" : "离线")}", "装置定值"); } } catch (Exception ex) { MonitoringEventBus.LogHandler($"{ex.Message}", "错误信息"); } }); MonitoringEventBus.LogHandler("开始启动TCP服务端", "装置定值"); await _dotNettyTcpServer.RunServerAsync(); }); } Process StartExe(string exePath) { try { var process = new Process { StartInfo = new ProcessStartInfo { WorkingDirectory = Path.GetDirectoryName(exePath), // 设置工作目录为exe所在目录 FileName = exePath, CreateNoWindow = true, UseShellExecute = false } }; process.Start(); return process; } catch (Exception ex) { MonitoringEventBus.LogHandler($"启动 {exePath} 失败: {ex.Message}", "错误信息"); return null; } } public void StopAllProcesses() { foreach (var process in _processes) { try { if (!process.HasExited) { process.Kill(); process.WaitForExit(); } } catch (Exception ex) { MonitoringEventBus.LogHandler($"停止进程失败: {ex.Message}", "错误信息"); } } } // 通过 Ping 判断设备是否在线 private bool IsDeviceOnline(string ipAddress) { try { if (ipAddress == "127.0.0.1"|| ipAddress == "localhost") { return false; } using (Ping ping = new Ping()) { // 发送 Ping 请求,设置超时时间为 1000 毫秒 (1秒) PingReply reply = ping.Send(ipAddress, 1000); // 如果状态是成功,则设备在线 return reply.Status == IPStatus.Success; } } catch (PingException) { // 如果发生异常,设备不可达(例如网络断开) return false; } } private void CopyDirectory(string sourceDir, string destDir) { var dir = new DirectoryInfo(sourceDir); if (!dir.Exists) { throw new DirectoryNotFoundException($"源目录不存在或无法找到: {sourceDir}"); } if (Directory.Exists(destDir)) { //如果目标目录存在,则直接跳过复制 return; } DirectoryInfo[] dirs = dir.GetDirectories(); Directory.CreateDirectory(destDir); foreach (FileInfo file in dir.GetFiles()) { string targetFilePath = Path.Combine(destDir, file.Name); file.CopyTo(targetFilePath, true); } foreach (DirectoryInfo subDir in dirs) { string newDestinationDir = Path.Combine(destDir, subDir.Name); CopyDirectory(subDir.FullName, newDestinationDir); } } private void ModifyDeviceAddrInConfig(string configFilePath, string gatewayIP1,int protectAddr) { if (File.Exists(configFilePath)) { var lines = File.ReadAllLines(configFilePath); for (int i = 0; i < lines.Length; i++) { if (lines[i].StartsWith("[Device]")) { for (int j = i + 1; j < lines.Length; j++) { if (lines[j].StartsWith("deviceAddr=")) { lines[j] = $"deviceAddr={gatewayIP1}"; } if (lines[j].StartsWith("protectAddr=")) { lines[j] = $"protectAddr={protectAddr}"; } } break; } } File.WriteAllLines(configFilePath, lines); } else { Debug.WriteLine($"文件未找到: {configFilePath}"); } } } }