diff --git a/IOB-UT-NEXT/FileProcMan.cs b/IOB-UT-NEXT/FileProcMan.cs index 1a9a6b5b..cc6bd0f2 100644 --- a/IOB-UT-NEXT/FileProcMan.cs +++ b/IOB-UT-NEXT/FileProcMan.cs @@ -9,6 +9,11 @@ namespace IOB_UT_NEXT { #region Public Constructors + /// + /// Init di base + /// + /// + /// public FileProcMan(string toolDir, string exeFileName) { this.confFileNameOut = "conf.json"; @@ -17,6 +22,34 @@ namespace IOB_UT_NEXT appPath = Path.Combine(baseDir, exeName); } + /// + /// Init con chiave Redis (es Emmegi FPW) + /// + /// + /// + /// + /// + public FileProcMan(string toolDir, string exeFileName, string redisKey, string refConfFileName) + { + this.confFileNameOut = "conf.json"; + this.redisKey = redisKey; + this.baseDir = toolDir; + this.exeName = exeFileName; + appPath = Path.Combine(baseDir, exeName); + // leggo file di conf base + string refConfFile = Path.Combine(baseDir, refConfFileName); + this.refConf = File.ReadAllText(refConfFile); + } + + /// + /// Init completa (es Fimat/Giacovelli) + /// + /// + /// + /// + /// + /// + /// public FileProcMan(string archiveDir, string convertDir, string toolDir, string exeFileName, string refConfFileName, string sheetName) { this.archDir = archiveDir; @@ -90,6 +123,7 @@ namespace IOB_UT_NEXT protected string exeName = ""; protected string refConf = ""; protected string sheetName = ""; + protected string redisKey = ""; #endregion Protected Fields @@ -115,6 +149,10 @@ namespace IOB_UT_NEXT rawContent = rawContent.Replace("{{FileInPath}}", fixJsonDir(item)); rawContent = rawContent.Replace("{{FileOutPath}}", outFileName); rawContent = rawContent.Replace("{{TargetSheetName}}", sheetName); + if (redisKey != null) + { + rawContent = rawContent.Replace("{{redisKey}}", redisKey); + } rawContent = rawContent.Replace("987654321", $"{idxOdl}"); // calcolo nome file conf specifico confFileNameOut = $"conf_{outFileName}"; diff --git a/IOB-UT-NEXT/FtpActConf.cs b/IOB-UT-NEXT/FtpActConf.cs index 7ee333b0..1d7d3e80 100644 --- a/IOB-UT-NEXT/FtpActConf.cs +++ b/IOB-UT-NEXT/FtpActConf.cs @@ -6,12 +6,8 @@ using System.Threading.Tasks; namespace IOB_UT_NEXT { - public class FtpActConf + public class FtpActConf : GenActConf { - /// - /// ID azione configurata - /// - public string ActionId { get; set; } = "000"; /// /// IP / DNS name del ServerAddr FTP @@ -43,69 +39,6 @@ namespace IOB_UT_NEXT /// public bool SkipCert { get; set; } = true; - /// - /// Tempo di attesa in SEC standard prima della prossima ri-esecuzione - /// - public int ReExecVeto { get; set; } = 60; - - /// - /// Note opzionali - /// - public string Note { get; set; } = ""; - - /// - /// Elenco step da eseguire - /// - public List StepsList { get; set; } - } - /// - /// Configurazione di un singolo step FTP - /// - public class ActionConfig - { - /// - /// ID azione (per ordinamento) - /// - public string Id { get; set; } = "00"; - - /// - /// Descrizione step - /// - public string Description { get; set; } = "00"; - - /// - /// Azione richiesta - /// - public ActType Action { get; set; } = ActType.CheckDir; - - /// - /// Dizionario parametri specifici per azione richiesta (dipendenti da azione...) - /// - public Dictionary ParamList { get; set; } = new Dictionary(); - } - - /// - /// Enum azioni FTP gestite/da gestire - /// - public enum ActType - { - CheckDir, - CheckFile, - CreateDir, - DelDir, - DelFile, - //DelFileList, - DownloadDir, - DownloadFile, - GenRandomDir, - ListContent, - MirrorDirL2R, - MirrorDirR2L, - PingServer, - RemoveFileByName, - UploadDir, - UploadFile - } } diff --git a/IOB-UT-NEXT/GenActConf.cs b/IOB-UT-NEXT/GenActConf.cs new file mode 100644 index 00000000..cac92fbe --- /dev/null +++ b/IOB-UT-NEXT/GenActConf.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IOB_UT_NEXT +{ + public class GenActConf + { + /// + /// ID azione configurata + /// + public string ActionId { get; set; } = "000"; + + /// + /// Tempo di attesa in SEC standard prima della prossima ri-esecuzione + /// + public int ReExecVeto { get; set; } = 60; + + /// + /// Note opzionali + /// + public string Note { get; set; } = ""; + + /// + /// Elenco step da eseguire + /// + public List StepsList { get; set; } + + /// + /// Configurazione di un singolo step FTP + /// + public class ActionConfig + { + /// + /// ID azione (per ordinamento) + /// + public string Id { get; set; } = "00"; + + /// + /// Descrizione step + /// + public string Description { get; set; } = "00"; + + /// + /// Azione richiesta + /// + public ActType Action { get; set; } = ActType.CheckDir; + + /// + /// Dizionario parametri specifici per azione richiesta (dipendenti da azione...) + /// + public Dictionary ParamList { get; set; } = new Dictionary(); + } + + /// + /// Enum azioni gestite/da gestire + /// + public enum ActType + { + CheckDir, + CheckFile, + CreateDir, + DelDir, + DelFile, + //DelFileList, + DownloadDir, + DownloadFile, + GenRandomDir, + ListContent, + MirrorDirL2R, + MirrorDirR2L, + PingServer, + RemoveFileByName, + UploadDir, + UploadFile + } + } +} diff --git a/IOB-UT-NEXT/IOB-UT-NEXT.csproj b/IOB-UT-NEXT/IOB-UT-NEXT.csproj index f494e0ec..7d29deaf 100644 --- a/IOB-UT-NEXT/IOB-UT-NEXT.csproj +++ b/IOB-UT-NEXT/IOB-UT-NEXT.csproj @@ -180,10 +180,12 @@ + + @@ -213,10 +215,15 @@ + + Always + + + diff --git a/IOB-UT-NEXT/Objects.cs b/IOB-UT-NEXT/Objects.cs index 0940bb90..e58db839 100644 --- a/IOB-UT-NEXT/Objects.cs +++ b/IOB-UT-NEXT/Objects.cs @@ -59,11 +59,22 @@ namespace IOB_UT_NEXT #endregion Public Methods } + /// + /// Elenco task di tipo FTP + /// public class FtpTaskList { public List ListTask { get; set; } = new List(); } + /// + /// Elenco task generici + /// + public class GenTaskList + { + public List ListTask { get; set; } = new List(); + } + /// /// Gestione dati di timing /// diff --git a/IOB-UT-NEXT/RedisMan.cs b/IOB-UT-NEXT/RedisMan.cs index beef51d8..f5f5f38a 100644 --- a/IOB-UT-NEXT/RedisMan.cs +++ b/IOB-UT-NEXT/RedisMan.cs @@ -13,6 +13,11 @@ namespace IOB_UT_NEXT { #region Public Fields + /// + /// Hash REDIS x dati IOB + /// + public string redIobKey = ""; + /// /// Hash REDIS x dati IOB /// @@ -1425,11 +1430,6 @@ namespace IOB_UT_NEXT /// protected string redIobChannel = "IobChannel"; - /// - /// Hash REDIS x dati IOB - /// - protected string redIobKey = ""; - /// /// Hash REDIS x dati server /// diff --git a/IOB-WIN-FTP/Iob/Ftp.cs b/IOB-WIN-FTP/Iob/Ftp.cs index cb1297c8..3db455b7 100644 --- a/IOB-WIN-FTP/Iob/Ftp.cs +++ b/IOB-WIN-FTP/Iob/Ftp.cs @@ -110,7 +110,7 @@ namespace IOB_WIN_FTP.Iob // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti... Dictionary taskDone = new Dictionary(); - ActionConfig currAct = new ActionConfig(); + GenActConf.ActionConfig currAct = new GenActConf.ActionConfig(); var currActParam = new Dictionary(); string actKey = "RemoteDir"; string newDir = ""; @@ -153,11 +153,11 @@ namespace IOB_WIN_FTP.Iob actKey = "RemoteDir"; newDir = $"{RemoteBaseDir}/{item.Value}"; currActParam.Add(actKey, newDir); - currAct = new ActionConfig() + currAct = new GenActConf.ActionConfig() { Id = "01", Description = "Verifica esistenza directory", - Action = ActType.CheckDir, + Action = GenActConf.ActType.CheckDir, ParamList = currActParam }; //eseguo step... @@ -166,11 +166,11 @@ namespace IOB_WIN_FTP.Iob if (!dirOk) { // nuovo act x crearla! - currAct = new ActionConfig() + currAct = new GenActConf.ActionConfig() { Id = "02", Description = "Creazione directory", - Action = ActType.CreateDir, + Action = GenActConf.ActType.CreateDir, ParamList = currActParam }; //eseguo step... @@ -359,15 +359,15 @@ namespace IOB_WIN_FTP.Iob if (!string.IsNullOrEmpty(reqFolder)) { // verifico se ci sia... - ActionConfig currAct = new ActionConfig(); + GenActConf.ActionConfig currAct = new GenActConf.ActionConfig(); var currActParam = new Dictionary(); // compongo remDir dai 2 parametri... currActParam.Add("RemoteDir", $"{RemoteBaseDir}/{reqFolder}"); - currAct = new ActionConfig() + currAct = new GenActConf.ActionConfig() { Id = "01", Description = "Verifica esistenza directory", - Action = ActType.CheckDir, + Action = GenActConf.ActType.CheckDir, ParamList = currActParam }; //eseguo step... @@ -655,7 +655,7 @@ namespace IOB_WIN_FTP.Iob /// /// /// - private bool doStep(ActionConfig step) + private bool doStep(GenActConf.ActionConfig step) { bool fatto = false; string remoteVal = ""; @@ -666,7 +666,7 @@ namespace IOB_WIN_FTP.Iob // faccio switch in base al tipo di azione da eseguire... switch (step.Action) { - case ActType.CheckDir: + case GenActConf.ActType.CheckDir: if (step.ParamList != null && step.ParamList.Count > 0) { sw.Restart(); @@ -685,10 +685,10 @@ namespace IOB_WIN_FTP.Iob } break; - case ActType.CheckFile: + case GenActConf.ActType.CheckFile: break; - case ActType.CreateDir: + case GenActConf.ActType.CreateDir: if (step.ParamList != null && step.ParamList.Count > 0) { sw.Restart(); @@ -715,29 +715,29 @@ namespace IOB_WIN_FTP.Iob } break; - case ActType.DelDir: + case GenActConf.ActType.DelDir: break; - case ActType.DelFile: + case GenActConf.ActType.DelFile: break; - case ActType.DownloadDir: + case GenActConf.ActType.DownloadDir: break; - case ActType.DownloadFile: + case GenActConf.ActType.DownloadFile: break; - case ActType.GenRandomDir: + case GenActConf.ActType.GenRandomDir: break; - case ActType.ListContent: + case GenActConf.ActType.ListContent: break; - case ActType.MirrorDirL2R: + case GenActConf.ActType.MirrorDirL2R: break; - case ActType.MirrorDirR2L: + case GenActConf.ActType.MirrorDirR2L: // eseguo mirroring directory actKey = "FtpSync"; actVal = "SRC --> DEST | Size"; @@ -808,10 +808,10 @@ namespace IOB_WIN_FTP.Iob break; - case ActType.PingServer: + case GenActConf.ActType.PingServer: break; - case ActType.RemoveFileByName: + case GenActConf.ActType.RemoveFileByName: string fName2Del = ""; int numRem = 0; if (step.ParamList != null && step.ParamList.Count > 1) @@ -854,10 +854,10 @@ namespace IOB_WIN_FTP.Iob break; - case ActType.UploadDir: + case GenActConf.ActType.UploadDir: break; - case ActType.UploadFile: + case GenActConf.ActType.UploadFile: if (step.ParamList != null && step.ParamList.Count > 1) { sw.Restart(); @@ -964,11 +964,11 @@ namespace IOB_WIN_FTP.Iob Dictionary currActParam = new Dictionary(); currActParam.Add("RemoteDir", remDir); currActParam.Add("FileName2Del", fNameOdl); - ActionConfig currAct = new ActionConfig() + GenActConf.ActionConfig currAct = new GenActConf.ActionConfig() { Id = "01", Description = "Clean Curr ODL Files", - Action = ActType.RemoveFileByName, + Action = GenActConf.ActType.RemoveFileByName, ParamList = currActParam }; // eseguo step... @@ -996,11 +996,11 @@ namespace IOB_WIN_FTP.Iob // invio file x ODL attivo currActParam.Add("LocalFile", locFile); currActParam.Add("RemoteFile", remFile); - ActionConfig currAct = new ActionConfig() + GenActConf.ActionConfig currAct = new GenActConf.ActionConfig() { Id = "01", Description = "Upload File", - Action = ActType.UploadFile, + Action = GenActConf.ActType.UploadFile, ParamList = currActParam }; // eseguo step... diff --git a/IOB-WIN-WS/DATA/CONF/L021.ini b/IOB-WIN-WS/DATA/CONF/L021.ini index 558ca039..a40149b7 100644 --- a/IOB-WIN-WS/DATA/CONF/L021.ini +++ b/IOB-WIN-WS/DATA/CONF/L021.ini @@ -70,6 +70,9 @@ ENABLE_DYN_DATA=TRUE DISABLE_SEND_WDST=TRUE PARAM_CONF=L021.json REST_CONF=L021.json +;parametri speciali x gestione checkfile +FileInPath=C:\Steamware\EmmegiFPW\FileTaglierina.xlsx +FileImportConf=FPW_import.json [BRANCH] NAME=master \ No newline at end of file diff --git a/IOB-WIN-WS/DATA/TEMPLATE_ODL_USDT.csv b/IOB-WIN-WS/DATA/CONF/TEMPLATE_ODL_USDT.csv similarity index 100% rename from IOB-WIN-WS/DATA/TEMPLATE_ODL_USDT.csv rename to IOB-WIN-WS/DATA/CONF/TEMPLATE_ODL_USDT.csv diff --git a/IOB-WIN-WS/DTO/EmmegiDTO.cs b/IOB-WIN-WS/DTO/EmmegiDTO.cs deleted file mode 100644 index 2440d640..00000000 --- a/IOB-WIN-WS/DTO/EmmegiDTO.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Xml.Serialization; - -namespace IOB_WIN_WS.DTO -{ - public class EmmegiDTO - { - /// - /// Converte valore raw stato impianto nel formato specifico - /// - /// - public static StatusDTO GetStatus(string xmlRaw) - { - StatusDTO answ = new StatusDTO(); - // deserializzo - var serializer = new XmlSerializer(typeof(StatusDTO)); - using (var reader = new StringReader(xmlRaw)) - { - answ = (StatusDTO)serializer.Deserialize(reader); - } - return answ; - } - public enum MachineStatus - { - // manuale - ON, - // attrezzaggio = zero assi - SETUP, - // pronta, in automatico, in attesa carico pezzi - READY, - // posizionamento (teste morse o cambio utensili) - POSITIONING, - // attesa (carico/scarico barra, operazioni utente) - WAIT, - // in lavorazione effettiva - WORKING, - // emergenza - EMERGENCY, - // in allarme - ALARM, - - // offline (poweroff?) - OFF_LINE, - OFF, - ERROR - } - - - [XmlRoot("result_workstation_status")] - public class StatusDTO - { - [XmlElement("workstation")] - public Workstation Workstation { get; set; } - } - - /// - /// Obj workstation - /// - public class Workstation - { - - [XmlElement("id")] - public WorkstationId Id { get; set; } - - [XmlElement("status")] - public MachineStatus Status { get; set; } - - [XmlElement("status_timestamp")] - public string StatusTimestampRaw { get; set; } - - [XmlIgnore] - public DateTime StatusTimestamp - { - get => DateTime.ParseExact(StatusTimestampRaw, "yyyy-MM-dd HH:mm:ss", null); - } - - [XmlElement("operator")] - public string Operator { get; set; } - - [XmlElement("job_id")] - public string JobId { get; set; } - - [XmlElement("operations")] - public int Operations { get; set; } - - [XmlElement("tot_operations")] - public int TotalOperations { get; set; } - } - - /// - /// Obj WorkstationId - /// - public class WorkstationId - { - [XmlAttribute("id")] - public string IdValue { get; set; } - } - } -} diff --git a/IOB-WIN-WS/IobWs/EmmegiFPW.cs b/IOB-WIN-WS/IobWs/EmmegiFPW.cs index 1f357eeb..0086a013 100644 --- a/IOB-WIN-WS/IobWs/EmmegiFPW.cs +++ b/IOB-WIN-WS/IobWs/EmmegiFPW.cs @@ -1,21 +1,16 @@ -using EgwProxy.Icoel; -using IOB_UT_NEXT; +using IOB_UT_NEXT; using IOB_UT_NEXT.Config; -//using IOB_WIN_WS.DTO; using MapoSDK; using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; using System.Xml.Serialization; using static IOB_UT_NEXT.CustomObj; -using static MapoSDK.WharehouseData; -//using static IOB_WIN_WS.DTO.EmmegiDTO; -//using static IOB_WIN_WS.IobWs.EmmegiFPW.Responses; +using static IOB_UT_NEXT.DataModel.UstdData; namespace IOB_WIN_WS.IobWs { @@ -43,7 +38,10 @@ namespace IOB_WIN_WS.IobWs { setupRestConf(getOptPar("REST_CONF")); } - // sistemo conf errori e samplePeriod... + + // sistemo chiavi specifiche redis... + rKeyConf = $"{redisMan.redIobKey}:Conf:ParamsUSTD"; + rKeyMD5 = $"{redisMan.redIobKey}:FPW:FILE-MD5"; lgInfo("Rest - 02"); if (EnableTest) @@ -154,7 +152,7 @@ namespace IOB_WIN_WS.IobWs WarnInfo alarmResp = JsonConvert.DeserializeObject(rawData); bankVal = (alarmResp != null && alarmResp.IsAlarm) ? alarmResp.message : "OK"; saveAlarmString(ref outVal, bankVal, "Alarms"); - // verificare eventuale invio allarmi "storici" + // verificare eventuale invio allarmi "storici" #endif return outVal; } @@ -187,6 +185,7 @@ namespace IOB_WIN_WS.IobWs return RestLutGet("pName"); } +#if false /// /// Esegue gestioen contapezzi... /// @@ -197,9 +196,6 @@ namespace IOB_WIN_WS.IobWs if (adesso.Subtract(lastRestProcPzCount.AddMilliseconds(samplePeriod * 4)).TotalSeconds > 0) { lastRestProcPzCount = adesso; -#if false - LadderIO ladderResp = new LadderIO(); -#endif // in primis testo che sia connessa... var rawData = ExecuteCallGet(GetUrlResource("GetStatus"), true); lgTrace($"GetConnection | {rawData} | EmmegiFPW.processOtherCounters"); @@ -207,28 +203,6 @@ namespace IOB_WIN_WS.IobWs // proseguo SOLO SE macchina OK, altrimenti disconnetto... if (!string.IsNullOrEmpty(rawData)) { -#if false - // faccio refresh token comunque... - string token = ExecuteCallGet(GetUrlResource("GetToken")); - token = token.Replace("\"", ""); - RestLutUpsert("token", token); - Task.Delay(samplePeriod / 20); - - // contapezzi corrente - int intVal = 0; - string qtyWrk = ExecuteCallGet(GetUrlResource("GetQtyProd")); - int.TryParse(qtyWrk, out intVal); - contapezziPLC = intVal; - RestLutUpsert("qtyWrk", qtyWrk); - - //attendo mezzo sample period... - Task.Delay(samplePeriod / 10); - - // gestione tempociclo e nome programma... - string cTime = ExecuteCallGet(GetUrlResource("GetCycleTime")); - RestLutUpsert("cTime", cTime); -#endif - // salvo i dati status aggiornati SaveCurrStatus(rawData); lgInfo($"EmmegiFPW | contapezziPLC {currStatusDTO.Workstation.Operations} | TotCount {currStatusDTO.Workstation.TotalOperations}"); @@ -243,9 +217,6 @@ namespace IOB_WIN_WS.IobWs if (adesso.Subtract(lastRestOtherCount.AddMilliseconds(samplePeriod * 30)).TotalSeconds > 0) { lastRestOtherCount = adesso; -#if false - LadderIO ladderResp = new LadderIO(); -#endif // in primis testo che sia connessa... var rawData = ExecuteCallGet(GetUrlResource("GetStatus"), true); lgTrace($"GetConnection | {rawData} | EmmegiFPW.processOtherCounters"); @@ -253,37 +224,13 @@ namespace IOB_WIN_WS.IobWs // proseguo SOLO SE macchina OK, altrimenti disconnetto... if (!string.IsNullOrEmpty(rawData)) { -#if false - // faccio refresh token comunque... - string token = ExecuteCallGet(GetUrlResource("GetToken")); - token = token.Replace("\"", ""); - RestLutUpsert("token", token); - Task.Delay(samplePeriod / 20); - - // gestione altri contapezzi x - string qtyTot = ExecuteCallGet(GetUrlResource("GetQtyTot")); - - //attendo mezzo sample period... - Task.Delay(samplePeriod / 5); - - string qtyReq = ExecuteCallGet(GetUrlResource("GetQtyReq")); - RestLutUpsert("qtyTot", qtyTot); - RestLutUpsert("qtyReq", qtyReq); - - //attendo mezzo sample period... - Task.Delay(samplePeriod / 5); - - // gestione tempociclo e nome programma... - string pName = ExecuteCallGet(GetUrlResource("GetProgName")); - RestLutUpsert("pName", pName); -#endif // salvo i dati status aggiornati SaveCurrStatus(rawData); lgInfo($"EmmegiFPW | JOB {currStatusDTO.Workstation.JobId} | pzCount {currStatusDTO.Workstation.Operations}"); } } } - +#endif /// /// Override connessione @@ -311,15 +258,15 @@ namespace IOB_WIN_WS.IobWs parentForm.commPlcActive = true; // chiamo metodo connect - var rawResp = ExecuteCallGet(GetUrlResource("GetStatus"), true); - lgInfo($"GetConnection | {rawResp} | EmmegiFPW.tryConnect"); + var rawData = ExecuteCallGet(GetUrlResource("GetStatus"), true); + lgInfo($"GetConnection | {rawData} | EmmegiFPW.tryConnect"); - if (!string.IsNullOrEmpty(rawResp)) + if (!string.IsNullOrEmpty(rawData)) { connectionOk = true; queueInEnabCurr = true; // salvo lo status con i relativi contenuti... - SaveCurrStatus(rawResp); + SaveCurrStatus(rawData); if (adpRunning) { lgInfo("Connessione EmmegiFPW OK"); @@ -327,7 +274,7 @@ namespace IOB_WIN_WS.IobWs } else { - lgError($"Errore check connessione EmmegiFPW | rawData: {rawResp}"); + lgError($"Errore check connessione EmmegiFPW | rawData: {rawData}"); } } catch (Exception exc) @@ -354,140 +301,118 @@ namespace IOB_WIN_WS.IobWs } } - /// - /// Riceve un valore raw xml dello status e salva in LUT tutti i valori... - /// - /// - private void SaveCurrStatus(string rawData) - { - if (!string.IsNullOrEmpty(rawData)) - { - try - { - // deserializzo - currStatusDTO = GetStatus(rawData); - RestLutUpsert("serial", currStatusDTO.Workstation.Id.IdValue); - RestLutUpsert("currOdl", currStatusDTO.Workstation.JobId); - RestLutUpsert("operator", currStatusDTO.Workstation.Operator); - RestLutUpsert("status", currStatusDTO.Workstation.Status); - RestLutUpsert("currCount", currStatusDTO.Workstation.Operations); - RestLutUpsert("totCount", currStatusDTO.Workstation.TotalOperations); - RestLutUpsert("lastStatCh", currStatusDTO.Workstation.StatusTimestamp); - } - catch { } - } - } - - private EmmegiResp.StatusDTO currStatusDTO = new EmmegiResp.StatusDTO(); - - private EmmegiResp.MachineStatus currState - { - get => currStatusDTO.Workstation.Status; - } - #endregion Public Methods - /// - /// Converte valore raw stato impianto nel formato specifico - /// - /// - internal EmmegiResp.StatusDTO GetStatus(string xmlRaw) - { - EmmegiResp.StatusDTO answ = new EmmegiResp.StatusDTO(); - // deserializzo - var serializer = new XmlSerializer(typeof(EmmegiResp.StatusDTO)); - using (var reader = new StringReader(xmlRaw)) - { - answ = (EmmegiResp.StatusDTO)serializer.Deserialize(reader); - } - return answ; - } - - #region Internal Classes + #region Public Classes /// /// Struttura delle risposte alle chiamare REST specifiche /// - internal class EmmegiResp + public class EmmegiResp { + #region Public Enums - internal enum MachineStatus + public enum MachineStatus { // manuale ON, + // attrezzaggio = zero assi SETUP, + // pronta, in automatico, in attesa carico pezzi READY, + // posizionamento (teste morse o cambio utensili) POSITIONING, + // attesa (carico/scarico barra, operazioni utente) WAIT, + // in lavorazione effettiva WORKING, + // emergenza EMERGENCY, + // in allarme ALARM, // offline (poweroff?) OFF_LINE, + OFF, ERROR } - #region Internal Classes + #endregion Public Enums + + #region Public Classes [XmlRoot("result_workstation_status")] - internal class StatusDTO + public class StatusDTO { + #region Public Properties + [XmlElement("workstation")] public Workstation Workstation { get; set; } + + #endregion Public Properties } /// /// Obj workstation /// - internal class Workstation + public class Workstation { + #region Public Properties [XmlElement("id")] public WorkstationId Id { get; set; } - [XmlElement("status")] - public MachineStatus Status { get; set; } - - [XmlElement("status_timestamp")] - public string StatusTimestampRaw { get; set; } - - [XmlIgnore] - public DateTime StatusTimestamp - { - get => DateTime.ParseExact(StatusTimestampRaw, "yyyy-MM-dd HH:mm:ss", null); - } - - [XmlElement("operator")] - public string Operator { get; set; } - [XmlElement("job_id")] public string JobId { get; set; } [XmlElement("operations")] public int Operations { get; set; } + [XmlElement("operator")] + public string Operator { get; set; } + + [XmlElement("status")] + public MachineStatus Status { get; set; } + + [XmlIgnore] + public DateTime StatusTimestamp + { + get => DateTime.ParseExact(StatusTimestampRaw, "yyyy-MM-dd HH:mm:ss", null); + } + + [XmlElement("status_timestamp")] + public string StatusTimestampRaw { get; set; } + [XmlElement("tot_operations")] public int TotalOperations { get; set; } + + #endregion Public Properties } /// /// Obj WorkstationId /// - internal class WorkstationId + public class WorkstationId { + #region Public Properties + [XmlAttribute("id")] public string IdValue { get; set; } + + #endregion Public Properties } + #endregion Public Classes + + #region Internal Classes /// /// Struttura info JobData da inviare x setup @@ -508,7 +433,27 @@ namespace IOB_WIN_WS.IobWs #endregion Internal Classes } - #endregion Internal Classes + #endregion Public Classes + + #region Internal Methods + + /// + /// Converte valore raw stato impianto nel formato specifico + /// + /// + internal EmmegiResp.StatusDTO GetStatus(string xmlRaw) + { + EmmegiResp.StatusDTO answ = new EmmegiResp.StatusDTO(); + // deserializzo + var serializer = new XmlSerializer(typeof(EmmegiResp.StatusDTO)); + using (var reader = new StringReader(xmlRaw)) + { + answ = (EmmegiResp.StatusDTO)serializer.Deserialize(reader); + } + return answ; + } + + #endregion Internal Methods #region Protected Methods @@ -548,18 +493,22 @@ namespace IOB_WIN_WS.IobWs case EmmegiResp.MachineStatus.WAIT: B_input += (1 << 4); break; + case EmmegiResp.MachineStatus.WORKING: B_input += (1 << 1); break; + case EmmegiResp.MachineStatus.EMERGENCY: case EmmegiResp.MachineStatus.ALARM: case EmmegiResp.MachineStatus.ERROR: B_input += (1 << 3); break; + case EmmegiResp.MachineStatus.OFF_LINE: case EmmegiResp.MachineStatus.OFF: B_input = 0; break; + case EmmegiResp.MachineStatus.READY: case EmmegiResp.MachineStatus.POSITIONING: default: @@ -602,6 +551,77 @@ namespace IOB_WIN_WS.IobWs } } + /// + /// Effettua eventuale file import del file excel come array json in REDIS + /// + /// + protected override bool ProcessFileImport() + { + bool answ = false; + + /* ------------------------------------------ + * esecuzione cablata, si potrebbe costruire una cosa più flessibile tramite conf, + * la procedura prevede: + * - controllo MD5 file sorgente *.xlsx + * - verifica MD5 precedente + * - verifica in redis del dict seralizzato + * + * in caso di mancanza REDIS o variazione MD5 --> lancio script import dati col relativo file di conf + * ------------------------------------------*/ + + // init condizioni check + bool cachePresent = false; + bool changedFile = true; + string newMd5 = ""; + string oldMd5 = ""; + string rawData = ""; + // cerco il file da controllare + string FileInPath = IOBConfFull.OptParGet("FileInPath"); + if (!string.IsNullOrEmpty(FileInPath)) + { + if (File.Exists(FileInPath)) + { + // verifico presenza in cache REDIS + rawData = redisMan.getRSV(rKeyConf); + cachePresent = !string.IsNullOrEmpty(rawData) && rawData.Length > 2; + // calcolo MD5 + newMd5 = baseUtils.GetFileMd5(FileInPath); + // verifico MD5 precedente + oldMd5 = redisMan.getRSV(rKeyMD5); + changedFile = string.IsNullOrEmpty(oldMd5) || !newMd5.Equals(oldMd5); + // se c'è una condizione di trigger effettuo import chiamando task esterno + conf file + if (changedFile || !cachePresent) + { + // recupero path file di conf x import + string FileConfPath = IOBConfFull.OptParGet("FileImportConf"); + if (!string.IsNullOrEmpty(FileConfPath)) + { + // da verificare exclToolDirPath + exclToolDirPath = "Tools"; + // avvio proc import tramite exe tool esterno... + FileProcMan fpm = new FileProcMan("Tools", "ExcImport.exe", rKeyConf, FileConfPath); + fpm.doProcess(FileInPath, 0); + answ = true; + // aggiorno md5... + rKeyMD5 = $"{redisMan.redIobKey}:FPW:FILE-MD5"; + redisMan.setRSV(rKeyMD5, newMd5); + } + } + } + } + // eseguo un SetJobDataEmmegiFPW ogni 5 minuti... + if (DateTime.Now.Subtract(lastSetJob).TotalSeconds > 300) + { + SetJobDataEmmegiFPW(); + lastSetJob = DateTime.Now; + } + + return answ; + } + + + private DateTime lastSetJob = DateTime.Now; + /// /// Esegue lettura dati + salvataggio in LUT /// @@ -614,12 +634,11 @@ namespace IOB_WIN_WS.IobWs lastRestRefreshData = adesso; // in primis testo che sia connessa... var rawData = ExecuteCallGet(GetUrlResource("GetStatus"), true); - lgTrace($"GetConnection | {rawData} | EmmegiFPW.processOtherCounters"); + lgTrace($"refreshData.GetStatus | {rawData}"); // proseguo SOLO SE macchina OK, altrimenti disconnetto... if (!string.IsNullOrEmpty(rawData)) { - // salvo i dati status aggiornati SaveCurrStatus(rawData); lgInfo($"EmmegiFPW | refreshData | {currStatusDTO.Workstation.StatusTimestamp} | Status: {currStatusDTO.Workstation.Status} | TotCount {currStatusDTO.Workstation.TotalOperations}"); @@ -646,15 +665,38 @@ namespace IOB_WIN_WS.IobWs private string basePath = ""; - private DateTime lastRestProcPzCount = DateTime.Now; private DateTime lastRestOtherCount = DateTime.Now; + private DateTime lastRestProcPzCount = DateTime.Now; + private DateTime lastRestRefreshData = DateTime.Now; + /// + /// Dizionario conf parametri taglio x taglierina Emmegi + /// + private Dictionary DictParamsFPW = new Dictionary(); + + /// + /// chiave salvataggio conf USTD + /// + private string rKeyConf = ""; + + /// + /// chiave check file config md5 + /// + private string rKeyMD5 = ""; + #endregion Private Fields #region Private Properties + private EmmegiResp.MachineStatus currState + { + get => currStatusDTO.Workstation.Status; + } + + private EmmegiResp.StatusDTO currStatusDTO { get; set; } = new EmmegiResp.StatusDTO(); + /// /// CHiave redis di salvataggio ultimo set di allarmi scaricato /// @@ -689,6 +731,51 @@ namespace IOB_WIN_WS.IobWs lgInfo($"Status:{Environment.NewLine}{output}"); } + /// + /// Effettua rilettura DB conf ricette FPW SEMPRE da REDIS + /// + private void ReloadConfDb() + { + // verifico presenza in cache REDIS + string rawData = redisMan.getRSV(rKeyConf); + if (!string.IsNullOrEmpty(rawData) && rawData.Length > 2) + { + // deserializzo! + try + { + DictParamsFPW = JsonConvert.DeserializeObject>(rawData); + } + catch (Exception exc) + { + lgError($"Eccezione in reloadConfDb{Environment.NewLine}{exc}"); + } + } + } + + /// + /// Riceve un valore raw xml dello status e salva in LUT tutti i valori... + /// + /// + private void SaveCurrStatus(string rawData) + { + if (!string.IsNullOrEmpty(rawData)) + { + try + { + // deserializzo + currStatusDTO = GetStatus(rawData); + RestLutUpsert("serial", currStatusDTO.Workstation.Id.IdValue); + RestLutUpsert("currOdl", currStatusDTO.Workstation.JobId); + RestLutUpsert("operator", currStatusDTO.Workstation.Operator); + RestLutUpsert("status", currStatusDTO.Workstation.Status); + RestLutUpsert("currCount", currStatusDTO.Workstation.Operations); + RestLutUpsert("totCount", currStatusDTO.Workstation.TotalOperations); + RestLutUpsert("lastStatCh", currStatusDTO.Workstation.StatusTimestamp); + } + catch { } + } + } + /// /// Effettua scrittura degli ODL aperti... /// @@ -696,15 +783,23 @@ namespace IOB_WIN_WS.IobWs private bool SetJobDataEmmegiFPW() { bool answ = false; - // conf path e file string basePath = @"x:\"; - string srcFile = "DATA/TEMPLATE_ODL_USDT.csv"; - string archFile = "DATA/FileTaglierina.xlsx"; + string srcFile = "TOOLS/TEMPLATE_ODL_USDT.csv"; + //string srcFile = "DATA/CONF/TEMPLATE_ODL_USDT.csv"; + + // esegue rilettura DictDB parametri... + ReloadConfDb(); + + // ricerca file csv preesistenti, se fossero stati creati oltre xx Ore prima li considera scaduti + List listFiles = Directory.GetFiles(basePath, "*.csv").ToList(); + + // processo scrittura files PODL con OPRxxx x ogni file missing/scaduto + // NB: impiego array json + dati degli ODL non ancora eseguiti + // leggo il file di conf excel con i valori... - // recupero elenco PODL corrente... List reqPOdlList = MachineNextPodl(); @@ -713,58 +808,46 @@ namespace IOB_WIN_WS.IobWs foreach (var item in reqPOdlList) { - // scrivo x ogni ODL richiesto un file di processing... - string codOdl = $"ODL{item.IdxOdl:00000000}"; - string codExt = item.KeyBCode; - string fileName = Path.Combine(basePath, $"{codExt}.csv"); - string fileCont = rawData; - // effettuo sostituzioni... - fileCont = fileCont.Replace("[[ODL]]", codOdl); - fileCont = fileCont.Replace("[[SERIE]]", "{{SERIE}}"); - fileCont = fileCont.Replace("[[CODICE]]", "{{CODICE}}"); - fileCont = fileCont.Replace("[[ALTEZZA]]", "{{ALTEZZA}}"); - fileCont = fileCont.Replace("[[QUOTA_USCITA]]", "{{QUOTA_USCITA}}"); - fileCont = fileCont.Replace("[[CODICE_LUNGH]]", "{{CODICE_LUNGH}}"); - fileCont = fileCont.Replace("[[QTA]]", $"{item.NumPezzi}"); - fileCont = fileCont.Replace("[[LUNGH]]", "{{LUNGH}}"); - fileCont = fileCont.Replace("[[CLIENTE]]", "COLCOM"); + // verifico che NON sia già presente... FARE controllo con età file (max 60 min?) + if (listFiles.Where(x => x.Contains(item.KeyBCode)).Count() > 0) + { + lgInfo($"Salto file preesistente: {item.KeyBCode}"); + } + else + { + // scrivo x ogni PODL richiesto un file di processing... + string codPOdl = $"PODL{item.IdxPromessa:00000000}"; + string codExt = item.KeyBCode; + string fileName = Path.Combine(basePath, $"{codExt}.csv"); + string fileCont = rawData; + // cerco item nel DB... + if (DictParamsFPW.ContainsKey(item.CodArticolo)) + { + var art = DictParamsFPW[item.CodArticolo]; + if (art != null) + { + // effettuo sostituzioni... + fileCont = fileCont.Replace("[[ODL]]", codPOdl); + fileCont = fileCont.Replace("[[SERIE]]", art.Serie); + fileCont = fileCont.Replace("[[CODICE]]", art.Codice); + fileCont = fileCont.Replace("[[ALTEZZA]]", $"{art.Altezza.ToString("N1", NumberFormatInfo.InvariantInfo)}"); + fileCont = fileCont.Replace("[[QUOTA_USCITA]]", $"{art.QuotaUscita.ToString("N1", NumberFormatInfo.InvariantInfo)}"); + fileCont = fileCont.Replace("[[CODICE_LUNGH]]", $"{art.Codice}_{(art.LungPezzo * 10).ToString("000", NumberFormatInfo.InvariantInfo)}"); + fileCont = fileCont.Replace("[[QTA]]", $"{item.NumPezzi}"); + fileCont = fileCont.Replace("[[LUNGH]]", $"{art.LungPezzo.ToString("N1", NumberFormatInfo.InvariantInfo)}"); + fileCont = fileCont.Replace("[[CLIENTE]]", "COLCOM"); - // scrivo file... - File.WriteAllText(fileName, fileCont); + // scrivo file... + File.WriteAllText(fileName, fileCont); + } + } + } // segno fatto answ = true; } return answ; - } - - /// - /// Effettua eventuale file import, archiviando file importati - /// - es gestione file excel di Giacovelli - /// - es gestione ritorno ricette FIMAT - /// - /// - protected virtual bool ProcessFileImport() - { - bool answ = false; - - /* ------------------------------------------ - * esecuzione cablata, si potrebbe costruire una cosa più flessibile tramite conf: - * Oggetto MultiStepFileImport - * { - * StepName: Step01 - * ProcType: Excel2Json - * FolderIn: xxx - * FolderOut: xxx - * FolderErr: xxx - * },{ - * StepName: Step02 - * ProcType: Json2RegGiac - * FolderIn: xxx - * FolderOut: xxx - * FolderErr: xxx - * } - * ------------------------------------------*/ +#if false if (!string.IsNullOrEmpty(fileImportFolder)) { // verifico esistenza folders... @@ -852,7 +935,7 @@ namespace IOB_WIN_WS.IobWs } } } - return answ; +#endif } /// diff --git a/IOB-WIN-WS/Tools/FPW_import.json b/IOB-WIN-WS/Tools/FPW_import.json new file mode 100644 index 00000000..8d199efc --- /dev/null +++ b/IOB-WIN-WS/Tools/FPW_import.json @@ -0,0 +1,23 @@ +{ + "ArchiveDir": "", + "ConvertDir": "", + "FileInPath": "C:\\Steamware\\EmmegiFPW\\FileTaglierina.xlsx", + "FileOutPath": "", + "IdxODL": 0, + "ProcessParamInt": { + "Codice": 0, + "Serie": 1, + "LungPezzo": 4, + "QuotaUscita": 5, + "LungBarra": 6, + "Altezza": 7 + }, + "ProcessParamStr": {}, + "RedisDB": 10, + "RedisOut": "{{redisKey}}", + "RedisTTL": 600, + "Return": "Redis", + "ReturnDataType": "ParamTaglioUstd", + "TargetName": "Ricette", + "Type": "Excel" +} \ No newline at end of file diff --git a/IOB-WIN-WS/DATA/FileTaglierina.xlsx b/IOB-WIN-WS/Tools/FileTaglierina.xlsx similarity index 100% rename from IOB-WIN-WS/DATA/FileTaglierina.xlsx rename to IOB-WIN-WS/Tools/FileTaglierina.xlsx diff --git a/IOB-WIN-WS/Tools/TEMPLATE_ODL_USDT.csv b/IOB-WIN-WS/Tools/TEMPLATE_ODL_USDT.csv new file mode 100644 index 00000000..3e90e531 --- /dev/null +++ b/IOB-WIN-WS/Tools/TEMPLATE_ODL_USDT.csv @@ -0,0 +1,3 @@ +C;[[ODL]]; +S;[[SERIE]];[[CODICE]];;;[[ALTEZZA]];0;[[QUOTA_USCITA]]; +P;[[CODICE_LUNGH]];[[QTA]];[[LUNGH]];90;90;;;[[CLIENTE]]; \ No newline at end of file