From 16bbeb4f6c55c787bf82840f55c481c6fbb33a06 Mon Sep 17 00:00:00 2001 From: CaesarBao Date: Tue, 20 Jan 2026 10:39:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=AE=BE=E5=A4=87=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E5=AD=98=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SlnMesnac.Config/AppsettingsConfig.cs | 2 +- SlnMesnac.Extensions/RfidFactorySetup.cs | 1 + SlnMesnac.Model/domain/Base_collect_state.cs | 53 +++++++++ SlnMesnac.Model/domain/Base_device_state.cs | 46 ++++++++ SlnMesnac.Model/domain/DeviceInfo.cs | 8 +- .../service/Impl/Real_workdataServiceImpl.cs | 6 +- SlnMesnac.Rfid/ApiServer.cs | 15 +-- SlnMesnac.Rfid/Factory/RflyFactory.cs | 17 +-- SlnMesnac.Rfid/MeshttpClient.cs | 15 +-- SlnMesnac.Rfid/RfidAbsractFactory.cs | 1 + SlnMesnac.Rfid/TouchSocketSetup.cs | 7 +- SlnMesnac.Serilog/SerilogExtensions.cs | 14 +-- SlnMesnac.WPF/App.xaml.cs | 27 ++--- SlnMesnac.WPF/Highway.ico | Bin 0 -> 1150 bytes SlnMesnac.WPF/Icon.png | Bin 0 -> 1153 bytes SlnMesnac.WPF/MainWindow.xaml | 2 +- SlnMesnac.WPF/MainWindow.xaml.cs | 17 +-- SlnMesnac.WPF/SlnMesnac.WPF.csproj | 8 ++ SlnMesnac.WPF/Startup.cs | 2 +- SlnMesnac.WPF/Templates/icon/Highway.ico | Bin 0 -> 1150 bytes .../IndexPage/MiddleWareViewModel.cs | 101 ++++++++++++------ .../ViewModel/MainWindowViewModel.cs | 30 +++--- SlnMesnac.WPF/appsettings.json | 2 +- SlnMesnac.WPF/cloud.ico | Bin 0 -> 67646 bytes 24 files changed, 263 insertions(+), 111 deletions(-) create mode 100644 SlnMesnac.Model/domain/Base_collect_state.cs create mode 100644 SlnMesnac.Model/domain/Base_device_state.cs create mode 100644 SlnMesnac.WPF/Highway.ico create mode 100644 SlnMesnac.WPF/Icon.png create mode 100644 SlnMesnac.WPF/Templates/icon/Highway.ico create mode 100644 SlnMesnac.WPF/cloud.ico diff --git a/SlnMesnac.Config/AppsettingsConfig.cs b/SlnMesnac.Config/AppsettingsConfig.cs index cf41cfd..59c6557 100644 --- a/SlnMesnac.Config/AppsettingsConfig.cs +++ b/SlnMesnac.Config/AppsettingsConfig.cs @@ -33,7 +33,7 @@ namespace SlnMesnac.Config } public bool WriteAppSettings(string session,string key, string value) { - string contentPath = System.IO.Directory.GetCurrentDirectory() + @"\"; ; //项目根目录 + string contentPath = System.IO.Directory.GetCurrentDirectory() + @"\"; //项目根目录 var filePath = contentPath + "appsettings.json"; JObject jsonObject; using (StreamReader file = new StreamReader(filePath)) diff --git a/SlnMesnac.Extensions/RfidFactorySetup.cs b/SlnMesnac.Extensions/RfidFactorySetup.cs index 02591a8..1d7dcd1 100644 --- a/SlnMesnac.Extensions/RfidFactorySetup.cs +++ b/SlnMesnac.Extensions/RfidFactorySetup.cs @@ -56,6 +56,7 @@ namespace SlnMesnac.Extensions string IP = colonIndex != -1 ? item.Connectstr.Substring(0, colonIndex) : item.Connectstr; string Port = colonIndex != -1 ? item.Connectstr.Substring(colonIndex + 1) : item.Connectstr; RfidAbsractFactory _rfid = x.GetService(); + _rfid.deviceid = item.Deviceid; _rfid.ip = IP; _rfid.port = int.Parse(Port); _rfid.ConfigKey = sensor_Infos.Find(x => x.Deviceid == item.Deviceid).Combineid; diff --git a/SlnMesnac.Model/domain/Base_collect_state.cs b/SlnMesnac.Model/domain/Base_collect_state.cs new file mode 100644 index 0000000..5ba0aa0 --- /dev/null +++ b/SlnMesnac.Model/domain/Base_collect_state.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SqlSugar; +namespace Models +{ + /// + /// + /// + [SugarTable("base_collect_state")] + public class Base_collect_state + { + + + /// + /// 备 注: + /// 默认值: + /// + [SugarColumn(ColumnName="Id" ,IsPrimaryKey = true,IsIdentity = true) ] + public int Id { get; set; } + + /// + /// 备 注: + /// 默认值: + /// + [SugarColumn(ColumnName="collectId" ) ] + public string CollectId { get; set; } = null!; + + /// + /// 备 注: + /// 默认值: + /// + [SugarColumn(ColumnName="collectState" ) ] + public int? CollectState { get; set; } + + /// + /// 备 注: + /// 默认值: + /// + [SugarColumn(ColumnName="collectTime" ) ] + public DateTime? CollectTime { get; set; } + + /// + /// 备 注: + /// 默认值: + /// + [SugarColumn(ColumnName="eidtTime" ) ] + public DateTime? EidtTime { get; set; } + + + } + +} \ No newline at end of file diff --git a/SlnMesnac.Model/domain/Base_device_state.cs b/SlnMesnac.Model/domain/Base_device_state.cs new file mode 100644 index 0000000..ee8a245 --- /dev/null +++ b/SlnMesnac.Model/domain/Base_device_state.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SqlSugar; +namespace Models +{ + /// + /// + /// + [SugarTable("base_device_state")] + public class Base_device_state + { + + + /// + /// 备 注: + /// 默认值: + /// + [SugarColumn(ColumnName="Id" ,IsPrimaryKey = true,IsIdentity = true) ] + public int Id { get; set; } + + /// + /// 备 注: + /// 默认值: + /// + [SugarColumn(ColumnName="deviceId" ) ] + public int DeviceId { get; set; } + + /// + /// 备 注:设备连接状态 0为未连接 1为连接 + /// 默认值: + /// + [SugarColumn(ColumnName="deviceState" ) ] + public int? DeviceState { get; set; } + + /// + /// 备 注: + /// 默认值: + /// + [SugarColumn(ColumnName="deviceTime" ) ] + public DateTime? DeviceTime { get; set; } + + + } + +} \ No newline at end of file diff --git a/SlnMesnac.Model/domain/DeviceInfo.cs b/SlnMesnac.Model/domain/DeviceInfo.cs index 24da22e..58de960 100644 --- a/SlnMesnac.Model/domain/DeviceInfo.cs +++ b/SlnMesnac.Model/domain/DeviceInfo.cs @@ -6,12 +6,12 @@ namespace SlnMesnac.Model.domain { public class DeviceInfo { - public string connectstr { get; set; } + public string IPAddress { get; set; } - public string combineid { get; set; } + public string EQUID { get; set; } - public string addr { get; set; } + public string position { get; set; } - public string port { get; set; } + public string ApiPort { get; set; } } } diff --git a/SlnMesnac.Repository/service/Impl/Real_workdataServiceImpl.cs b/SlnMesnac.Repository/service/Impl/Real_workdataServiceImpl.cs index 75eed7f..7a6f312 100644 --- a/SlnMesnac.Repository/service/Impl/Real_workdataServiceImpl.cs +++ b/SlnMesnac.Repository/service/Impl/Real_workdataServiceImpl.cs @@ -27,7 +27,7 @@ namespace SlnMesnac.Repository.service.Impl List taskInfos = null; try { - String sql = "select t1.connectstr, t2.combineid,t1.addr,t3.port from base_device_info t1 left join [dbo].[base_sensor_info] t2 on t1.deviceid = t2.deviceid left join [dbo].[base_collect_info] t3 on t1.collectid = t3.collectId where t1.deleteflag != 1 "; + String sql = "select t1.connectstr as IPAddress, t2.combineid as EQUID,t1.addr as position,t3.port as ApiPort from base_device_info t1 left join [dbo].[base_sensor_info] t2 on t1.deviceid = t2.deviceid left join [dbo].[base_collect_info] t3 on t1.collectid = t3.collectId where t1.deleteflag != 1 "; taskInfos = base._rep.AsTenant().GetConnection("mes").Ado.SqlQuery(sql); } catch (Exception ex) @@ -43,9 +43,9 @@ namespace SlnMesnac.Repository.service.Impl try { List device = new List(); - String sql = " SELECT [port] FROM [WLDB].[dbo].[base_collect_info] where deleteflag != 1 and collectId = "+ collectid; + String sql = " SELECT [port] as ApiPort FROM [WLDB].[dbo].[base_collect_info] where deleteflag != 1 and collectId = " + collectid; device = base._rep.AsTenant().GetConnection("mes").Ado.SqlQuery(sql); - return device[0].port; + return device[0].ApiPort; } catch (Exception ex) { diff --git a/SlnMesnac.Rfid/ApiServer.cs b/SlnMesnac.Rfid/ApiServer.cs index 87f3c36..4a8208d 100644 --- a/SlnMesnac.Rfid/ApiServer.cs +++ b/SlnMesnac.Rfid/ApiServer.cs @@ -10,6 +10,7 @@ using SlnMesnac.Repository.service; using SlnMesnac.Repository.service.@base; using SlnMesnac.Rfid; using SlnMesnac.Rfid.Factory; +using SlnMesnac.Serilog; using SqlSugar; using System; using System.Collections.Generic; @@ -46,7 +47,7 @@ namespace SlnMesnac.TouchSocket { public class ApiServer: RpcServer { - private ILogger _logger; + private readonly SerilogHelper _logger; private List rfidAbsractFactory; private List base_Sensor_Infos; public static Action _RefreshLogMessageAction; @@ -54,7 +55,7 @@ namespace SlnMesnac.TouchSocket private IReal_mesdataService _real_MesdataService; private IReal_workdataService _real_WorkdataService; - public ApiServer(ILogger logger, List rfidAbsractFactory, IReal_mesdataService real_MesdataService, IReal_workdataService real_WorkdataService) + public ApiServer(SerilogHelper logger, List rfidAbsractFactory, IReal_mesdataService real_MesdataService, IReal_workdataService real_WorkdataService) { _logger = logger; this.rfidAbsractFactory = rfidAbsractFactory; @@ -124,7 +125,7 @@ namespace SlnMesnac.TouchSocket // 设置标志位为 true,表示方法正在执行 iFlag = true; _RefreshLogMessageAction?.Invoke("接收MES主动读取指令" + JsonSerializer.Serialize(mesReadPara)); - _logger.LogInformation("接收MES主动读取指令{0}", JsonSerializer.Serialize(mesReadPara)); + _logger.Info("接收MES主动读取指令"+ JsonSerializer.Serialize(mesReadPara)); string FilterData = rfidAbsractFactory.Find(x => x.ConfigKey == mesReadPara.EQUID).FilterData; List rfid = await rfidAbsractFactory.Find(x => x.ConfigKey == mesReadPara.EQUID).GetRFIDAsync(); @@ -177,7 +178,7 @@ namespace SlnMesnac.TouchSocket Msg = Msg, }; _RefreshLogMessageAction?.Invoke("发送MES主动读取指令" + JsonSerializer.Serialize(response)); - _logger.LogInformation("发送MES主动读取指令{0}", JsonSerializer.Serialize(response)); + _logger.Info("发送MES主动读取指令"+ JsonSerializer.Serialize(response)); Real_mesdata real_Mesdata = new Real_mesdata() { Combineid = mesReadPara.EQUID.ToString(), @@ -197,7 +198,7 @@ namespace SlnMesnac.TouchSocket } catch (Exception ex) { - _logger.LogInformation("read接口异常" + ex.ToString()); + _logger.Error("read接口异常" + ex.ToString()); return response; } finally @@ -226,7 +227,7 @@ namespace SlnMesnac.TouchSocket ApiResponse response = new ApiResponse(); _RefreshLogMessageAction?.Invoke("接收MES控制报警灯指令" + JsonSerializer.Serialize(mesAlarmLightPara)); - _logger.LogInformation("接收MES控制报警灯指令{0}", JsonSerializer.Serialize(mesAlarmLightPara)); + _logger.Info("接收MES控制报警灯指令"+ JsonSerializer.Serialize(mesAlarmLightPara)); if (mesAlarmLightPara.Code == "0") { @@ -251,7 +252,7 @@ namespace SlnMesnac.TouchSocket Msg = "sucess", }; _RefreshLogMessageAction?.Invoke("发送MES控制报警灯指令" + JsonSerializer.Serialize(response)); - _logger.LogInformation("发送MES控制报警灯指令{0}", JsonSerializer.Serialize(response)); + _logger.Info("发送MES控制报警灯指令"+ JsonSerializer.Serialize(response)); Real_mesdata real_Mesdata = new Real_mesdata() { Combineid = mesAlarmLightPara.EQUID.ToString(), diff --git a/SlnMesnac.Rfid/Factory/RflyFactory.cs b/SlnMesnac.Rfid/Factory/RflyFactory.cs index dfb8668..0dbfda8 100644 --- a/SlnMesnac.Rfid/Factory/RflyFactory.cs +++ b/SlnMesnac.Rfid/Factory/RflyFactory.cs @@ -7,6 +7,7 @@ using SlnMesnac.Model.dto; using SlnMesnac.Repository.service; using SlnMesnac.Rfid.Dto; using SlnMesnac.Rfid.Enum; +using SlnMesnac.Serilog; using SlnMesnac.TouchSocket; using System; using System.Collections; @@ -44,14 +45,14 @@ namespace SlnMesnac.Rfid.Factory { public class RflyFactory:RfidAbsractFactory { - private ILogger _logger; + private SerilogHelper _logger; private readonly TcpClient _tcpClient = new TcpClient(); private readonly StringChange _stringChange; private string m_strIP; private string m_deviceID; private MeshttpClient _meshttpClient; - public RflyFactory(ILogger logger,StringChange stringChange, MeshttpClient meshttpClient) + public RflyFactory(SerilogHelper logger,StringChange stringChange, MeshttpClient meshttpClient) { _logger = logger; _stringChange = stringChange; @@ -168,7 +169,7 @@ namespace SlnMesnac.Rfid.Factory byte[] reciveBuffer = waitClient.SendThenReturn(pMessagePack.m_pData, timeout); - _logger.LogInformation($"接收原始报文:{_stringChange.bytesToHexStr(reciveBuffer,reciveBuffer.Length)}"); + _logger.Info($"接收原始报文:{_stringChange.bytesToHexStr(reciveBuffer,reciveBuffer.Length)}"); byte[] resultBuffer = PareReceiveBufferData(reciveBuffer,reciveBuffer.Length); @@ -233,10 +234,10 @@ namespace SlnMesnac.Rfid.Factory }); byte[] reciveBuffer = await waitClient.SendThenReturnAsync(pMessagePack.m_pData, timeout); - _logger.LogInformation($"{m_deviceID}发送读取指令{_stringChange.bytesToHexStr(pMessagePack.m_pData,pMessagePack.m_pData.Length)}"); + _logger.Info($"{m_deviceID}发送读取指令{_stringChange.bytesToHexStr(pMessagePack.m_pData,pMessagePack.m_pData.Length)}"); byte[] resultBuffer = PareReceiveBufferData(reciveBuffer, reciveBuffer.Length); - _logger.LogInformation($"{m_deviceID}接收读取指令{_stringChange.bytesToHexStr(resultBuffer,resultBuffer.Length)}"); + _logger.Info($"{m_deviceID}接收读取指令{_stringChange.bytesToHexStr(resultBuffer,resultBuffer.Length)}"); tagInfoList = Device_DealTagInfoList(resultBuffer); @@ -378,10 +379,10 @@ namespace SlnMesnac.Rfid.Factory return false; } }); - _logger.LogInformation($"{m_deviceID}发送修改功率指令{_stringChange.bytesToHexStr(pMessagePack.m_pData, pMessagePack.m_pData.Length)}"); + _logger.Info($"{m_deviceID}发送修改功率指令{_stringChange.bytesToHexStr(pMessagePack.m_pData, pMessagePack.m_pData.Length)}"); byte[] reciveBuffer = await waitClient.SendThenReturnAsync(pMessagePack.m_pData, 2000); - _logger.LogInformation($"{m_deviceID}接收修改功率指令{_stringChange.bytesToHexStr(reciveBuffer, reciveBuffer.Length)}"); + _logger.Info($"{m_deviceID}接收修改功率指令{_stringChange.bytesToHexStr(reciveBuffer, reciveBuffer.Length)}"); //byte[] resultBuffer = PareReceiveBufferData(reciveBuffer, reciveBuffer.Length); if (reciveBuffer[3] == 0x42) @@ -781,7 +782,7 @@ namespace SlnMesnac.Rfid.Factory iFirstPC = iFirstAnt + 1; iFirstLeftBarcketPos = iFirstLeftBarcketPos + iBarcodeLength + 5; - _logger.LogInformation($"----{m_deviceID}函数调用:Device_DealTagInfoList 第[" + (iCommonSecondFlag + 1) + "]次数据解析为:" + tag.EPCstring + ",读取标签次数:[" + tempDataCount + "],标签信号强度:[" + tempDataRSSI + "],天线号:[" + tempDataANT + "]"); + _logger.Info($"----{m_deviceID}函数调用:Device_DealTagInfoList 第[" + (iCommonSecondFlag + 1) + "]次数据解析为:" + tag.EPCstring + ",读取标签次数:[" + tempDataCount + "],标签信号强度:[" + tempDataRSSI + "],天线号:[" + tempDataANT + "]"); iCommonSecondFlag++; if (iCommonSecondFlag == iBarcodeGroupCount) { diff --git a/SlnMesnac.Rfid/MeshttpClient.cs b/SlnMesnac.Rfid/MeshttpClient.cs index 5fd55c2..bdb6ab2 100644 --- a/SlnMesnac.Rfid/MeshttpClient.cs +++ b/SlnMesnac.Rfid/MeshttpClient.cs @@ -8,6 +8,7 @@ using Serilog.Events; using SlnMesnac.Config; using SlnMesnac.Model.AirportApiEntity; using SlnMesnac.Model.domain; +using SlnMesnac.Serilog; using SQLitePCL; using SqlSugar; using System; @@ -26,10 +27,10 @@ namespace SlnMesnac.TouchSocket public class MeshttpClient { private readonly AppConfig _appConfig; - private readonly ILogger _logger; + private readonly SerilogHelper _logger; public static Action RefreshStateEvent; public static Action _RefreshLogMessageAction; - public MeshttpClient(AppConfig appConfig, ILogger logger) + public MeshttpClient(AppConfig appConfig, SerilogHelper logger) { _appConfig = appConfig; _logger = logger; @@ -42,14 +43,14 @@ namespace SlnMesnac.TouchSocket MESHttpClient = new WebApiClient(); try { - _logger.LogInformation("正在连接:" + IpHost); + _logger.Info("正在连接:" + IpHost); MESHttpClient.Connect(IpHost); - _logger.LogInformation(IpHost + "连接成功"); + _logger.Info(IpHost + "连接成功"); return MESHttpClient; } catch (Exception ex) { - _logger.LogError("ERROR: " + ex.Message); + _logger.Info("MES API连接ERROR: " + ex.Message); return null; } } @@ -93,14 +94,14 @@ namespace SlnMesnac.TouchSocket JToken responseValue = MESHttpClient.InvokeT("POST:/autoread", null, requestValue); //JToken responseValue = MESHttpClient.InvokeT("POST:/ApiServer/autoread", null, requestValue); _RefreshLogMessageAction?.Invoke("发送MES自动读取指令"+JsonSerializer.Serialize(requestValue)); - _logger.LogInformation("发送MES自动读取指令{0}", JsonSerializer.Serialize(requestValue)); + _logger.Info("发送MES自动读取指令"+ JsonSerializer.Serialize(requestValue)); RefreshStateEvent?.Invoke(requestValue.EQUID,requestValue.EPCID); return JTokenToEntity>(responseValue); } catch (Exception ex) { - _logger.LogError("ERROR: " + ex.Message); + _logger.Info("autoread ERROR: " + ex.Message); return new ApiResponse(); } diff --git a/SlnMesnac.Rfid/RfidAbsractFactory.cs b/SlnMesnac.Rfid/RfidAbsractFactory.cs index 0cf4329..45f227a 100644 --- a/SlnMesnac.Rfid/RfidAbsractFactory.cs +++ b/SlnMesnac.Rfid/RfidAbsractFactory.cs @@ -35,6 +35,7 @@ namespace SlnMesnac.Rfid public string FilterData; public string ip; public int port; + public string deviceid; public string ConfigKey { get; set; } /// /// 异步建立连接 diff --git a/SlnMesnac.Rfid/TouchSocketSetup.cs b/SlnMesnac.Rfid/TouchSocketSetup.cs index 157b13b..9a1f484 100644 --- a/SlnMesnac.Rfid/TouchSocketSetup.cs +++ b/SlnMesnac.Rfid/TouchSocketSetup.cs @@ -37,16 +37,15 @@ namespace SlnMesnac.TouchSocket public static class TouchSocketSetup { - public static IApplicationBuilder UseTouchSocketExtensions(this IApplicationBuilder app) + public static void UseTouchSocketExtensions(this IServiceProvider service) { //var _server = app.ApplicationServices.GetService(); - var _httpclient = app.ApplicationServices.GetService(); - var _apiServer = app.ApplicationServices.GetService(); + var _httpclient = service.GetService(); + var _apiServer = service.GetService(); _apiServer.Init(); //_server.Init(6001); _httpclient.CreateWebApiClient("172.16.0.106:9880"); //_httpclient.CreateWebApiClient("127.0.0.1:9880"); - return app; } } } \ No newline at end of file diff --git a/SlnMesnac.Serilog/SerilogExtensions.cs b/SlnMesnac.Serilog/SerilogExtensions.cs index 180da7e..622d7f7 100644 --- a/SlnMesnac.Serilog/SerilogExtensions.cs +++ b/SlnMesnac.Serilog/SerilogExtensions.cs @@ -103,7 +103,7 @@ namespace SlnMesnac.Serilog } // 确保各模块日志子目录存在 - string[] subDirectories = { "Info", "Data", "Error", "Debug", "Audit" }; + string[] subDirectories = { "Info", "Data", "Error"}; foreach (var subDir in subDirectories) { string dirPath = Path.Combine(baseLogPath, subDir); @@ -114,12 +114,12 @@ namespace SlnMesnac.Serilog } // 创建当前实例的启动日志文件 - string startupLog = Path.Combine(baseLogPath, "Startup.log"); - File.AppendAllText(startupLog, - $"=== Instance Startup ===\r\n" + - $"Time: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}\r\n" + - $"Base Log Path: {baseLogPath}\r\n" + - $"=================================================================\r\n"); + //string startupLog = Path.Combine(baseLogPath, "Startup.log"); + //File.AppendAllText(startupLog, + // $"=== Instance Startup ===\r\n" + + // $"Time: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}\r\n" + + // $"Base Log Path: {baseLogPath}\r\n" + + // $"=================================================================\r\n"); } catch (Exception ex) { diff --git a/SlnMesnac.WPF/App.xaml.cs b/SlnMesnac.WPF/App.xaml.cs index e363547..2da8c58 100644 --- a/SlnMesnac.WPF/App.xaml.cs +++ b/SlnMesnac.WPF/App.xaml.cs @@ -15,6 +15,8 @@ using System.Reflection; using TouchSocket.Sockets; using SlnMesnac.WPF.Attribute; using SlnMesnac.Rfid; +using SlnMesnac.TouchSocket; +using SlnMesnac.Quartz; namespace SlnMesnac.WPF { @@ -86,6 +88,7 @@ namespace SlnMesnac.WPF // 配置Serilog和其他扩展 ServiceProvider.UseSerilogExtensions(); + ServiceProvider.UseTouchSocketExtensions(); // 获取AppConfig并更新实例特定的配置 var appConfig = ServiceProvider.GetService(); @@ -114,8 +117,8 @@ namespace SlnMesnac.WPF serilog.Info($"应用程序启动 - 实例ID: {_instanceId}, 进程ID: {Process.GetCurrentProcess().Id}"); serilog.Info($"日志目录: {appConfig?.logPath}"); - serilog.Data($"数据目录: {_instanceDataPath}"); - serilog.Error($"日志目录: {appConfig?.logPath}"); + //serilog.Data($"数据目录: {_instanceDataPath}"); + //serilog.Error($"日志目录: {appConfig?.logPath}"); } catch (Exception exception) { @@ -177,7 +180,7 @@ namespace SlnMesnac.WPF //Directory.CreateDirectory(Path.Combine(_instanceDataPath, "Cache")); //Directory.CreateDirectory(Path.Combine(_instanceDataPath, "Temp")); - SaveInstanceInfo(); + //SaveInstanceInfo(); CleanupOldInstances(); } @@ -242,15 +245,15 @@ namespace SlnMesnac.WPF WorkingDirectory = Environment.CurrentDirectory }; - string infoFile = Path.Combine(_instanceDataPath, "instance.info"); - File.WriteAllText(infoFile, - $"Instance ID: {info.InstanceId}\r\n" + - $"Start Time: {info.StartTime}\r\n" + - $"Process ID: {info.ProcessId}\r\n" + - $"Process Name: {info.ProcessName}\r\n" + - $"Machine: {info.MachineName}\r\n" + - $"User: {info.UserName}\r\n" + - $"Working Dir: {info.WorkingDirectory}"); + //string infoFile = Path.Combine(_instanceDataPath, "instance.info"); + //File.WriteAllText(infoFile, + // $"Instance ID: {info.InstanceId}\r\n" + + // $"Start Time: {info.StartTime}\r\n" + + // $"Process ID: {info.ProcessId}\r\n" + + // $"Process Name: {info.ProcessName}\r\n" + + // $"Machine: {info.MachineName}\r\n" + + // $"User: {info.UserName}\r\n" + + // $"Working Dir: {info.WorkingDirectory}"); } catch (Exception ex) { diff --git a/SlnMesnac.WPF/Highway.ico b/SlnMesnac.WPF/Highway.ico new file mode 100644 index 0000000000000000000000000000000000000000..437aaa45d80bfdc7f56efdbf44ca6f23056a34c2 GIT binary patch literal 1150 zcmb7^O-NKx7=}MXB*Mik#6^K!WEe&q=gwd&8BnA}ix$#CLR>@)B|_pVh6r)tV!Q(- zBBGmW5iKgjg@g+iEm{~!MGPX^qEazhL_}1GV9$H!3{2yMbcW}i_kQQR=kGgr% zBF59Rp?b4sGm8TuBBeOhu_Z_)Pr@j?g@Z!cKcwD=7cdy4lPCT)2<A1H$d?EHk`OcO5sOCKa??CsnPj|Ai5UYp&HgC7c z7#l%*du4N|X>WpMm**mS8nmA|_yC7D64@dA-Vw74kxzJE3;=?X7_)U`hGlXChs4tKrt8q literal 0 HcmV?d00001 diff --git a/SlnMesnac.WPF/Icon.png b/SlnMesnac.WPF/Icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1560465576f3ed6859851e46cbfaa7f36a29088e GIT binary patch literal 1153 zcmV-{1b+L8P)OHlTZy?6%WCU`gDotWBe3;0SuzI`SI+anTAQ@!Wo}KY<3?+}Xw z|Gw_)zRzQEg}Ex=$_rRsZ09eCqxPJSborN!>k|2KI*tdMYb=jk2P>z<9x5#)W7SG| zmyr)X=l8)Ae9>NKmCJRoa*Azx_jc$y0xNEXffIpyS}IITLbuu{rXVjHu1(Y%Gnl^C zZW$uHFA_iX(_8f=-i~@JpAe!7kZSJBf|MkvZGatH^~MalK8AuE8KS8JUf3cd3NZyl z;`!I0y-tS6EeQl!x>$|~?~62s$=={EFzWSZ%zN?_rxO;D9a;yDfP{FsF-ZCh@C6C@!wcCf18Zw`OSy}PRI4cS?uE_kYYoCq{^!iKf*_+wC64LyDEz8gPf?*9aL>c9~YX&XkOwM*HU zsey2ez_b*2_Z2y!Vh{8W<0mw@VfQDreAS4@5ilQ^t!aYRR>HESY7oXZga+4gc-L-W z%=WR#5nu|;s5ht9W2$e8wVC_V|7Ig%X#7n6b8m+3MK zrXIdI2)~9*#n2^I(AdJ{!8YDds@>+pXBym*{tZ1Ukd)wA zKA#-;j^Va$K8+=y{F*pkPfaG~ytVz3RA}Qe{n$1O&YmMtTlkFJ^UzV9r0u*XssR1S zFSRp#J~D{H-|&cSv3a4*M!9}0NcU;i#lc3K^CzHyErfD1$W! z4eTO}++y2}xMTsjCALfHHZNxohRNQPkD-J(mN)OSh6!Qb1k5)3AhTsb?d7_yQ+t6X zQLRZ>vR#CraU)~YYh7QJIcFB?d$q0JYDP#zGjPAofWz?%DGJZhtOEWo906TDcBaBKH|1nm1!}rzEdBiS^w_C7fiq>sL@D;H%CdSTAYTHSxdi?JAB`KK ToJ%gE00000NkvXXu0mjfn6xJD literal 0 HcmV?d00001 diff --git a/SlnMesnac.WPF/MainWindow.xaml b/SlnMesnac.WPF/MainWindow.xaml index 2756c3a..9a3f3d6 100644 --- a/SlnMesnac.WPF/MainWindow.xaml +++ b/SlnMesnac.WPF/MainWindow.xaml @@ -5,7 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:SlnMesnac.WPF" mc:Ignorable="d" - Title="汇集软件" WindowStartupLocation="CenterScreen" WindowState="Normal" Height="1000" Width="1420" Topmost="False" Loaded="Window_Loaded" Closing="Window_Closing"> + Title="汇集软件" WindowStartupLocation="CenterScreen" WindowState="Normal" Height="1000" Width="1420" Topmost="False" Loaded="Window_Loaded" Closing="Window_Closing" Icon="/Highway.ico"> diff --git a/SlnMesnac.WPF/MainWindow.xaml.cs b/SlnMesnac.WPF/MainWindow.xaml.cs index 13fbb25..d0b0999 100644 --- a/SlnMesnac.WPF/MainWindow.xaml.cs +++ b/SlnMesnac.WPF/MainWindow.xaml.cs @@ -1,5 +1,8 @@ -using SlnMesnac.Model.AirportApiEntity; +using Microsoft.Extensions.DependencyInjection; +using SlnMesnac.Model.AirportApiEntity; +using SlnMesnac.Serilog; using SlnMesnac.TouchSocket; +using SlnMesnac.WPF.Attribute; using SlnMesnac.WPF.ViewModel; using System; using System.Collections.Generic; @@ -7,18 +10,16 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; +using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; +using System.Windows.Forms; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; -using System.Windows; - -using System.Windows.Forms; -using SlnMesnac.WPF.Attribute; namespace SlnMesnac.WPF { @@ -29,6 +30,7 @@ namespace SlnMesnac.WPF [RegisterAsSingletonAttribute] public partial class MainWindow : Window { + private readonly SerilogHelper _logger; //托盘 NotifyIcon trayIcon; //注册AreaIcon属性,用于托盘的图标 @@ -45,6 +47,7 @@ namespace SlnMesnac.WPF DependencyProperty.Register("AreaMenuItems", typeof(List), typeof(MainWindow), new PropertyMetadata(new List())); public MainWindow() { + _logger = App.ServiceProvider.GetRequiredService(); InitializeComponent(); this.DataContext = new MainWindowViewModel(); @@ -65,12 +68,12 @@ namespace SlnMesnac.WPF private void Window_Loaded(object sender, RoutedEventArgs e) { - + _logger.Info("系统启动!"); } private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { - + _logger.Info("系统关闭!"); } diff --git a/SlnMesnac.WPF/SlnMesnac.WPF.csproj b/SlnMesnac.WPF/SlnMesnac.WPF.csproj index a27b950..9d616c8 100644 --- a/SlnMesnac.WPF/SlnMesnac.WPF.csproj +++ b/SlnMesnac.WPF/SlnMesnac.WPF.csproj @@ -7,10 +7,14 @@ true true 1.0.1.0 + Templates\icon\Highway.ico + + + @@ -19,9 +23,13 @@ PreserveNewest + + + + diff --git a/SlnMesnac.WPF/Startup.cs b/SlnMesnac.WPF/Startup.cs index 66abe93..d0516fd 100644 --- a/SlnMesnac.WPF/Startup.cs +++ b/SlnMesnac.WPF/Startup.cs @@ -83,7 +83,7 @@ namespace SlnMesnac.WPF //启用Serilog中间件 //app.UseSerilogExtensions(); - app.UseTouchSocketExtensions(); + //app.UseTouchSocketExtensions(); //app.UseTouchSocketExtensions(); app.UseRouting(); diff --git a/SlnMesnac.WPF/Templates/icon/Highway.ico b/SlnMesnac.WPF/Templates/icon/Highway.ico new file mode 100644 index 0000000000000000000000000000000000000000..437aaa45d80bfdc7f56efdbf44ca6f23056a34c2 GIT binary patch literal 1150 zcmb7^O-NKx7=}MXB*Mik#6^K!WEe&q=gwd&8BnA}ix$#CLR>@)B|_pVh6r)tV!Q(- zBBGmW5iKgjg@g+iEm{~!MGPX^qEazhL_}1GV9$H!3{2yMbcW}i_kQQR=kGgr% zBF59Rp?b4sGm8TuBBeOhu_Z_)Pr@j?g@Z!cKcwD=7cdy4lPCT)2<A1H$d?EHk`OcO5sOCKa??CsnPj|Ai5UYp&HgC7c z7#l%*du4N|X>WpMm**mS8nmA|_yC7D64@dA-Vw74kxzJE3;=?X7_)U`hGlXChs4tKrt8q literal 0 HcmV?d00001 diff --git a/SlnMesnac.WPF/ViewModel/IndexPage/MiddleWareViewModel.cs b/SlnMesnac.WPF/ViewModel/IndexPage/MiddleWareViewModel.cs index 20fe28b..de4c004 100644 --- a/SlnMesnac.WPF/ViewModel/IndexPage/MiddleWareViewModel.cs +++ b/SlnMesnac.WPF/ViewModel/IndexPage/MiddleWareViewModel.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Models; using SlnMesnac.Config; +using SlnMesnac.Model.domain; using SlnMesnac.Repository; using SlnMesnac.Rfid; using SlnMesnac.TouchSocket; @@ -55,6 +56,7 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage LoadDeviceInfo(); LoadSenorInfo(); StartCheckStatus(); + CollectState(); } /// /// 日志信息 @@ -83,7 +85,7 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage LogMessages.Add($"{DateTime.Now}: {msg}"); while (LogMessages.Count > 10) { - LogMessages.RemoveAt(0); + LogMessages.Clear(); } var orderedList = LogMessages.OrderByDescending(x => x); // 排序后转为 List LogMessages = new ObservableCollection(orderedList); @@ -131,7 +133,7 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage private void LoadDeviceInfo() { - List DeviceInfos = sqlSugarClient.Queryable().Where(expression: x =>x.Collectid == appConfig.StationCode).ToList(); + List DeviceInfos = sqlSugarClient.Queryable().Where(expression: x =>x.Collectid == appConfig.StationCode && x.Deleteflag == 0).ToList(); App.Current.Dispatcher.Invoke(() => { Deviceinfo.Clear(); @@ -152,7 +154,7 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage } private void LoadSenorInfo() { - List SenorInfos = sqlSugarClient.Queryable().ToList(); + List SenorInfos = sqlSugarClient.Queryable().Where(x=>x.Deleteflag == 0).ToList(); Senorinfo.Clear(); foreach (var item in Deviceinfo) { @@ -205,27 +207,83 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage status = await device.ConnectAsync(device.ip, device.port,device.ConfigKey); if (!status) { - Deviceinfo.FirstOrDefault(x => x.Connectstr == $"{device.ip}:{device.port}").IsOnline = "未连接"; + Deviceinfo.FirstOrDefault(x => x.Deviceid == device.deviceid).IsOnline = "未连接"; + } else { - Deviceinfo.FirstOrDefault(x => x.Connectstr == $"{device.ip}:{device.port}").IsOnline = "已连接"; + Deviceinfo.FirstOrDefault(x => x.Deviceid == device.deviceid).IsOnline = "已连接"; } } else { //更新界面状态 - Deviceinfo.FirstOrDefault(x => x.Connectstr == $"{device.ip}:{device.port}").IsOnline = "已连接"; + Deviceinfo.FirstOrDefault(x => x.Deviceid == device.deviceid).IsOnline = "已连接"; + } + //存库,如果没有则插入如果存在则更新 + lock (string.Empty) + { + try + { + List Base_device_state = sqlSugarClient.Ado.Context.CopyNew().Queryable().Where(x => x.DeviceId == int.Parse(device.deviceid)).ToList(); + if (Base_device_state != null && Base_device_state.Count > 0) + { + //只更新 + Base_device_state[0].DeviceState = status ? 1 : 0; + Base_device_state[0].DeviceTime = DateTime.Now; + sqlSugarClient.Ado.Context.CopyNew().Updateable(Base_device_state).UpdateColumns(it => new { it.DeviceState,it.DeviceTime }).ExecuteCommand(); + } + else + { + Base_device_state base_device_state = new Base_device_state() + { + DeviceId = int.Parse(device.deviceid), + DeviceState = status ? 1 : 0, + DeviceTime = DateTime.Now, + }; + var a = sqlSugarClient.Ado.Context.CopyNew().Insertable(base_device_state).ExecuteCommand(); + } + } + catch (Exception ex) + { + _logger.LogError($"更新RFID状态异常:{ex.Message}", ex); + } } - } catch (Exception ex) { - + _logger.LogError($"更新RFID状态异常:{ex.Message}", ex); } } + + private void CollectState() + { + Task.Run(async () => + { + while (true) + { + try + { + #region 汇集软件状态 + Base_collect_state base_Collect_State = new Base_collect_state() + { + CollectId = appConfig.StationCode, + CollectState = 1, + CollectTime = DateTime.Now, + }; + sqlSugarClient.Ado.Context.CopyNew().Insertable(base_Collect_State).ExecuteCommand(); + #endregion 汇集软件状态 + } + catch (Exception ex) + { + _logger.LogError($"更新汇集软件状态异常:{ex.Message}"); + } + await Task.Delay(1000 * 60 * 10); + } + }); + } private void StartCheckStatus() { Task.Run(async () => @@ -253,36 +311,11 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage await Task.Delay(10); } } - //foreach (var rfid in rfidList) - //{ - // if (rfid.ConfigKey == "C031040701") - // { - // } - // bool status = rfid.GetOnlineStatus(); - // if (!status) - // { - // status = await rfid.ConnectAsync(rfid.ip, rfid.port); - // if (!status) - // { - // Deviceinfo.FirstOrDefault(x => x.Connectstr == $"{rfid.ip}:{rfid.port}").IsOnline = "未连接"; - // } - // else - // { - // Deviceinfo.FirstOrDefault(x => x.Connectstr == $"{rfid.ip}:{rfid.port}").IsOnline = "已连接"; - // } - // } - // else - // { - // //更新界面状态 - // Deviceinfo.FirstOrDefault(x => x.Connectstr == $"{rfid.ip}:{rfid.port}").IsOnline = "已连接"; - // } - //} - #endregion RFID状态 } catch (Exception ex) { - //_logger.Error($"监听设备状态异常:{ex.Message}"); + _logger.LogError($"监听设备状态异常:{ex.Message}"); } await Task.Delay(1000 * 30); } diff --git a/SlnMesnac.WPF/ViewModel/MainWindowViewModel.cs b/SlnMesnac.WPF/ViewModel/MainWindowViewModel.cs index 58a8856..d137af9 100644 --- a/SlnMesnac.WPF/ViewModel/MainWindowViewModel.cs +++ b/SlnMesnac.WPF/ViewModel/MainWindowViewModel.cs @@ -8,6 +8,7 @@ using SlnMesnac.Config; using SlnMesnac.Extensions; using SlnMesnac.Plc; using SlnMesnac.Repository.service; +using SlnMesnac.Serilog; using SlnMesnac.TouchSocket; using SlnMesnac.WPF.Attribute; using SlnMesnac.WPF.Page.Generate; @@ -20,11 +21,11 @@ namespace SlnMesnac.WPF.ViewModel [RegisterAsSingletonAttribute] public class MainWindowViewModel: ViewModelBase { - private readonly ILogger _logger; - private readonly ILogger _BaseTaskInfoBusinesslogger; - private IAirportTaskService _Taskservice; - private IAGVStateService _AGVStateService; - private TcpServer _tcpServer; + private readonly SerilogHelper _logger; + //private readonly ILogger _BaseTaskInfoBusinesslogger; + //private IAirportTaskService _Taskservice; + //private IAGVStateService _AGVStateService; + //private TcpServer _tcpServer; //代码生成 //private readonly GenerateControl generateControl = new GenerateControl(); private MiddleWare indexContent = new MiddleWare(); @@ -111,16 +112,16 @@ namespace SlnMesnac.WPF.ViewModel public MainWindowViewModel() { _appConfig = App.ServiceProvider.GetService(); - _logger = App.ServiceProvider.GetService>(); - _Taskservice = App.ServiceProvider.GetService(); - _AGVStateService = App.ServiceProvider.GetService(); - _BaseTaskInfoBusinesslogger = App.ServiceProvider.GetService>(); - _tcpServer = App.ServiceProvider.GetService(); + _logger = App.ServiceProvider.GetRequiredService(); + //_Taskservice = App.ServiceProvider.GetService(); + //_AGVStateService = App.ServiceProvider.GetService(); + //_BaseTaskInfoBusinesslogger = App.ServiceProvider.GetService>(); + //_tcpServer = App.ServiceProvider.GetService(); _airPorthttpClient = App.ServiceProvider.GetService(); - BaseTaskInfoBusiness.GetInstance(_BaseTaskInfoBusinesslogger, _Taskservice, _AGVStateService, _tcpServer, _airPorthttpClient); + //BaseTaskInfoBusiness.GetInstance(_BaseTaskInfoBusinesslogger, _Taskservice, _AGVStateService, _tcpServer, _airPorthttpClient); ControlOnClickCommand = new RelayCommand(obj => ControlOnClick(obj)); FormControlCommand = new RelayCommand(x => FormControl(x)); - _tcpServer.RefreshStateAction+= (_clientIP, _state) => + //_tcpServer.RefreshStateAction+= (_clientIP, _state) => { //if (_clientIP == _appConfig.AMRIP) //{ @@ -128,6 +129,7 @@ namespace SlnMesnac.WPF.ViewModel //} }; UserContent = indexContent; + } /// @@ -176,7 +178,7 @@ namespace SlnMesnac.WPF.ViewModel } catch (Exception ex) { - _logger.LogError("窗体控制逻辑异常", ex); + _logger.Error("窗体控制逻辑异常", ex); } } @@ -201,7 +203,7 @@ namespace SlnMesnac.WPF.ViewModel } catch (Exception ex) { - _logger.LogError("界面跳转逻辑异常", ex); + _logger.Error("界面跳转逻辑异常", ex); } } diff --git a/SlnMesnac.WPF/appsettings.json b/SlnMesnac.WPF/appsettings.json index 48637a6..45fbc93 100644 --- a/SlnMesnac.WPF/appsettings.json +++ b/SlnMesnac.WPF/appsettings.json @@ -9,7 +9,7 @@ "AllowedHosts": "*", "AppConfig": { "logPath": "D:\\net6.0-windows\\log", - "InstanceDataPath": "D:\\net6.0-windows\\InstanceData", + "InstanceDataPath": "D:\\net6.0-windows\\log", "SqlConfig": [ { "configId": "mes", diff --git a/SlnMesnac.WPF/cloud.ico b/SlnMesnac.WPF/cloud.ico new file mode 100644 index 0000000000000000000000000000000000000000..d608918e31215db3f3049527ea8f35b05f27ab95 GIT binary patch literal 67646 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