using IOB_UT_NEXT.Config; using IOB_UT_NEXT.Config.Base; using IOB_UT_NEXT.Config.Special; using MapoSDK; using Newtonsoft.Json; using NLog; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Management.Instrumentation; using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Threading; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; using static IOB_UT_NEXT.BaseAlarmConf; using static IOB_UT_NEXT.Config.EnumConf; using static System.Net.Mime.MediaTypeNames; // // This is here so CodeMaid doesn't reorganize this document // namespace IOB_UT_NEXT.Config { /// /// Albero configurazione globale IOB in formato serializable /// [Serializable] public class IobConfTree { /// /// Init classe configurazione /// public IobConfTree() { Log = LogManager.GetCurrentClassLogger(); } /// /// Init classe configurazione da file /// public IobConfTree(string confFilePath) { Log = LogManager.GetCurrentClassLogger(); if (File.Exists(confFilePath)) { IobConfTree newConfObj = new IobConfTree(); // verifico TIPO file... string fileExt = Path.GetExtension(confFilePath); string fileName = Path.GetFileName(confFilePath); string rawData = File.ReadAllText(confFilePath); if (!string.IsNullOrEmpty(rawData)) { // leggo in base al tipo... switch (fileExt) { case "yaml": case "yml": var deserializer = new DeserializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build(); try { newConfObj = deserializer.Deserialize(rawData); } catch (Exception exc) { Log.Error($"Eccezione in LoadFromYaml{Environment.NewLine}{exc}"); } break; default: break; } if (newConfObj != null) { // ora copio in oggetto corrente... General = newConfObj.General; Device = newConfObj.Device; SignalProc = newConfObj.SignalProc; OptPar = newConfObj.OptPar; MapoMes = newConfObj.MapoMes; Special = newConfObj.Special; TCDataConf = newConfObj.TCDataConf; Actions = newConfObj.Actions; // sovrascrivo filename General.FileName = fileName; } } } } /// /// Restituisce un oggetto di conf leggendo INI ed effettuando conversione /// /// /// public static IobConfTree LoadFromINI(string iniFilePath) { IobConfTree newConfObj = new IobConfTree(); try { // leggo file INI IniFile fIni = new IniFile(iniFilePath); string dirPath = Path.GetDirectoryName(iniFilePath); string codIob = Path.GetFileNameWithoutExtension(iniFilePath); // elenco valori OPT_Par già acquisiti da togliere dal dizionario generico in coda List exclOptPar = new List(); // Dati generali (vendor, modello...) int maxErrCheck = 50; if (!string.IsNullOrEmpty(utils.CRS("maxErroriCheck"))) { maxErrCheck = utils.CRI("maxErroriCheck"); } Assembly entryAssembly = Assembly.GetEntryAssembly(); string relVers = entryAssembly != null ? $"{entryAssembly?.GetName().Version}" : $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Version}"; newConfObj.General = new IobDto() { CodIOB = fIni.ReadString("IOB", "IOB_NAME", codIob), CodGruppoIob = fIni.ReadString("OPTPAR", "CodGruppoIob", "ND-00"), DelayReadPzCount = Convert.ToDouble(fIni.ReadString("OPTPAR", "DELAY_READ_PZ_COUNT", "0")), FileName = Path.GetFileName(iniFilePath), Customer = fIni.ReadString("TAGS", "Customer", "EgalWare"), EnabelPodlManFull = bool.Parse(fIni.ReadString("OPTPAR", "EnabelPodlManFull", "false")), EnabRedisQue = bool.Parse(fIni.ReadString("IOB", "EnableRedisQueue", "true")), MaxErroriCheck = fIni.ReadInteger("OPTPAR", "MAX_ERR_CHECK", maxErrCheck), MaxPingRetry = fIni.ReadInteger("OPTPAR", "MAX_PING_RETRY", 5), MinDeltaSec = fIni.ReadInteger("IOB", "MinDeltaSec", 6), RelVers = relVers,// $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Version}", ResetAlarmOnStart = bool.Parse(fIni.ReadString("OPTPAR", "SEND_ALARM_RESET", "false")), SenMachineConf = bool.Parse(fIni.ReadString("OPTPAR", "SEND_MACHINE_CONF", "true")), WaitRecMsec = Convert.ToInt32(fIni.ReadString("OPTPAR", "WAIT_REC_MSEC", "90000")), WatchDogPeriod = Convert.ToInt32(fIni.ReadString("OPTPAR", "WATCHDOG_PERIOD", "2")), DisabWDST = bool.Parse(fIni.ReadString("OPTPAR", "DISABLE_SEND_WDST", "true")) }; // escludo valori OPTPAR gestiti exclOptPar.Add("CodGruppoIob"); exclOptPar.Add("DELAY_READ_PZ_COUNT"); exclOptPar.Add("DISABLE_SEND_WDST"); exclOptPar.Add("EnabelPodlManFull"); exclOptPar.Add("MAX_ERR_CHECK"); exclOptPar.Add("MAX_PING_RETRY"); exclOptPar.Add("SEND_ALARM_RESET"); exclOptPar.Add("SEND_MACHINE_CONF"); exclOptPar.Add("timerIntMs"); exclOptPar.Add("WAIT_REC_MSEC"); exclOptPar.Add("WATCHDOG_PERIOD"); // da togliere da conf app... int uiTimer = utils.CRI("timerIntMs"); string rawTimer = fIni.ReadString("OPTPAR", "timerIntMs", ""); if (!string.IsNullOrEmpty(rawTimer)) { int.TryParse(rawTimer, out uiTimer); } // ultimo controllo: timer deve essere compreso tra 10 a 500 x evitare task troppo veloci o lenti... uiTimer = uiTimer < 10 ? 10 : uiTimer; uiTimer = uiTimer > 500 ? 500 : uiTimer; // init struttura coi valori calcolati da conf... newConfObj.General.Timers = new TimersDto() { MsUI = uiTimer, MsVHF = uiTimer * 6 < 6000 ? uiTimer * 6 : 6000, MsHF = uiTimer * utils.CRI("fastCount") < 15000 ? uiTimer * utils.CRI("fastCount") : 15000, MsMF = uiTimer * utils.CRI("normCount") < 45000 ? uiTimer * utils.CRI("normCount") : 45000, MsLF = uiTimer * utils.CRI("slowCount") < 90000 ? uiTimer * utils.CRI("slowCount") : 90000, MsVLF = uiTimer * utils.CRI("verySlowCount") < 300000 ? uiTimer * utils.CRI("verySlowCount") : 300000, MsSample = uiTimer * utils.CRI("sampleMemCount") < 600000 ? uiTimer * utils.CRI("sampleMemCount") : 600000, }; // tipo adapter// verifico tipo adapter try { newConfObj.General.IobType = (tipoAdapter)Enum.Parse(typeof(tipoAdapter), fIni.ReadString("IOB", "CNCTYPE", "ND")); } catch (Exception exc) { newConfObj.General.IobType = tipoAdapter.ND; string rawVal = fIni.ReadString("IOB", "CNCTYPE", "DEMO"); newConfObj.lgError($"Eccezione in conversione tipo adapter: richiesto {rawVal} | tipo non codificato...{Environment.NewLine}{exc}"); } // Gestione conf ODL newConfObj.Odl = new OdlDto() { AutoChangeOdl = bool.Parse(fIni.ReadString("OPTPAR", "AUTO_CHANGE_ODL", "false")), ChangeOdlMode = fIni.ReadString("OPTPAR", "CHANGE_ODL_MODE", ""), DisableOdl = bool.Parse(fIni.ReadString("OPTPAR", "DISABLE_ODL", "false")), OdlDurationHours = fIni.ReadInteger("OPTPAR", "CHANGE_ODL_HOURS", 24), IdleStateMin = fIni.ReadInteger("OPTPAR", "CHANGE_ODL_IDLE_MIN", 0), // il change ODL al reset contapezzi può essere configurato in 2 modi: con chiave esplicita oppure con il CHANGE_ODL_MODE specifico... ChangeOnResetCount = bool.Parse(fIni.ReadString("OPTPAR", "CHANGE_PZCOUNT_RESET", "false")) || (fIni.ReadString("OPTPAR", "CHANGE_ODL_MODE", "") == "PZCOUNT_RESET"), // gestione precedente: bastava 1 solo pezzo pre... ResetCountMinPre = fIni.ReadInteger("OPTPAR", "RESET_COUNT_PRE", 1), // e reset a zero... ResetCountMaxPost = fIni.ReadInteger("OPTPAR", "RESET_COUNT_POST", 0), }; exclOptPar.Add("AUTO_CHANGE_ODL"); exclOptPar.Add("CHANGE_ODL_MODE"); exclOptPar.Add("CHANGE_ODL_HOURS"); exclOptPar.Add("CHANGE_ODL_IDLE_MIN"); exclOptPar.Add("CHANGE_PZCOUNT_RESET"); exclOptPar.Add("DISABLE_ODL"); exclOptPar.Add("RESET_COUNT_PRE"); exclOptPar.Add("RESET_COUNT_POST"); // gestione FluxLog float globDBand = 1; string sDBand = fIni.ReadString("OPTPAR", "GLOBAL_DBAND", ""); if (!string.IsNullOrEmpty(sDBand)) { float.TryParse(sDBand, out globDBand); } newConfObj.FluxLog = new FluxLogDto() { AutoSnapshotDossier = bool.Parse(fIni.ReadString("OPTPAR", "AUTO_SNAPSHOT_DOSSIER", "false")), CopyDyn2MemWrite = bool.Parse(fIni.ReadString("OPTPAR", "COPY_DYN2PROD_DATA", "false")), DemFactDynData = fIni.ReadInteger("OPTPAR", "DEM_FACT_DYN_DATA", 1), DisDynData = bool.Parse(fIni.ReadString("OPTPAR", "DISABLE_DYN_DATA", "false")), DisDynDataRangeCheck = bool.Parse(fIni.ReadString("OPTPAR", "disDynDataRangeCheck", "false")), EnableDynData = bool.Parse(fIni.ReadString("OPTPAR", "ENABLE_DYN_DATA", "true")), EnableFilt = bool.Parse(fIni.ReadString("OPTPAR", "ENABLE_DATA_FILTER", "false")), EnableOverrides = bool.Parse(fIni.ReadString("OPTPAR", "ENABLE_OVERRIDES", "false")), EnableSlowData = bool.Parse(fIni.ReadString("OPTPAR", "ENABLE_SLOW_DATA", "false")), ForceDynData = bool.Parse(fIni.ReadString("OPTPAR", "FORCE_DYN_DATA", "false")), GlobalDeadBand = globDBand, MaxSecReload = fIni.ReadInteger("OPTPAR", "MAX_ELAPSED_TIME_SEC", 3600), SamplePeriod = fIni.ReadInteger("OPTPAR", "BASE_SAMPLE_PERIOD", 3600), SendDynDataRec = bool.Parse(fIni.ReadString("OPTPAR", "SEND_DYN_DATA_FLOG", "false")), VetoSendSnapshotSec = fIni.ReadInteger("OPTPAR", "VETO_SEND_SNAPSHOT", 6) }; exclOptPar.Add("AUTO_SNAPSHOT_DOSSIER"); exclOptPar.Add("COPY_DYN2PROD_DATA"); exclOptPar.Add("BASE_SAMPLE_PERIOD"); exclOptPar.Add("DEM_FACT_DYN_DATA"); exclOptPar.Add("DISABLE_DYN_DATA"); exclOptPar.Add("disDynDataRangeCheck"); exclOptPar.Add("ENABLE_DATA_FILTER"); exclOptPar.Add("ENABLE_OVERRIDES"); exclOptPar.Add("ENABLE_DYN_DATA"); exclOptPar.Add("ENABLE_SLOW_DATA"); exclOptPar.Add("FORCE_DYN_DATA"); exclOptPar.Add("GLOBAL_DBAND"); exclOptPar.Add("MAX_ELAPSED_TIME_SEC"); exclOptPar.Add("SEND_DYN_DATA_FLOG"); exclOptPar.Add("VETO_SEND_SNAPSHOT"); newConfObj.Device = new DeviceDto() { DisabExeTask = bool.Parse(fIni.ReadString("IOB", "DIS_EXE_TASK", "false")), DisabPing = bool.Parse(fIni.ReadString("OPTPAR", "NO_PING", "false")), DisabStateCh = bool.Parse(fIni.ReadString("IOB", "DIS_STATE_CH", "false")), DisabSigIn = bool.Parse(fIni.ReadString("OPTPAR", "VETO_SIG_IN", "false")), DisabResendScaduto = bool.Parse(fIni.ReadString("OPTPAR", "VETO_SCADUTO", "false")), EnabMemRewrite = bool.Parse(fIni.ReadString("OPTPAR", "ENABLE_MEM_REWRITE", "true")), EnabProgName = bool.Parse(fIni.ReadString("CNC", "GETPRGNAME", "true")), EnabPzCount = utils.CRB("enableContapezzi"), ExeModeCheckBypass = bool.Parse(fIni.ReadString("OPTPAR", "EXEMODE_CHECK_BYPASS", "false")), Model = fIni.ReadString("MACHINE", "MODEL", "ND"), MinRespTimeMs = fIni.ReadInteger("OPTPAR", "MIN_RESP_TIME_MS", 5), MultiIobListRaw = fIni.ReadString("OPTPAR", "IOB_MULTI_CNAME", ""), NumArtMode = fIni.ReadString("OPTPAR", "SET_NUM_ART", ""), NumOdlMode = fIni.ReadString("OPTPAR", "SET_NUM_COM", ""), PoweroffTimeOutSec = fIni.ReadInteger("OPTPAR", "POWEROFF_TIMEOUT_SEC", 120), PzCadMode = fIni.ReadString("OPTPAR", "PZCAD_MODE", ""), PzCountDelay = utils.CRI("pzCountDelay"), PzCountMode = fIni.ReadString("OPTPAR", "PZCOUNT_MODE", ""), PzReqMode = fIni.ReadString("OPTPAR", "PZREQ_MODE", ""), PzTotMode = fIni.ReadString("OPTPAR", "PZGTOT_MODE", ""), ReadErrorMax = fIni.ReadInteger("OPTPAR", "READ_ERROR_MAX", 20), ReadErrorSleepTime = fIni.ReadInteger("OPTPAR", "READ_ERROR_SLEEP_TIME", 20000), StartupVetoQueueIN = fIni.ReadInteger("OPTPAR", "VETO_QUEUE_IN", 10), Vendor = fIni.ReadString("MACHINE", "VENDOR", "STEAMWARE"), Connect = new ConnectionDto() { IpAddr = fIni.ReadString("CNC", "IP", "::1"), PingIpAddr = fIni.ReadString("CNC", "PING_IP", fIni.ReadString("CNC", "IP", "::1")), PingMsTimeout = fIni.ReadInteger("IOB", "PING_MS_TIMEOUT", 500), Port = fIni.ReadString("CNC", "PORT", "0"), MaxTryPing = fIni.ReadInteger("OPTPAR", "MAX_TRY_PING", 4), EnableRestart = bool.Parse(fIni.ReadString("OPTPAR", "ENABLE_CLI_RESTART", "false")) } }; exclOptPar.Add("ENABLE_CLI_RESTART"); exclOptPar.Add("ENABLE_MEM_REWRITE"); exclOptPar.Add("EXEMODE_CHECK_BYPASS"); exclOptPar.Add("IOB_MULTI_CNAME"); exclOptPar.Add("MAX_TRY_PING"); exclOptPar.Add("MIN_RESP_TIME_MS"); exclOptPar.Add("NO_PING"); exclOptPar.Add("POWEROFF_TIMEOUT_SEC"); exclOptPar.Add("PZCAD_MODE"); exclOptPar.Add("PZCOUNT_MODE"); exclOptPar.Add("PZREQ_MODE"); exclOptPar.Add("PZGTOT_MODE"); exclOptPar.Add("READ_ERROR_MAX"); exclOptPar.Add("READ_ERROR_SLEEP_TIME"); exclOptPar.Add("SET_NUM_ART"); exclOptPar.Add("SET_NUM_COM"); exclOptPar.Add("VETO_QUEUE_IN"); exclOptPar.Add("VETO_SIG_IN"); exclOptPar.Add("VETO_SCADUTO"); // multi... if (!string.IsNullOrEmpty(fIni.ReadString("OPTPAR", "IS_MULTI", "false"))) { string rawVal = fIni.ReadString("OPTPAR", "IS_MULTI", ""); if (rawVal.Length > 1) { newConfObj.Device.IsMulti = Convert.ToBoolean(fIni.ReadString("OPTPAR", "IS_MULTI", "false")); } else { newConfObj.Device.IsMulti = fIni.ReadInteger("OPTPAR", "IS_MULTI", 0) == 1; } } exclOptPar.Add("IS_MULTI"); // verifico comunque se ci fosse Device.MultiIobListRaw if (!string.IsNullOrEmpty(newConfObj.Device.MultiIobListRaw)) { newConfObj.Device.IsMulti = true; newConfObj.Device.MultiIobList = newConfObj.Device.MultiIobListRaw.Split(',').ToList() ?? new List(); } // BLINK newConfObj.SignalProc.BlinkMaxCounter = Convert.ToInt32(fIni.ReadString("BLINK", "MAX_COUNTER_BLINK", "1")); newConfObj.SignalProc.BlinkFilterMask = Convert.ToInt32(fIni.ReadString("BLINK", "BLINK_FILT", "0")); newConfObj.TCDataConf.MaxDelayFactor = Convert.ToDouble(fIni.ReadString("OPTPAR", "TC_MAX_TC_FACTOR", "1.2").Replace(".", ",")); newConfObj.TCDataConf.Lambda = Convert.ToDouble(fIni.ReadString("OPTPAR", "TC_LAMBDA", "0.5").Replace(".", ",")); newConfObj.TCDataConf.MaxIncrPz = Convert.ToDouble(fIni.ReadString("OPTPAR", "TC_MAX_INCR", "5").Replace(".", ",")); exclOptPar.Add("TC_MAX_TC_FACTOR"); exclOptPar.Add("TC_LAMBDA"); exclOptPar.Add("TC_MAX_INCR"); // Server string MpIp = fIni.ReadString("SERVER", "MPIP", "::1"); if (!string.IsNullOrEmpty(MpIp)) { newConfObj.MapoMes.Transport = MpIp.StartsWith("https://") ? "https" : "http"; newConfObj.MapoMes.IpAddr = MpIp.Replace($"{newConfObj.MapoMes.Transport}://", ""); // tolgo http/https... newConfObj.MapoMes.ClientInstall = "SteamWare"; } string MpUrl = fIni.ReadString("SERVER", "MPURL", ""); if (!string.IsNullOrEmpty(MpUrl)) { newConfObj.MapoMes.BaseAppUrl = $"{MpUrl}/".Replace("//", "/"); } // copio conf ping come x server... newConfObj.MapoMes.DisabPing = newConfObj.Device.DisabPing; // verifico opzione per disabilitare FeepAlive (es non voglio keepalive e info IOB da acquisitori potenza che sovrascrivono dati IOB macchina) newConfObj.MapoMes.DisabKeepAlive = bool.Parse(fIni.ReadString("OPTPAR", "DISAB_KEEPALIVE", "false")); exclOptPar.Add("DISAB_KEEPALIVE"); // Gestione contapezzi... newConfObj.Counters.EnabSendPzcBlock = bool.Parse(fIni.ReadString("OPTPAR", "ENABLE_SEND_PZC_BLOCK", "false")); newConfObj.Counters.EnableSetPzCount = bool.Parse(fIni.ReadString("OPTPAR", "ENABLE_PZ_CNT", "false")); newConfObj.Counters.EnableSetPzReq = bool.Parse(fIni.ReadString("OPTPAR", "ENABLE_PZ_REQ", "false")); newConfObj.Counters.MaxIncrPzCountPerc = fIni.ReadInteger("OPTPAR", "MAX_PZ_INCR_PERC", 300); newConfObj.Counters.ResetOnProdEnd = bool.Parse(fIni.ReadString("OPTPAR", "ENABLE_PZ_RESET_ENDPROD", "false")); newConfObj.Counters.ResetOnSetupStart = bool.Parse(fIni.ReadString("OPTPAR", "ENABLE_PZ_RESET", "false")); newConfObj.Counters.ResetOnSetupStop = bool.Parse(fIni.ReadString("OPTPAR", "ENABLE_PZ_RESET_stopSetup", "false")); newConfObj.Counters.SendPzcBlockMin = fIni.ReadInteger("OPTPAR", "MIN_SEND_PZC_BLOCK", 0); newConfObj.Counters.SendPzcBlockMax = fIni.ReadInteger("OPTPAR", "MAX_SEND_PZC_BLOCK", 100); newConfObj.Counters.SendPzCountMode = fIni.ReadString("OPTPAR", "SEND_PZCNT_MODE", "DIRECT"); exclOptPar.Add("ENABLE_SEND_PZC_BLOCK"); exclOptPar.Add("ENABLE_PZ_CNT"); exclOptPar.Add("ENABLE_PZ_REQ"); exclOptPar.Add("ENABLE_PZ_RESET_ENDPROD"); exclOptPar.Add("ENABLE_PZ_RESET"); exclOptPar.Add("ENABLE_PZ_RESET_stopSetup"); exclOptPar.Add("MAX_PZ_INCR_PERC"); exclOptPar.Add("MAX_SEND_PZC_BLOCK"); exclOptPar.Add("MIN_SEND_PZC_BLOCK"); exclOptPar.Add("SEND_PZCNT_MODE"); // init special a prescindere... newConfObj.Special = new SpecializedDto(); // FTP string ftpServer = fIni.ReadString("OPTPAR", "FTP_SERVER", ""); if (!string.IsNullOrEmpty(ftpServer)) { if (newConfObj.Special.FtpConf == null) { newConfObj.Special.FtpConf = new FtpDto() { Server = ftpServer, User = fIni.ReadString("OPTPAR", "FTP_USER", ""), Passwd = fIni.ReadString("OPTPAR", "FTP_PWD", ""), CertValue = fIni.ReadString("OPTPAR", "FTP_CERT", ""), CsvAddHeader = bool.Parse(fIni.ReadString("OPTPAR", "CSV_ADD_HEADER", "false")), SkipCert = bool.Parse(fIni.ReadString("OPTPAR", "FTP_SKIP", "true")), DirLocal = fIni.ReadString("OPTPAR", "FTP_LOC_DIR", ""), DirRemote = fIni.ReadString("OPTPAR", "FTP_REM_DIR", ""), }; // continuo col resto } } exclOptPar.Add("FTP_SERVER"); exclOptPar.Add("FTP_USER"); exclOptPar.Add("FTP_PWD"); exclOptPar.Add("FTP_CERT"); exclOptPar.Add("CSV_ADD_HEADER"); exclOptPar.Add("FTP_SKIP"); exclOptPar.Add("FTP_LOC_DIR"); exclOptPar.Add("FTP_REM_DIR"); // allarmi... string jsonAlarms = fIni.ReadString("OPTPAR", "ALARM_CONF", ""); if (!string.IsNullOrEmpty(jsonAlarms)) { string alarmsFileName = Path.Combine(dirPath, jsonAlarms); if (File.Exists(alarmsFileName)) { newConfObj.lgInfo($"Apertura file {alarmsFileName}"); StreamReader reader = new StreamReader(alarmsFileName); string jsonData = reader.ReadToEnd(); reader.Dispose(); if (!string.IsNullOrEmpty(jsonData)) { newConfObj.lgInfo($"File json ALLARMI composto da {jsonData.Length} caratteri"); try { newConfObj.lgInfo("loadMemConf | Inizio setup allarmi"); newConfObj.Alarms = new AlarmDto(); newConfObj.Alarms.AlarmMaps = JsonConvert.DeserializeObject>(jsonData); newConfObj.lgInfo("loadMemConf | Fine setup allarmi"); } catch (Exception exc) { newConfObj.lgError($"Eccezione in decodifica conf json degli ALLARMI{Environment.NewLine}{exc}"); } } else { newConfObj.lgError("Errore in loadMemConf: file ALLARMI json vuoto!"); } } else { newConfObj.lgError($"File allarmi non trovato: {alarmsFileName}"); } } else { newConfObj.lgInfo("loadMemConf: non trovata opzione ALARM_CONF in file INI"); } exclOptPar.Add("ALARM_CONF"); // file conf... if (!string.IsNullOrEmpty(fIni.ReadString("OPTPAR", "FILE_IMPORT_FOLDER", ""))) { if (newConfObj.Special.FileConf == null) { newConfObj.Special.FileConf = new FileDto() { ImportFolder = fIni.ReadString("OPTPAR", "FILE_IMPORT_FOLDER", ""), ImportType = fIni.ReadString("OPTPAR", "FILE_IMPORT_TYPE", "*.xslx"), ArchiveFolder = fIni.ReadString("OPTPAR", "FILE_ARCHIVE_FOLDER", ""), ExcelToolDirPath = fIni.ReadString("OPTPAR", "EXCL_TOOL_PATH", "") }; } } exclOptPar.Add("FILE_IMPORT_FOLDER"); exclOptPar.Add("FILE_IMPORT_TYPE"); exclOptPar.Add("FILE_ARCHIVE_FOLDER"); exclOptPar.Add("EXCL_TOOL_PATH"); // Altro newConfObj.IobMan.MinDeltaSec = fIni.ReadInteger("IOB", "MinDeltaSec", 6); // alla fine verifico eventuali eccezioni alla gestione pzCount con abilitazione esplicita if (!string.IsNullOrEmpty(fIni.ReadString("OPTPAR", "ENABLE_PZCOUNT", ""))) { newConfObj.Device.EnabPzCount = bool.Parse(fIni.ReadString("OPTPAR", "ENABLE_PZCOUNT", "false")); } // o al contrario con disabilitazione esplicita if (!string.IsNullOrEmpty(fIni.ReadString("OPTPAR", "DISABLE_PZCOUNT", ""))) { newConfObj.Device.EnabPzCount = !bool.Parse(fIni.ReadString("OPTPAR", "DISABLE_PZCOUNT", "false")); } // gestione override idx articoli... if (!string.IsNullOrEmpty(fIni.ReadString("OPTPAR", "NUM_ART_CHR_TRIM", ""))) { newConfObj.Device.NumArtCharTrim = bool.Parse(fIni.ReadString("OPTPAR", "NUM_ART_CHR_TRIM", "false")); } exclOptPar.Add("ENABLE_PZCOUNT"); exclOptPar.Add("DISABLE_PZCOUNT"); exclOptPar.Add("NUM_ART_CHR_TRIM"); bool doExclOptPar = bool.Parse(fIni.ReadString("OPTPAR", "DO_EXCLUDE_OPT_PAR", "true")); exclOptPar.Add("DO_EXCLUDE_OPT_PAR"); // se è tipo ping if (newConfObj.General.IobType == tipoAdapter.PingWatchdog) { // verifico SE ci siano in optPar indicazioni x valori da inviare al poweron/poweroff newConfObj.Special.PingConf = new PingDto(); newConfObj.Special.PingConf.B_PowerOff = fIni.ReadInteger("OPTPAR", "B_IN_OFF", 0); newConfObj.Special.PingConf.B_PowerOn = fIni.ReadInteger("OPTPAR", "B_IN_ON", 1); newConfObj.Special.PingConf.VetoCheckSec = fIni.ReadInteger("OPTPAR", "VETO_PING_SEC", 5); } exclOptPar.Add("B_IN_OFF"); exclOptPar.Add("B_IN_ON"); exclOptPar.Add("VETO_PING_SEC"); // caricamento finale OptPar Dictionary optParRead = new Dictionary(); string[] optParRows = fIni.ReadSection("OPTPAR"); if (optParRows.Length > 0) { string[] kvp; if (doExclOptPar) { try { foreach (var item in optParRows) { kvp = item.Split('='); // escludo valori già acquisiti... if (!exclOptPar.Contains(kvp[0])) { optParRead.Add(kvp[0], kvp[1]); } } newConfObj.lgDebug($"Caricati {optParRead.Count} parametri opzionali da OPTPAR"); } catch (Exception exc) { newConfObj.lgError($"EXCEPTION in fase di lettura OPTPAR: {Environment.NewLine}{exc}"); } } else { foreach (var item in optParRows) { kvp = item.Split('='); optParRead.Add(kvp[0], kvp[1]); } } } // riordino alfabeticamente optParRead = optParRead.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); newConfObj.OptPar = optParRead; // verifico se ho conf json speciali: LUT decodifica PARAMETRI (uso una delle chaivi ammesse...) List memKeyNames = new List() { "PARAM_CONF", "OPC_PARAM_CONF", "MTC_PARAM_CONF" }; string memFileName = ""; foreach (var memKey in memKeyNames) { if (optParRead.ContainsKey(memKey)) { memFileName = optParRead[memKey]; newConfObj.lgDebug($"loadMemConf: trovata opzione per recupero IobConfTree.Memory in file INI | key: {memKey} | file:{memFileName} | valori testati: {String.Join(" | ", memKeyNames.ToArray())}"); break; } } if (string.IsNullOrEmpty(memFileName)) { newConfObj.lgInfo($"loadMemConf: non trovata opzione per recupero IobConfTree.Memory in file INI, valori testati: {String.Join(" | ", memKeyNames.ToArray())}"); } string jsonFileName = Path.Combine(dirPath, memFileName); if (File.Exists(jsonFileName)) { newConfObj.lgInfo($"Apertura file {jsonFileName}"); using (StreamReader reader = new StreamReader(jsonFileName)) { string jsonData = reader.ReadToEnd(); if (!string.IsNullOrEmpty(jsonData)) { if (newConfObj.Memory == null) { newConfObj.Memory = new plcMemMapExt(); } try { newConfObj.Memory = JsonConvert.DeserializeObject(jsonData); } catch (Exception exc) { newConfObj.lgError($"Eccezione in decodifica conf json{Environment.NewLine}{exc}"); } } else { newConfObj.lgError("Errore in loadMemConf: file json vuoto!"); } } } #if false if (optParRead.ContainsKey("PARAM_CONF")) { string jsonParams = optParRead["PARAM_CONF"]; if (!string.IsNullOrEmpty(jsonParams)) { string jsonFileName = Path.Combine(dirPath, jsonParams); if (File.Exists(jsonFileName)) { newConfObj.lgInfo($"Apertura file {jsonFileName}"); using (StreamReader reader = new StreamReader(jsonFileName)) { string jsonData = reader.ReadToEnd(); if (!string.IsNullOrEmpty(jsonData)) { if (newConfObj.Memory == null) { newConfObj.Memory = new plcMemMapExt(); } try { newConfObj.Memory = JsonConvert.DeserializeObject(jsonData); } catch (Exception exc) { newConfObj.lgError($"Eccezione in decodifica conf json{Environment.NewLine}{exc}"); } } else { newConfObj.lgError("Errore in loadMemConf: file json vuoto!"); } } } } else { newConfObj.lgInfo("loadMemConf: non trovata opzione PARAM_CONF in file INI"); } } #endif // parametri opzionali Siemens if (!string.IsNullOrEmpty(fIni.ReadString("CNC", "CPUTYPE", ""))) { newConfObj.Special.SiemensConf = new SiemensDto(); // CPU Siemens newConfObj.Special.SiemensConf.CpuType = fIni.ReadString("CNC", "CPUTYPE", ""); newConfObj.Special.SiemensConf.Rack = (short)fIni.ReadInteger("CNC", "RACK", 0); newConfObj.Special.SiemensConf.Slot = (short)fIni.ReadInteger("CNC", "SLOT", 0); // memoria Siemens! newConfObj.Special.SiemensConf.MemAddrRead = fIni.ReadString("MEMORY", "ADDR_READ", ""); newConfObj.Special.SiemensConf.MemAddrWrite = fIni.ReadString("MEMORY", "ADDR_WRITE", ""); newConfObj.Special.SiemensConf.MemSizeRead = fIni.ReadInteger("MEMORY", "SIZE_READ", 0); newConfObj.Special.SiemensConf.MemSizeWrite = fIni.ReadInteger("MEMORY", "SIZE_WRITE", 0); } // parametri opzionali OpcUA if (optParRead.ContainsKey("OPC_PARAM_CONF")) { string opcParamConf = optParRead["OPC_PARAM_CONF"]; if (!string.IsNullOrEmpty(opcParamConf)) { string jsonOpcFileName = Path.Combine(dirPath, opcParamConf); if (File.Exists(jsonOpcFileName)) { newConfObj.lgInfo($"Apertura file {jsonOpcFileName}"); using (StreamReader reader = new StreamReader(jsonOpcFileName)) { string jsonData = reader.ReadToEnd().Replace("\n", "").Replace("\r", ""); if (!string.IsNullOrEmpty(jsonData)) { newConfObj.lgDebug($"File json composto da {jsonData.Length} caratteri"); if (newConfObj.Special.OpcUaConf == null) { newConfObj.Special.OpcUaConf = new OpcUaParamConf(); } try { newConfObj.Special.OpcUaConf = JsonConvert.DeserializeObject(jsonData); newConfObj.lgDebug($"Decodifica aree OpcUaParamConf: trovati {newConfObj.Special.OpcUaConf.paramsEndThresh.Count} valori paramsEndThresh"); #if false // sistemo se ci sono dati memMap... if (newConfObj.Memory == null) { newConfObj.Memory = new plcMemMapExt(); } try { newConfObj.Memory = JsonConvert.DeserializeObject(jsonData); } catch (Exception exc) { newConfObj.lgError($"Eccezione in decodifica conf json{Environment.NewLine}{exc}"); } #endif // elimino conf memoria da area OPC che tanto è già OK... newConfObj.Special.OpcUaConf.mMapRead = new Dictionary(); newConfObj.Special.OpcUaConf.mMapWrite = new Dictionary(); } catch (Exception exc) { newConfObj.lgError($"Eccezione in decodifica conf json OPC-UA{Environment.NewLine}{exc}"); } } else { newConfObj.lgError("Errore in loadOpcUaConf: file json vuoto!"); } } } } } // parametri opzionali BankConf string[] memSection = fIni.ReadSection("MEMORY"); // in primis SE ho qualcosa... if (memSection != null && memSection.Count() > 0) { // trasformo in array... Dictionary memDict = new Dictionary(); foreach (var item in memSection) { // verifica preliminare NON sia commento (inizia per ";") if (!item.StartsWith(";") && item.Contains("=")) { var KVP = item.Split('='); memDict.Add(KVP[0], KVP[1]); } } // ora se ho qualcosa proseguo... if (memDict.Count() > 0) { // cerco dati x popolare SigLUT foreach (var item in memDict.Where(x => x.Key.StartsWith("BIT"))) { if (newConfObj.Device.SigLUT.ContainsKey(item.Key)) { newConfObj.Device.SigLUT[item.Key] = item.Value; } else { newConfObj.Device.SigLUT.Add(item.Key, item.Value); } } // cerco dati specifici x popolare l'area Memoria (Fanuc/Mitsubischi/...) if (memDict.Where(x => x.Key.StartsWith("AREA") || x.Key.StartsWith("PAR") || x.Key.StartsWith("SIGN")).Count() > 0) { // init info bank memoria... if (newConfObj.Special.BankConf == null) { newConfObj.Special.BankConf = new MemBankDto(); } // inizio setup prendendo quelli con valori addrSize foreach (var item in memDict.Where(x => x.Key.EndsWith("SIZE"))) { int addrSize = 0; int.TryParse(item.Value, out addrSize); // salvo solo quelli con valori addrSize > 0 if (addrSize > 0) { string mId = item.Key.Replace("_SIZE", ""); // cerco record inizio var valStart = memDict.Where(x => x.Key == item.Key.Replace("_SIZE", "_START")).Select(x => x.Value).FirstOrDefault(); if (!string.IsNullOrEmpty(valStart)) { int addrStart = 0; int.TryParse(valStart, out addrStart); var memArea = new Mem.MemAreaDto() { Start = addrStart, Size = addrSize }; if (newConfObj.Special.BankConf.AreaConf.ContainsKey(mId)) { newConfObj.Special.BankConf.AreaConf[mId] = memArea; } else { newConfObj.Special.BankConf.AreaConf.Add(mId, memArea); } } } } } } } // cerco in OPTPAR la conf json del dizionario StepActionList if (optParRead.ContainsKey("STEP_ACTION_CONF")) { string opcParamConf = optParRead["STEP_ACTION_CONF"]; if (!string.IsNullOrEmpty(opcParamConf)) { string jsonStepActFileName = Path.Combine(dirPath, opcParamConf); if (File.Exists(jsonStepActFileName)) { newConfObj.lgInfo($"Apertura file {jsonStepActFileName}"); using (StreamReader reader = new StreamReader(jsonStepActFileName)) { string jsonData = reader.ReadToEnd().Replace("\n", "").Replace("\r", ""); if (!string.IsNullOrEmpty(jsonData)) { newConfObj.lgDebug($"File json composto da {jsonData.Length} caratteri"); if (newConfObj.Actions == null) { newConfObj.Actions = new ActionDto(); //newConfObj.Actions.StepActionList = new Dictionary(); try { newConfObj.Actions = JsonConvert.DeserializeObject(jsonData); } catch (Exception exc) { newConfObj.lgError($"Eccezione in decodifica conf json STEP_ACTION_CONF{Environment.NewLine}{exc}"); } } } } } } } // salvo eventuale memTrace... if (!string.IsNullOrEmpty(fIni.ReadString("OPTPAR", "MEM_2_TRACE", ""))) { if (newConfObj.Special.BankConf == null) { newConfObj.Special.BankConf = new MemBankDto(); } newConfObj.Special.BankConf.Mem2Trace = fIni.ReadString("OPTPAR", "MEM_2_TRACE", ""); exclOptPar.Add("MEM_2_TRACE"); } // gestione speciale x type MBus if ($"{newConfObj.General.IobType}".StartsWith("MODBUS_TCP")) { ModBusTcpParamConf newMBusPar = new ModBusTcpParamConf() { memAddrRead = fIni.ReadString("MEMORY", "ADDR_READ", ""), memAddrWrite = fIni.ReadString("MEMORY", "ADDR_WRITE", ""), memSizeRead = fIni.ReadInteger("MEMORY", "SIZE_READ", 0), memSizeWrite = fIni.ReadInteger("MEMORY", "SIZE_WRITE", 0), holdRegBaseAddr = fIni.ReadInteger("MEMORY", "HR_BASE_ADDR", 40001), useCalcBaseAddr = fIni.ReadBoolean("MEMORY", "CALC_BASE_ADDR", true), // valore delta base e shift deltaBase = fIni.ReadInteger("MEMORY", "DELTA_BASE", 0), indexLutCorr = fIni.ReadInteger("MEMORY", "INDEX_LUT_CORR", 0), // verifico eventuale parametro memoria estesa (non 0...10'000 ma 0...xFFFF=65536) modbusExtReg = fIni.ReadBoolean("MEMORY", "MODBUS_EXT_REG") }; newConfObj.Special.ModbusConf = newMBusPar; } } catch (Exception exc) { newConfObj.lgError($"EXCEPTION in decodifica IobConfTree: {Environment.NewLine}{exc}"); } return newConfObj; } /// /// Calcola la scadenza in ms del timer richiesto /// /// Tipo di ciclo richiesto x estrarre da obj conf /// Fattore di perturbazione random come valore +/- da aggiungere in % /// default 0 = deterministico /// Range ammesso: 0..0.5 /// public int TimerMs(gatherCycle ciclo, double percFact = 0) { // default a 1sec... int answ = 1000; // verifica quale valore recuperare switch (ciclo) { case gatherCycle.VHF: answ = General.Timers.MsVHF; break; case gatherCycle.HF: answ = General.Timers.MsHF; break; case gatherCycle.MF: answ = General.Timers.MsMF; break; case gatherCycle.LF: answ = General.Timers.MsLF; break; case gatherCycle.VLF: answ = General.Timers.MsVLF; break; default: break; } // se richeisto perturbo... if (percFact != 0) { // prendo valore in modulo percFact = Math.Abs(percFact); // verifico sia < 50%... percFact = percFact > 0.5 ? 0.5 : percFact; // mi baso su un fattore 1'000 da perturbare int mult = 1000; answ = (answ * rand.Next((int)(mult * (1 - percFact)), (int)(mult * (1 + percFact))) / mult); } return answ; } /// /// Info generali delative all'IOB impiegato /// public IobDto General { get; set; } = new IobDto(); /// /// Parametri server Mapo MES /// public ServerMapoDto MapoMes { get; set; } = new ServerMapoDto(); /// /// Setup info verso IOB-MAN /// public IobManDto IobMan { get; set; } = new IobManDto(); /// /// Gestione specifica azioni sul contapezzi /// public CounterDto Counters { get; set; } = new CounterDto(); /// /// Gestione configurazione parametri relativi ai FluxLog /// public FluxLogDto FluxLog { get; set; } = new FluxLogDto(); /// /// Configurazione specifica gestione ODL /// public OdlDto Odl { get; set; } = new OdlDto(); /// /// Info relative al device interconnesso /// public DeviceDto Device { get; set; } = new DeviceDto(); /// /// Struttura memoria PLC x lettura/scrittura /// public plcMemMapExt Memory { get; set; } /// /// Setup processing dati in ingresso (es: blink segnali) /// public InputSignalDto SignalProc { get; set; } = new InputSignalDto(); /// /// Dati relativi ai parametri gestione tempo ciclo /// public TCDataDto TCDataConf { get; set; } = new TCDataDto(); /// /// Configurazione Allarmi /// public AlarmDto Alarms { get; set; } /// /// Configurazione speciale comportamenti IOB (es setup) /// public ActionDto Actions { get; set; } /// /// Dizionario delle traduzioni termini chiave/valore /// public Dictionary ItemTranslation { get; set; } = new Dictionary(); /// /// Recupera traduzoine item richiesta /// /// /// public string ItemTranslationGet(string key) { string answ = ""; if (ItemTranslation != null && ItemTranslation.ContainsKey(key)) { answ = ItemTranslation[key]; } return answ; } /// /// Dizionario dei parametri opzionali /// public Dictionary OptPar { get; set; } = new Dictionary(); /// /// Recupera valore della chiave specifica richiesta /// /// /// public string OptParGet(string key) { string answ = ""; if (OptPar != null && OptPar.Count > 0 && OptPar.ContainsKey(key)) { answ = OptPar[key]; } else { #if DEBUG lgError($"OptParGet | key not found: {key}"); #else lgDebug($"OptParGet | key not found: {key}"); #endif } return answ; } /// /// Configurazione speciale/opzionale per tipo IOB /// public SpecializedDto Special { get; set; } #region Metodi Serializzazione /// /// Restituisce conf serializzata in formato JSON /// /// /// public string GetJson() { string rawdata = JsonConvert.SerializeObject(this, Formatting.Indented); return rawdata; } /// /// Restituisce conf serializzata in formato YAML /// /// /// public string GetYaml() { // opzioni alternative: PascalCaseNamingConvention (iniziale masiucola) o lowerCaseNamingConvention var serializer = new SerializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build(); var rawdata = serializer.Serialize(this); return rawdata; } #endregion #region Metodi Load/Save /// /// Scrive conf serializzata in formato JSON /// /// /// public bool SaveJson(string filePath) { bool answ = false; try { string rawdata = GetJson(); File.WriteAllText(filePath, rawdata); answ = true; } catch { } return answ; } /// /// Scrive conf serializzata in formato YAML /// /// /// public bool SaveYaml(string filePath) { bool answ = false; try { var rawdata = GetYaml(); File.WriteAllText(filePath, rawdata); answ = true; } catch { } return answ; } /// /// Invia a server conf serializzata in formato YAML /// /// URL x chiamata salvtaggio yaml /// public bool SendConfYaml(string urlSaveYaml) { bool answ = false; try { string rawData = GetYaml(); // prova anche ad inviare il contenuto al server IO... string resp = utils.ExecCallPostPlain($"{urlSaveYaml}", rawData); answ = resp == "OK"; } catch { } return answ; } #endregion #region Logging /// /// oggetto logging /// protected Logger Log;// = LogManager.GetCurrentClassLogger(); /// /// Effettua logging DEBUG corretto impostanto anche la variabile IOB prima di scrivere... /// /// protected void lgDebug(string txt2log) { Log.Factory.Configuration.Variables["codIOB"] = General.FilenameIOB; Log.Debug(txt2log); } /// /// Effettua logging ERROR corretto impostanto anche la variabile IOB prima di scrivere... /// /// protected void lgError(string txt2log) { if (!string.IsNullOrEmpty(txt2log)) { Log.Factory.Configuration.Variables["codIOB"] = General.FilenameIOB; Log.Error(txt2log); } } /// /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere... /// /// protected void lgInfo(string txt2log) { Log.Factory.Configuration.Variables["codIOB"] = General.FilenameIOB; Log.Info(txt2log); } /// /// Effettua logging TRACE corretto impostanto anche la variabile IOB prima di scrivere... /// /// protected void lgTrace(string txt2log) { Log.Factory.Configuration.Variables["codIOB"] = General.FilenameIOB; Log.Trace(txt2log); } #endregion #region Area Private /// /// Generatore random x gestione non deterministica /// private Random rand = new Random(); #endregion Area Private } }