From 8de7cbb4d933cbefcab67944c59bd19d16ae17a0 Mon Sep 17 00:00:00 2001 From: SoulStar Date: Sat, 11 Apr 2026 09:25:05 +0800 Subject: [PATCH] =?UTF-8?q?feat=20-=20MES=E4=BA=A4=E4=BA=92=E5=AE=8C?= =?UTF-8?q?=E5=96=84=EF=BC=8CCFX=E9=80=9A=E8=AE=AF=E5=BE=85=E5=91=BD?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E7=83=A4=E7=AE=B1=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E9=93=BE=E6=8E=A5BUG=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=9B=B4?= =?UTF-8?q?=E5=A4=9A=E6=97=A5=E5=BF=97=E6=98=BE=E7=A4=BA=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sln.Iot.Business/BusinessStart.cs | 4 +- Sln.Iot.Business/ErrorAnalyseBusiness.cs | 56 ++- Sln.Iot.Business/MesReportBusiness.cs | 437 ++++++++++++++++-- Sln.Iot.Business/RFID01Business.cs | 9 + Sln.Iot.Business/RFID06Business.cs | 3 + Sln.Iot.Business/RecipeBusiness.cs | 2 +- Sln.Iot.CFX/CFXHelper.cs | 11 +- Sln.Iot.Common/GlobalVar.cs | 25 +- Sln.Iot.Common/Sln.Iot.Common.csproj | 1 + Sln.Iot.Config/AppConfig.cs | 30 ++ Sln.Iot.Model/Entity/MesReportEntity.cs | 89 ++++ .../service/OvenPlcDataService.cs | 54 ++- Sln.Iot.Socket/DeltaHttpClient.cs | 25 +- Sln.Iot.Test/UnitTest1.cs | 37 +- Sln.Iot/Program.cs | 9 + Sln.Iot/appsettings.json | 18 +- 16 files changed, 720 insertions(+), 90 deletions(-) create mode 100644 Sln.Iot.Model/Entity/MesReportEntity.cs diff --git a/Sln.Iot.Business/BusinessStart.cs b/Sln.Iot.Business/BusinessStart.cs index f0c59c6..5ca60e1 100644 --- a/Sln.Iot.Business/BusinessStart.cs +++ b/Sln.Iot.Business/BusinessStart.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -19,6 +20,7 @@ namespace Sln.Iot.Business private RFID06Business _rfid06; private ErrorAnalyseBusiness _errorAnalyse; private RecipeBusiness _recipeBusiness; + private MesReportBusiness _mesReportBusiness; public BusinessStart() { _rfid01 = new RFID01Business(); @@ -29,7 +31,7 @@ namespace Sln.Iot.Business _rfid06 = new RFID06Business(); _errorAnalyse = new ErrorAnalyseBusiness(); _recipeBusiness = new RecipeBusiness(); - + _mesReportBusiness = new MesReportBusiness(); } } } diff --git a/Sln.Iot.Business/ErrorAnalyseBusiness.cs b/Sln.Iot.Business/ErrorAnalyseBusiness.cs index ff1c48d..ea147e9 100644 --- a/Sln.Iot.Business/ErrorAnalyseBusiness.cs +++ b/Sln.Iot.Business/ErrorAnalyseBusiness.cs @@ -1,21 +1,22 @@ -using System; +using Amqp; +using CFX; +using CFX.ResourcePerformance; +using CFX.Structures; +using HslCommunication; +using Sln.Iot.Business.Entity; +using Sln.Iot.CFX.CFXConnect; +using Sln.Iot.CFX.Event; +using Sln.Iot.Config; +using Sln.Iot.PLC; +using Sln.Iot.Repository.dao; +using Sln.Iot.Repository.service; +using Sln.Iot.Serilog; +using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using Sln.Iot.PLC; -using HslCommunication; -using System.Collections; -using Sln.Iot.Business.Entity; -using Sln.Iot.Repository.service; -using Sln.Iot.Repository.dao; -using Sln.Iot.CFX.CFXConnect; -using CFX.ResourcePerformance; -using Sln.Iot.CFX.Event; -using CFX; -using CFX.Structures; -using Sln.Iot.Serilog; -using Amqp; using TouchSocket.Core; namespace Sln.Iot.Business @@ -26,6 +27,7 @@ namespace Sln.Iot.Business private readonly PLCConnect _plc = PLCConnect.Instance; private readonly SerilogHelper _log = SerilogHelper.Instance; + private readonly AppConfig _appConfig = AppConfigSetting.Load(); private readonly ErrorService errorService = ErrorService.Instance; private readonly TrayBindingService trayBindingService = TrayBindingService.Instance; @@ -39,7 +41,7 @@ namespace Sln.Iot.Business public ErrorAnalyseBusiness() { - _timer = new Timer(TimerCallback, null, 0, 2000); + _timer = new Timer(TimerCallback, null, 0, 3000); } /// @@ -120,7 +122,8 @@ namespace Sln.Iot.Business Guid logGuid = Guid.NewGuid(); errorService.InsertVacuum1Error(logGuid.ToString(), errorMessage.ENAlarmMessage, errorMessage.CNAlarmMessage, errorMessage.ErrorCode); connect1.PublishEvent(new CFXEnvelope(faultOccurredEvent.Handle(errorMessage.ErrorCode, LevelTrans(errorMessage.AlarmDegarde), logGuid, errorMessage.ENAlarmMessage + "-Vacuum1", transID))); - _log.Info($"真空箱1报警发生 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); + if (_appConfig.IsAlarmLog) + _log.Info($"真空箱1报警发生 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); } } else @@ -132,7 +135,8 @@ namespace Sln.Iot.Business string delGuid = errorService.DeleteVacuum1Error(errorMessage.ENAlarmMessage); Guid.TryParse(delGuid, out Guid guidRes); connect1.PublishEvent(new CFXEnvelope(faultClearedEvent.Handle(guidRes))); - _log.Info($"真空箱1报警消除 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); + if (_appConfig.IsAlarmLog) + _log.Info($"真空箱1报警消除 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); } } } @@ -158,7 +162,8 @@ namespace Sln.Iot.Business Guid logGuid = Guid.NewGuid(); errorService.InsertVacuum2Error(logGuid.ToString(), errorMessage.ENAlarmMessage, errorMessage.CNAlarmMessage, errorMessage.ErrorCode); connect1.PublishEvent(new CFXEnvelope(faultOccurredEvent.Handle(errorMessage.ErrorCode, LevelTrans(errorMessage.AlarmDegarde), logGuid, errorMessage.ENAlarmMessage + "-Vacuum2", transID))); - _log.Info($"真空箱2报警发生 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); + if (_appConfig.IsAlarmLog) + _log.Info($"真空箱2报警发生 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); } } else @@ -170,7 +175,8 @@ namespace Sln.Iot.Business string delGuid = errorService.DeleteVacuum2Error(errorMessage.ENAlarmMessage); Guid.TryParse(delGuid, out Guid guidRes); connect1.PublishEvent(new CFXEnvelope(faultClearedEvent.Handle(guidRes))); - _log.Info($"真空箱2报警消除 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); + if (_appConfig.IsAlarmLog) + _log.Info($"真空箱2报警消除 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); } } } @@ -196,7 +202,8 @@ namespace Sln.Iot.Business Guid logGuid = Guid.NewGuid(); errorService.InsertLiftError(logGuid.ToString(), errorMessage.ENAlarmMessage, errorMessage.CNAlarmMessage, errorMessage.ErrorCode); connect2.PublishEvent(new CFXEnvelope(faultOccurredEvent.Handle(errorMessage.ErrorCode, LevelTrans(errorMessage.AlarmDegarde), logGuid, errorMessage.ENAlarmMessage, transID))); - _log.Info($"提升机报警发生 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); + if (_appConfig.IsAlarmLog) + _log.Info($"提升机报警发生 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); } } else @@ -208,7 +215,8 @@ namespace Sln.Iot.Business string delGuid = errorService.DeleteliftError(errorMessage.ENAlarmMessage); Guid.TryParse(delGuid, out Guid guidRes); connect2.PublishEvent(new CFXEnvelope(faultClearedEvent.Handle(guidRes))); - _log.Info($"提升机报警消除 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); + if (_appConfig.IsAlarmLog) + _log.Info($"提升机报警消除 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); } } } @@ -234,7 +242,8 @@ namespace Sln.Iot.Business Guid logGuid = Guid.NewGuid(); errorService.InsertOvenError(logGuid.ToString(), errorMessage.ENAlarmMessage, errorMessage.CNAlarmMessage, errorMessage.ErrorCode); connect3.PublishEvent(new CFXEnvelope(faultOccurredEvent.Handle(errorMessage.ErrorCode, LevelTrans(errorMessage.AlarmDegarde), logGuid, errorMessage.ENAlarmMessage, transID))); - _log.Info($"烤箱报警发生 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); + if (_appConfig.IsAlarmLog) + _log.Info($"烤箱报警发生 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); } } else @@ -246,7 +255,8 @@ namespace Sln.Iot.Business string delGuid = errorService.DeleteOvenError(errorMessage.ENAlarmMessage); Guid.TryParse(delGuid, out Guid guidRes); connect3.PublishEvent(new CFXEnvelope(faultClearedEvent.Handle(guidRes))); - _log.Info($"烤箱报警消除 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); + if (_appConfig.IsAlarmLog) + _log.Info($"烤箱报警消除 内容:{errorMessage.CNAlarmMessage} 级别:{errorMessage.AlarmDegarde.GetDescription()}"); } } } diff --git a/Sln.Iot.Business/MesReportBusiness.cs b/Sln.Iot.Business/MesReportBusiness.cs index 7036e12..8cc9a39 100644 --- a/Sln.Iot.Business/MesReportBusiness.cs +++ b/Sln.Iot.Business/MesReportBusiness.cs @@ -1,4 +1,12 @@ -using Microsoft.AspNetCore.Http; +using CFX; +using CFX.Structures; +using Microsoft.AspNetCore.Http; +using Sln.Iot.Business.Entity; +using Sln.Iot.CFX.CFXConnect; +using Sln.Iot.CFX.Event; +using Sln.Iot.Common; +using Sln.Iot.Config; +using Sln.Iot.Model.Entity; using Sln.Iot.PLC; using Sln.Iot.Serilog; using Sln.Iot.Socket; @@ -16,58 +24,123 @@ namespace Sln.Iot.Business private Timer _timer; private readonly SerilogHelper _log = SerilogHelper.Instance; private readonly DeltaHttpClient _deltaHttpClient = DeltaHttpClient.Instance; + private readonly AppConfig _appConfig = AppConfigSetting.Load(); + private readonly PLCConnect _plc = PLCConnect.Instance; - public string InterfaceID; - public string Status = "0"; - public string StatusCode = "0"; - - public int PassQuantity = 0; - public int FailQuantity = 0; - public string ErrorCount = "0"; - public string ErrorTime = "0"; - public double CycleTime = 0; - public double RunningTime = 0; - public double WaitingTime = 0; - public int InputQuantity = 0; - public string Barcode = "0"; - public int Cya = 0; + CFXConnect1 _cfxHelper = CFXConnect1.Instance; + CFXConnect2 _cfxHelper2 = CFXConnect2.Instance; + CFXConnect3 _cfxHelper3 = CFXConnect3.Instance; + CFXConnect4 _cfxHelper4 = CFXConnect4.Instance; + StationParametersModifiedEvent stationParametersModifiedEvent = new StationParametersModifiedEvent(); public MesReportBusiness() { _deltaHttpClient.Init(); - _timer = new Timer(TimerCallback, null, 0, 1000*15); + _timer = new Timer(TimerCallback, null, 0, 1000 * 15); } public void TimerCallback(object? state) { - _deltaHttpClient.PostRequestSend(tranter()); + ErrorGet(1); + _deltaHttpClient.PostRequestSend(tranter(GlobalVar.Connect1Entity)); + ErrorGet(2); + _deltaHttpClient.PostRequestSend(tranter(GlobalVar.Connect2Entity)); + ErrorGet(3); + _deltaHttpClient.PostRequestSend(tranter(GlobalVar.Connect3Entity)); + ErrorGet(4); + _deltaHttpClient.PostRequestSend(tranter(GlobalVar.Connect4Entity)); + + _cfxHelper.PublishEvent(new CFXEnvelope(stationParametersModifiedEvent.Handle(ParameterSet(GlobalVar.Connect1Entity.InterfaceID, + "制程设备", + GlobalVar.Connect1Entity.Status, + GlobalVar.Connect1Entity.Status, + GlobalVar.Connect1Entity.StatusCode, + GlobalVar.Connect1Entity.PassQuantity.ToString(), + GlobalVar.Connect1Entity.FailQuantity.ToString(), + GlobalVar.Connect1Entity.CycleTime.ToString(), + GlobalVar.Connect1Entity.RunningTime.ToString(), + GlobalVar.Connect1Entity.WaitingTime.ToString(), + "1", + GlobalVar.Connect1Entity.InputQuantity.ToString(), + GlobalVar.Connect1Entity.ErrorCount.ToString(), + GlobalVar.Connect1Entity.ErrorTime.ToString() + )))); + + _cfxHelper2.PublishEvent(new CFXEnvelope(stationParametersModifiedEvent.Handle(ParameterSet(GlobalVar.Connect2Entity.InterfaceID, + "制程设备", + GlobalVar.Connect2Entity.Status, + GlobalVar.Connect2Entity.Status, + GlobalVar.Connect2Entity.StatusCode, + GlobalVar.Connect2Entity.PassQuantity.ToString(), + GlobalVar.Connect2Entity.FailQuantity.ToString(), + GlobalVar.Connect2Entity.CycleTime.ToString(), + GlobalVar.Connect2Entity.RunningTime.ToString(), + GlobalVar.Connect2Entity.WaitingTime.ToString(), + "1", + GlobalVar.Connect2Entity.InputQuantity.ToString(), + GlobalVar.Connect2Entity.ErrorCount.ToString(), + GlobalVar.Connect2Entity.ErrorTime.ToString() + )))); + + _cfxHelper3.PublishEvent(new CFXEnvelope(stationParametersModifiedEvent.Handle(ParameterSet(GlobalVar.Connect3Entity.InterfaceID, + "制程设备", + GlobalVar.Connect3Entity.Status, + GlobalVar.Connect3Entity.Status, + GlobalVar.Connect3Entity.StatusCode, + GlobalVar.Connect3Entity.PassQuantity.ToString(), + GlobalVar.Connect3Entity.FailQuantity.ToString(), + GlobalVar.Connect3Entity.CycleTime.ToString(), + GlobalVar.Connect3Entity.RunningTime.ToString(), + GlobalVar.Connect3Entity.WaitingTime.ToString(), + "1", + GlobalVar.Connect3Entity.InputQuantity.ToString(), + GlobalVar.Connect3Entity.ErrorCount.ToString(), + GlobalVar.Connect3Entity.ErrorTime.ToString() + )))); + + _cfxHelper4.PublishEvent(new CFXEnvelope(stationParametersModifiedEvent.Handle(ParameterSet(GlobalVar.Connect4Entity.InterfaceID, + "制程设备", + GlobalVar.Connect4Entity.Status, + GlobalVar.Connect4Entity.Status, + GlobalVar.Connect4Entity.StatusCode, + GlobalVar.Connect4Entity.PassQuantity.ToString(), + GlobalVar.Connect4Entity.FailQuantity.ToString(), + GlobalVar.Connect4Entity.CycleTime.ToString(), + GlobalVar.Connect4Entity.RunningTime.ToString(), + GlobalVar.Connect4Entity.WaitingTime.ToString(), + "1", + GlobalVar.Connect4Entity.InputQuantity.ToString(), + GlobalVar.Connect4Entity.ErrorCount.ToString(), + GlobalVar.Connect4Entity.ErrorTime.ToString() + )))); } - private string tranter() + private string tranter(MesReportEntity entity) { + entity.CycleTime = _appConfig.CycleTime; + entity.RunningTime = (int)(DateTime.Now - GlobalVar.OpenTime).TotalSeconds; #region 傳送字的資料 string strSendData; strSendData = "[{"; // strSendData += "\"factory\":\"" + "DG5" + "\","; - strSendData += "\"interfaceID\":\"" + InterfaceID + "\","; + strSendData += "\"interfaceID\":\"" + entity.InterfaceID + "\","; // strSendData += "\"EquipType\":" + EquipType + ","; - strSendData += "\"status\":" + Status + ","; - strSendData += "\"statusCode\":\"" + StatusCode + "\","; - strSendData += "\"passQty\":" + PassQuantity + ","; - strSendData += "\"failQty\":" + FailQuantity + ","; - strSendData += "\"errorCnt\":" + ErrorCount + ","; - strSendData += "\"errorTimes\":" + ErrorTime + ","; - strSendData += "\"cycleTime\":" + CycleTime + ","; - strSendData += "\"runningTime\":" + RunningTime + ","; - strSendData += "\"waitingTime\":" + WaitingTime + ","; + strSendData += "\"status\":" + entity.Status + ","; + strSendData += "\"statusCode\":\"" + entity.StatusCode + "\","; + strSendData += "\"passQty\":" + entity.PassQuantity + ","; + strSendData += "\"failQty\":" + entity.FailQuantity + ","; + strSendData += "\"errorCnt\":" + entity.ErrorCount + ","; + strSendData += "\"errorTimes\":" + entity.ErrorTime + ","; + strSendData += "\"cycleTime\":" + entity.CycleTime + ","; + strSendData += "\"runningTime\":" + entity.RunningTime + ","; + strSendData += "\"waitingTime\":" + entity.WaitingTime + ","; // strSendData += "\"selfCheck\":" + (SELFCHECK ? "1" : "0") + ","; strSendData += "\"selfCheck\":" + "1" + ","; - strSendData += "\"inputQty\":" + InputQuantity + ","; - strSendData += "\"barcode\":\"" + Barcode + "\","; - strSendData += "\"model\":\"" + Cya + "\","; + strSendData += "\"inputQty\":" + entity.InputQuantity + ","; + strSendData += "\"barcode\":\"" + entity.Barcode + "\","; + strSendData += "\"model\":\"" + entity.Cya + "\","; - //端子壽命 strSendData += "\"paramList\":["; // strSendData += "{\"paramCode\":\"" + Key1 + "\","; // strSendData += "\"paramValue\":\"" + Value1 + "\"},"; @@ -80,11 +153,307 @@ namespace Sln.Iot.Business strSendData += "]"; strSendData += "}]"; + _cfxHelper.PublishEvent(new CFXEnvelope(stationParametersModifiedEvent.Handle(ParameterSet(entity.InterfaceID, + "制程设备", + entity.Status, + entity.Status, + entity.StatusCode, + entity.PassQuantity.ToString(), + entity.FailQuantity.ToString(), + entity.CycleTime.ToString(), + entity.RunningTime.ToString(), + entity.WaitingTime.ToString(), + "1", + entity.InputQuantity.ToString(), + entity.ErrorCount.ToString(), + entity.ErrorTime.ToString() + )))); + #endregion return strSendData; + } + + /// + /// 设备状态获取 + /// + /// + private void ErrorGet(int deviceNo) + { + string status = "0"; + string statusCode = "0"; + if (deviceNo == 1) + { + var r1 = _plc.ReadInt16(_plc.DeltaInstance1, "D15176"); + var r2 = _plc.ReadInt16(_plc.DeltaInstance2, "D15176"); + if (r1.IsSuccess && r2.IsSuccess) + { + if (r1.Content == 0 && r2.Content == 0) + { + GlobalVar.Connect1Entity.StatusCode = "0"; + GlobalVar.Connect1Entity.Status = StatusJudge(0).ToString(); + } + else if (r1.Content != 0) + { + GlobalVar.Connect1Entity.StatusCode = r1.Content.ToString(); + GlobalVar.Connect1Entity.Status = StatusJudge(r1.Content).ToString(); + } + else if (r2.Content != 0) + { + GlobalVar.Connect1Entity.StatusCode = r2.Content.ToString(); + GlobalVar.Connect1Entity.Status = StatusJudge(r2.Content).ToString(); + } + if (GlobalVar.Connect1Entity.Status == "1") + { + if (GlobalVar.Connect1Entity.IsError == false) + { + GlobalVar.Connect1Entity.ErrorCount++; + GlobalVar.Connect1Entity.LastErrorTime = DateTime.Now; + GlobalVar.Connect1Entity.IsError = true; + } + else + { + GlobalVar.Connect1Entity.ErrorTime = (int)(DateTime.Now - GlobalVar.Connect1Entity.LastErrorTime).TotalSeconds; + } + } + else + { + if (GlobalVar.Connect1Entity.IsError == true) + { + GlobalVar.Connect1Entity.IsError = false; + } + } + } + else + { + _log.Error($"读取PLC状态失败: 真空箱1{r1.IsSuccess} - {r1.Message}; 真空箱2{r2.IsSuccess} - {r2.Message}"); + } + } + else if (deviceNo == 2) + { + var r1 = _plc.ReadInt16(_plc.DeltaInstance3, "D15176"); + if (r1.IsSuccess) + { + GlobalVar.Connect2Entity.StatusCode = r1.Content.ToString(); + GlobalVar.Connect2Entity.Status = StatusJudge(r1.Content).ToString(); + + if (GlobalVar.Connect2Entity.Status == "1") + { + if (GlobalVar.Connect2Entity.IsError == false) + { + GlobalVar.Connect2Entity.ErrorCount++; + GlobalVar.Connect2Entity.LastErrorTime = DateTime.Now; + GlobalVar.Connect2Entity.IsError = true; + } + else + { + GlobalVar.Connect2Entity.ErrorTime = (int)(DateTime.Now - GlobalVar.Connect2Entity.LastErrorTime).TotalSeconds; + } + } + else + { + if (GlobalVar.Connect2Entity.IsError == true) + { + GlobalVar.Connect2Entity.IsError = false; + } + } + } + else + { + _log.Error($"读取PLC状态失败: 上料提升机{r1.IsSuccess} - {r1.Message}"); + } + } + else if (deviceNo == 3) + { + var r1 = _plc.ReadInt16(_plc.DeltaInstance0, "D15176"); + if (r1.IsSuccess) + { + GlobalVar.Connect3Entity.StatusCode = r1.Content.ToString(); + GlobalVar.Connect3Entity.Status = StatusJudge(r1.Content).ToString(); + + if (GlobalVar.Connect3Entity.Status == "1") + { + if (GlobalVar.Connect3Entity.IsError == false) + { + GlobalVar.Connect3Entity.ErrorCount++; + GlobalVar.Connect3Entity.LastErrorTime = DateTime.Now; + GlobalVar.Connect3Entity.IsError = true; + } + else + { + GlobalVar.Connect3Entity.ErrorTime = (int)(DateTime.Now - GlobalVar.Connect3Entity.LastErrorTime).TotalSeconds; + } + } + else + { + if (GlobalVar.Connect3Entity.IsError == true) + { + GlobalVar.Connect3Entity.IsError = false; + } + } + } + else + { + _log.Error($"读取PLC状态失败: 烤箱{r1.IsSuccess} - {r1.Message}"); + } + } + else if (deviceNo == 4) + { + var r1 = _plc.ReadInt16(_plc.DeltaInstance4, "D15176"); + if (r1.IsSuccess) + { + GlobalVar.Connect4Entity.StatusCode = r1.Content.ToString(); + GlobalVar.Connect4Entity.Status = StatusJudge(r1.Content).ToString(); + + if (GlobalVar.Connect4Entity.Status == "1") + { + if (GlobalVar.Connect4Entity.IsError == false) + { + GlobalVar.Connect4Entity.ErrorCount++; + GlobalVar.Connect4Entity.LastErrorTime = DateTime.Now; + GlobalVar.Connect4Entity.IsError = true; + } + else + { + GlobalVar.Connect4Entity.ErrorTime = (int)(DateTime.Now - GlobalVar.Connect4Entity.LastErrorTime).TotalSeconds; + } + } + else + { + if (GlobalVar.Connect4Entity.IsError == true) + { + GlobalVar.Connect4Entity.IsError = false; + } + } + } + else + { + _log.Error($"读取PLC状态失败: 下料提升机{r1.IsSuccess} - {r1.Message}"); + } + } + + //return (status, statusCode); + } + + private void ErrorJudge(bool errorSituation) + { } + + /// + /// 根据StatusCode判断Status + /// + /// + /// + private int StatusJudge(int sc) + { + if (sc == -1 || sc == 2) + { + return 0; + } + if (sc == 1 || sc == 10 || sc == 11) + { + return 1; + } + if (sc == 12) + { + return 10; + } + return 4; + } + + /// + /// stationParameters参数设置 + /// + public List ParameterSet( + string interfaceID, + string equipType, + string status, + string light, + string statusCode, + string passQty, + string failQty, + string cycleTime, + string runningTime, + string waitingTime, + string selfCheck, + string inputQty, + string errorCnt, + string errorTimes + ) + { + return new List() + { + new GenericParameter() + { + Name = "InterfaceID", + Value = interfaceID + }, + new GenericParameter() + { + Name = "EquipType", + Value = equipType + }, + new GenericParameter() + { + Name = "Status", + Value = status + }, + new GenericParameter() + { + Name = "Light", + Value = light + }, + new GenericParameter() + { + Name = "StatusCode", + Value = statusCode + }, + new GenericParameter() + { + Name = "PassQty", + Value = passQty + }, + new GenericParameter() + { + Name = "FailQty", + Value = failQty + }, + new GenericParameter() + { + Name = "CycleTime", + Value = cycleTime + }, + new GenericParameter() + { + Name = "RunningTime", + Value = runningTime + }, + new GenericParameter() + { + Name = "WaitingTime", + Value = waitingTime + }, + new GenericParameter() + { + Name = "SelfCheck", + Value = selfCheck + }, + new GenericParameter() + { + Name = "InputQty", + Value = inputQty + }, + new GenericParameter() + { + Name = "ErrorCnt", + Value = errorCnt + }, + new GenericParameter() + { + Name = "ErrorTimes", + Value = errorTimes + }, + }; + } } - - } diff --git a/Sln.Iot.Business/RFID01Business.cs b/Sln.Iot.Business/RFID01Business.cs index d770fa7..eb142ec 100644 --- a/Sln.Iot.Business/RFID01Business.cs +++ b/Sln.Iot.Business/RFID01Business.cs @@ -4,6 +4,7 @@ using CFX.Structures.PressInsertion; using HslCommunication; using Sln.Iot.CFX.CFXConnect; using Sln.Iot.CFX.Event; +using Sln.Iot.Common; using Sln.Iot.PLC; using Sln.Iot.Repository; using Sln.Iot.Repository.dao; @@ -94,6 +95,14 @@ namespace Sln.Iot.Business chars[j + 1] = temp; } prodcode[i] = new string(chars); + GlobalVar.Connect2Entity.InputQuantity++; + GlobalVar.Connect2Entity.PassQuantity++; + GlobalVar.Connect3Entity.InputQuantity++; + GlobalVar.Connect1Entity.InputQuantity++; + GlobalVar.Connect1Entity.PassQuantity++; + GlobalVar.Connect3Entity.PassQuantity++; + GlobalVar.Connect4Entity.InputQuantity++; + GlobalVar.Connect4Entity.PassQuantity++; _log.Info($"{prodcode[i]}进入产线"); } } diff --git a/Sln.Iot.Business/RFID06Business.cs b/Sln.Iot.Business/RFID06Business.cs index 8c261f3..621fa71 100644 --- a/Sln.Iot.Business/RFID06Business.cs +++ b/Sln.Iot.Business/RFID06Business.cs @@ -5,6 +5,7 @@ using HslCommunication; using Sln.Iot.CFX.CFXBusiness; using Sln.Iot.CFX.CFXConnect; using Sln.Iot.CFX.Event; +using Sln.Iot.Common; using Sln.Iot.PLC; using Sln.Iot.Repository.service; using Sln.Iot.Serilog; @@ -92,6 +93,8 @@ namespace Sln.Iot.Business string[] prodcode = trayBindingService.ProdCodeGet(traycode); + + bool res = trayBindingService.TrayCodeDelete(traycode); if (!res) diff --git a/Sln.Iot.Business/RecipeBusiness.cs b/Sln.Iot.Business/RecipeBusiness.cs index 079123f..1d0fc09 100644 --- a/Sln.Iot.Business/RecipeBusiness.cs +++ b/Sln.Iot.Business/RecipeBusiness.cs @@ -29,7 +29,7 @@ namespace Sln.Iot.Business public RecipeBusiness() { - _timer = new Timer(TimerCallback, null, 0, 1500); + _timer = new Timer(TimerCallback, null, 0, 5000); } /// diff --git a/Sln.Iot.CFX/CFXHelper.cs b/Sln.Iot.CFX/CFXHelper.cs index 6e8373e..d9519c1 100644 --- a/Sln.Iot.CFX/CFXHelper.cs +++ b/Sln.Iot.CFX/CFXHelper.cs @@ -23,16 +23,18 @@ #endregion << 版 本 注 释 >> -using System.Diagnostics; using CFX; using CFX.InformationSystem.UnitValidation; using CFX.Production; using CFX.ResourcePerformance; using CFX.Structures; using CFX.Transport; +using Microsoft.Identity.Client; using Sln.Iot.CFX.Event; using Sln.Iot.CFX.RequestReceived; +using Sln.Iot.Config; using Sln.Iot.Serilog; +using System.Diagnostics; namespace Sln.Iot.CFX; @@ -43,6 +45,8 @@ public abstract class CFXHelper { SerilogHelper _log = SerilogHelper.Instance; + private readonly AppConfig _appConfig = AppConfigSetting.Load(); + /// /// CFX通讯端点 /// @@ -61,7 +65,7 @@ public abstract class CFXHelper { try { - if(Endpoint == null) + if (Endpoint == null) { throw new ArgumentNullException("CFX 端点无引用(null)"); } @@ -118,7 +122,8 @@ public abstract class CFXHelper //Task.Run(() => //{ Endpoint.Publish(env); - //_log.Iot($"{Endpoint.CFXHandle}推送事件{env.MessageName}"); + if (_appConfig.IsCFXLog) + _log.Iot($"{Endpoint.CFXHandle}推送事件{env.MessageName}"); //}); } catch (Exception e) diff --git a/Sln.Iot.Common/GlobalVar.cs b/Sln.Iot.Common/GlobalVar.cs index c98ffa0..49ffd49 100644 --- a/Sln.Iot.Common/GlobalVar.cs +++ b/Sln.Iot.Common/GlobalVar.cs @@ -3,11 +3,34 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Sln.Iot.Model.Entity; namespace Sln.Iot.Common { + /// + /// 全局内存变量 + /// public class GlobalVar { - //public static int + public static DateTime OpenTime; + /// + /// 真空箱数据 + /// + public static MesReportEntity Connect1Entity = new MesReportEntity() { InterfaceID = "OT00470018" }; + + /// + /// 提升机1数据 + /// + public static MesReportEntity Connect2Entity = new MesReportEntity() { InterfaceID = "OT00470019" }; + + /// + /// 烤箱2数据 + /// + public static MesReportEntity Connect3Entity = new MesReportEntity() { InterfaceID = "OT00470017" }; + + /// + /// 提升机2数据 + /// + public static MesReportEntity Connect4Entity = new MesReportEntity() { InterfaceID = "OT00470020" }; } } diff --git a/Sln.Iot.Common/Sln.Iot.Common.csproj b/Sln.Iot.Common/Sln.Iot.Common.csproj index ada983b..76eab91 100644 --- a/Sln.Iot.Common/Sln.Iot.Common.csproj +++ b/Sln.Iot.Common/Sln.Iot.Common.csproj @@ -11,6 +11,7 @@ + diff --git a/Sln.Iot.Config/AppConfig.cs b/Sln.Iot.Config/AppConfig.cs index 1ed77d3..7fafd90 100644 --- a/Sln.Iot.Config/AppConfig.cs +++ b/Sln.Iot.Config/AppConfig.cs @@ -34,6 +34,11 @@ namespace Sln.Iot.Config /// public string logPath { get; set; } + /// + /// 节拍时间(秒) + /// + public int CycleTime { get; set; } + /// /// PLC配置 /// @@ -59,6 +64,31 @@ namespace Sln.Iot.Config /// public CFXConfig Lift2Config { get; set; } + /// + /// MES的URL + /// + public string MESURL { get; set; } + + /// + /// MES的URN + /// + public string MESURN { get; set; } + + /// + /// 是否输出报警日志 + /// + public bool IsAlarmLog { get; set; } + + /// + /// 是否输出MES日志 + /// + public bool IsMESLog { get; set; } + + /// + /// 是否输出CFX日志 + /// + public bool IsCFXLog { get; set; } + /// /// Gets the current application configuration instance. /// diff --git a/Sln.Iot.Model/Entity/MesReportEntity.cs b/Sln.Iot.Model/Entity/MesReportEntity.cs new file mode 100644 index 0000000..3352d92 --- /dev/null +++ b/Sln.Iot.Model/Entity/MesReportEntity.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Sln.Iot.Model.Entity +{ + /// + /// 日志上报实体类 + /// + public class MesReportEntity + { + /// + /// 设备ID + /// + public string InterfaceID { get; set; } + + /// + /// 设备运行状态 + /// + public string Status { get; set; } = "0"; + + /// + /// 设备状态码 + /// + public string StatusCode { get; set; } = "0"; + + /// + /// 良品数量 + /// + public int PassQuantity { get; set; } = 0; + + /// + /// 不良品数量 + /// + public int FailQuantity { get; set; } = 0; + + /// + /// 故障次数 + /// + public int ErrorCount { get; set; } = 0; + + /// + /// 故障时间 + /// + public int ErrorTime { get; set; } = 0; + + /// + /// 节拍时间 + /// + public int CycleTime { get; set; } = 0; + + /// + /// 运行时间 + /// + public int RunningTime { get; set; } = 0; + + /// + /// 等待时间 + /// + public int WaitingTime { get; set; } = 10000; + + /// + /// 投入数量 + /// + public int InputQuantity { get; set; } = 0; + + /// + /// 条码数据 + /// + public string Barcode { get; set; } = "Unknow"; + + /// + /// 产品型号 + /// + public string Cya { get; set; } = "灌胶机"; + + /// + /// 上次故障时间 + /// + public DateTime LastErrorTime { get; set; } + + /// + /// 现在是否故障 + /// + public bool IsError { get; set; } + } +} diff --git a/Sln.Iot.Repository/service/OvenPlcDataService.cs b/Sln.Iot.Repository/service/OvenPlcDataService.cs index 26b88d8..5aa007c 100644 --- a/Sln.Iot.Repository/service/OvenPlcDataService.cs +++ b/Sln.Iot.Repository/service/OvenPlcDataService.cs @@ -66,14 +66,27 @@ namespace Sln.Iot.Repository.service { return false; } - var res = _helper.Update(new OvenPlcData() + var oldData = _helper.Query(x => x.GUID == guid).FirstOrDefault(); + if (oldData != null) { - GUID = guid, - PreCureOven1TempActValue = data.PreCureOven1TempActValue, - PreCureOven2TempActValue = data.PreCureOven2TempActValue, - PreCureOven3TempActValue = data.PreCureOven3TempActValue, - PreCureOven4TempActValue = data.PreCureOven4TempActValue, - }); + oldData.PreCureOven1TempActValue = data.PreCureOven1TempActValue; + oldData.PreCureOven2TempActValue = data.PreCureOven2TempActValue; + oldData.PreCureOven3TempActValue = data.PreCureOven3TempActValue; + oldData.PreCureOven4TempActValue = data.PreCureOven4TempActValue; + } + else + { + oldData = new OvenPlcData() + { + GUID = guid, + PreCureOven1TempActValue = data.PreCureOven1TempActValue, + PreCureOven2TempActValue = data.PreCureOven2TempActValue, + PreCureOven3TempActValue = data.PreCureOven3TempActValue, + PreCureOven4TempActValue = data.PreCureOven4TempActValue, + }; + } + + var res = _helper.Update(oldData); return res == 0 ? false : true; } catch (Exception ex) @@ -95,14 +108,27 @@ namespace Sln.Iot.Repository.service { return false; } - var res = _helper.Update(new OvenPlcData() + var oldData = _helper.Query(x => x.GUID == guid).FirstOrDefault(); + if (oldData != null) { - GUID = guid, - CureOven1TempActValue = data.CureOven1TempActValue, - CureOven2TempActValue = data.CureOven2TempActValue, - CureOven3TempActValue = data.CureOven3TempActValue, - CureOven4TempActValue = data.CureOven4TempActValue, - }); + oldData.CureOven1TempActValue = data.CureOven1TempActValue; + oldData.CureOven2TempActValue = data.CureOven2TempActValue; + oldData.CureOven3TempActValue = data.CureOven3TempActValue; + oldData.CureOven4TempActValue = data.CureOven4TempActValue; + } + else + { + oldData = new OvenPlcData() + { + GUID = guid, + CureOven1TempActValue = data.CureOven1TempActValue, + CureOven2TempActValue = data.CureOven2TempActValue, + CureOven3TempActValue = data.CureOven3TempActValue, + CureOven4TempActValue = data.CureOven4TempActValue, + }; + } + + var res = _helper.Update(oldData!); return res == 0 ? false : true; } catch (Exception ex) diff --git a/Sln.Iot.Socket/DeltaHttpClient.cs b/Sln.Iot.Socket/DeltaHttpClient.cs index f97c9b1..fdd9ffb 100644 --- a/Sln.Iot.Socket/DeltaHttpClient.cs +++ b/Sln.Iot.Socket/DeltaHttpClient.cs @@ -1,4 +1,5 @@ -using Sln.Iot.Serilog; +using Sln.Iot.Config; +using Sln.Iot.Serilog; using System.Text; using TouchSocket.Core; using TouchSocket.Http; @@ -20,6 +21,7 @@ namespace Sln.Iot.Socket } HttpClient DeltaClent = new HttpClient(); + private readonly AppConfig _appConfig = AppConfigSetting.Load(); SerilogHelper _log = SerilogHelper.Instance; @@ -32,7 +34,7 @@ namespace Sln.Iot.Socket { var config = new TouchSocketConfig(); #region Http设置远程服务器地址 - config.SetRemoteIPHost("http://10.148.192.32:8090"); + config.SetRemoteIPHost(_appConfig.MESURL); #endregion #region Http客户端获取断线通知 @@ -40,15 +42,24 @@ namespace Sln.Iot.Socket { a.AddTcpClosedPlugin(async (c, e) => { - Console.WriteLine("客户端断开连接"); + _log.Info("客户端断开连接"); await e.InvokeNext(); }); }); + //断线重连设置 + config.ConfigurePlugins(a => + { + a.UseReconnection(options => + { + options.PollingInterval = TimeSpan.FromSeconds(5); + }); + }); #endregion //配置config await DeltaClent.SetupAsync(config); await DeltaClent.ConnectAsync();//先做连接 + _log.Info("MES连接成功"); } catch (Exception ex) { @@ -65,10 +76,9 @@ namespace Sln.Iot.Socket var request = new HttpRequest(); request.SetContent(new StringHttpContent(jsonData, Encoding.UTF8, "application/json")) .InitHeaders() - .SetUrl("/sensordata?sensorId=UploadMachineData") + .SetUrl(_appConfig.MESURN) .SetHost(DeltaClent.RemoteIPHost.Host) .AsPost(); - try { //创建一个超时操作,10秒后取消。 @@ -77,8 +87,11 @@ namespace Sln.Iot.Socket using (var responseResult = await DeltaClent.RequestAsync(request, cts.Token)) { var response = responseResult.Response; + if (_appConfig.IsMESLog) + _log.Info($"发送数据:{jsonData}"); var result = await response.GetBodyAsync(); - _log.Info($"响应结果:{result}"); + if (_appConfig.IsMESLog) + _log.Info($"响应结果:{result}"); } } catch (Exception ex) diff --git a/Sln.Iot.Test/UnitTest1.cs b/Sln.Iot.Test/UnitTest1.cs index 516f999..da50894 100644 --- a/Sln.Iot.Test/UnitTest1.cs +++ b/Sln.Iot.Test/UnitTest1.cs @@ -1,16 +1,20 @@ -global using Xunit; global using Sln.Iot.Repository.dao; +global using Xunit; +using Sln.Iot.Business; +using Sln.Iot.Common; +using Sln.Iot.Config; +using Sln.Iot.PLC; using Sln.Iot.Repository; using Sln.Iot.Repository.service; using System.Collections; -using Sln.Iot.Business; -using Sln.Iot.PLC; -using Sln.Iot.Common; namespace Sln.Iot.Test { public class UnitTest1 { + private readonly AppConfig _appConfig = AppConfigSetting.Load(); + + [Fact] public void Test1() { @@ -80,9 +84,30 @@ namespace Sln.Iot.Test [Fact] public void Test3() - { - GetLocalIP.GetLocalIPAddress(); + { + var ins = OvenPlcDataService.Instance; + var a = Guid.NewGuid().ToString(); + ins.InsertData(a, 123); + ins.UpdateDataPreCure(a, new Model.Entity.UnitsProcess3Entity + { + PreCureOven1TempActValue = 1233, + PreCureOven2TempActValue = 1223, + PreCureOven3TempActValue = 1213, + PreCureOven4TempActValue = 1203, + }); + ins.UpdateDataCure(a, new Model.Entity.UnitsProcess3Entity + { + CureOven1TempActValue = 1233, + CureOven2TempActValue = 1223, + CureOven3TempActValue = 1213, + CureOven4TempActValue = 1203, + }); + } + [Fact] + public void Test4() + { + var a = _appConfig.IsCFXLog; } } } diff --git a/Sln.Iot/Program.cs b/Sln.Iot/Program.cs index f024ed9..58b1a7a 100644 --- a/Sln.Iot/Program.cs +++ b/Sln.Iot/Program.cs @@ -7,6 +7,7 @@ using Sln.Iot.Business; using Sln.Iot.CFX; using Sln.Iot.CFX.CFXConnect; using Sln.Iot.CFX.Event; +using Sln.Iot.Common; using Sln.Iot.Config; using Sln.Iot.PLC; using Sln.Iot.Repository; @@ -53,6 +54,13 @@ namespace Sln.Iot static async Task Main(string[] args) { + bool isNotRunning; //互斥体判断 + System.Threading.Mutex instance = new System.Threading.Mutex(true, "MutexName", out isNotRunning); //同步基元变量 + if (!isNotRunning) // 如果不是未运行状态 + { + Environment.Exit(1); + } + SetConsoleCtrlHandler(cancelHandler, true); //Serilog中间件 SerilogExtensions.UseSerilogExtensions(); @@ -62,6 +70,7 @@ namespace Sln.Iot var appConfig = AppConfigSetting.Load(); //PLC连接初始化 PLCConnect.Instance.InitConnect(); + GlobalVar.OpenTime = DateTime.Now; //CFX接口启动 //真空注胶机 diff --git a/Sln.Iot/appsettings.json b/Sln.Iot/appsettings.json index 7fbbb41..28013a8 100644 --- a/Sln.Iot/appsettings.json +++ b/Sln.Iot/appsettings.json @@ -1,10 +1,16 @@ { "AppConfig": { + //MES数据中的CycleTime字段 + "CycleTime": 7200, "logPath": "D:\\log", + //CFX连接配置 "VacuumConfig": { + //设备名 "DeviceName": "Vacuum", "CFXHandle": "CFX.A00.OT00470018", + //本地URI "LocalURI": "amqp://127.0.0.1:1235", + //上位系统URI "UpperURI": "http://10.148.192.32:8090/sensordata?sensorId=UploadMachineData" }, "Lift1Config": { @@ -24,6 +30,16 @@ "CFXHandle": "CFX.A00.OT00470020", "LocalURI": "amqp://127.0.0.1:1238", "UpperURI": "http://10.148.192.32:8090/sensordata?sensorId=UploadMachineData" - } + }, + //MES连接地址和端口号 + "MESURL": "http://10.148.192.32:8090", + //MES连接接口地址 + "MESURN": "/sensordata?sensorId=UploadMachineData", + //是否输出报警日志 + "IsAlarmLog": true, + //是否输出MES日志 + "IsMESLog": true, + //是否输出CFX日志 + "IsCFXLog": false } }