using Newtonsoft.Json; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization; using NLog; using System.IO; using System; using static IOB_UT_NEXT.Config.EnumConf; using System.Collections.Generic; using System.Linq; using IOB_UT_NEXT.Config; using IOB_UT_NEXT.Config.Base; using IOB_UT_NEXT.Config.Special; 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) { //lgError($"Eccezione in LoadFromYaml{Environment.NewLine}{exc}"); } break; default: break; } if (newConfObj != null) { // ora copio in oggetto corrente... GenConf = newConfObj.GenConf; DeviceConf = newConfObj.DeviceConf; ProcInputConf = newConfObj.ProcInputConf; OptParConf = newConfObj.OptParConf; MapoMesConf = newConfObj.MapoMesConf; SpecialConf = newConfObj.SpecialConf; TCDataConf = newConfObj.TCDataConf; ActionConf = newConfObj.ActionConf; // sovrascrivo filename GenConf.ConfFileName = 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); // Dati generali (vendor, modello...) newConfObj.GenConf = new IobDto() { CodIOB = fIni.ReadString("IOB", "IOB_NAME", codIob), ConfFileName = Path.GetFileName(iniFilePath), Customer = fIni.ReadString("TAGS", "Customer", "EgalWare"), DisableExeTask = bool.Parse(fIni.ReadString("IOB", "DIS_EXE_TASK", "false")), DisableStateCh = bool.Parse(fIni.ReadString("IOB", "DIS_STATE_CH", "false")), EnableRedisQueue = bool.Parse(fIni.ReadString("IOB", "EnableRedisQueue", "false")), MinDeltaSec = fIni.ReadInteger("IOB", "MinDeltaSec", 6), ReleaseVers = $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Version}" }; // tipo adapter// verifico tipo adapter try { newConfObj.GenConf.IobType = (tipoAdapter)Enum.Parse(typeof(tipoAdapter), fIni.ReadString("IOB", "CNCTYPE", "ND")); } catch (Exception exc) { newConfObj.GenConf.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}"); } newConfObj.DeviceConf = new DeviceDto() { Vendor = fIni.ReadString("MACHINE", "VENDOR", "STEAMWARE"), Model = fIni.ReadString("MACHINE", "MODEL", "ND"), ConnectConf = new ConnectionDto() { pingMsTimeout = fIni.ReadInteger("IOB", "PING_MS_TIMEOUT", 500), IpAddr = fIni.ReadString("CNC", "IP", "::1"), Port = fIni.ReadString("CNC", "PORT", "0") } }; // parametri opzionali Memory 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 SignalLUT foreach (var item in memDict.Where(x => x.Key.StartsWith("BIT"))) { if (newConfObj.DeviceConf.SignalLUT.ContainsKey(item.Key)) { newConfObj.DeviceConf.SignalLUT[item.Key] = item.Value; } else { newConfObj.DeviceConf.SignalLUT.Add(item.Key, item.Value); } } // cerco dati specifici x popolare l'area Fanuc if (memDict.Where(x => x.Key.StartsWith("AREA") || x.Key.StartsWith("PAR")).Count() > 0) { // init fanuc... newConfObj.DeviceConf.FanucConf = new FanucDto(); // 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() { AddressStart = addrStart, AddressSize = addrSize }; newConfObj.DeviceConf.FanucConf.MemConf.Add(mId, memArea); } } } } } } // parametri opzionali Siemens if (!string.IsNullOrEmpty(fIni.ReadString("CNC", "CPUTYPE", ""))) { newConfObj.DeviceConf.SiemensConf = new SiemensDto(); newConfObj.DeviceConf.SiemensConf.CpuType = fIni.ReadString("CNC", "CPUTYPE", ""); newConfObj.DeviceConf.SiemensConf.Rack = (short)fIni.ReadInteger("CNC", "RACK", 0); newConfObj.DeviceConf.SiemensConf.Slot = (short)fIni.ReadInteger("CNC", "SLOT", 0); } // BLINK newConfObj.ProcInputConf.BlinkMaxCounter = Convert.ToInt32(fIni.ReadString("BLINK", "MAX_COUNTER_BLINK", "1")); newConfObj.ProcInputConf.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(".", ",")); // Server string MpIp = fIni.ReadString("SERVER", "MPIP", "::1"); #if false string[] serverSection = fIni.ReadSection("SERVER"); // trasformo in array... Dictionary servDict = new Dictionary(); foreach (var item in serverSection) { var KVP = item.Split('='); servDict.Add(KVP[0], KVP[1]); } // processo array appena acquisito if (servDict.ContainsKey("MPIP")) { string MpIp = servDict["MPIP"]; } #endif if (!string.IsNullOrEmpty(MpIp)) { newConfObj.MapoMesConf.Transport = MpIp.StartsWith("https://") ? "https" : "http"; newConfObj.MapoMesConf.IpAddr = MpIp.Replace($"{newConfObj.MapoMesConf.Transport}://", ""); // tolgo http/https... } // Altro newConfObj.IobManConf.MinDeltaSec = fIni.ReadInteger("IOB", "MinDeltaSec", 6); // OptParConf Dictionary optParRead = new Dictionary(); string[] optParRows = fIni.ReadSection("OPTPAR"); if (optParRows.Length > 0) { try { string[] kvp; foreach (var item in optParRows) { kvp = item.Split('='); 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}"); } } // riordino alfabeticamente optParRead = optParRead.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); newConfObj.OptParConf = optParRead; newConfObj.SpecialConf = new SpecializedDto(); // verifico se ho conf json speciali: LUT decodifica PARAMETRI 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)) { newConfObj.SpecialConf.MemMap = new plcMemMapExt(); try { newConfObj.SpecialConf.MemMap = 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"); } } } catch (Exception exc) { newConfObj.lgError($"EXCEPTION in decodifica IobConfTree: {Environment.NewLine}{exc}"); } return newConfObj; } /// /// Info generali delative all'IOB impiegato /// public IobDto GenConf { get; set; } = new IobDto(); /// /// Info relative al device interconnesso /// public DeviceDto DeviceConf { get; set; } = new DeviceDto(); /// /// Parametri server Mapo MES /// public ServerMapoDto MapoMesConf { get; set; } = new ServerMapoDto(); /// /// Setup info verso IOB-MAN /// public IobManDto IobManConf { get; set; } = new IobManDto(); /// /// Setup processing dati in ingresso (es: blink segnali) /// public InputSignalDto ProcInputConf { get; set; } = new InputSignalDto(); /// /// Dati relativi ai parametri gestione tempo ciclo /// public TCDataDto TCDataConf { get; set; } = new TCDataDto(); /// /// Configurazione speciale/opzionale per tipo IOB /// public SpecializedDto SpecialConf { get; set; } /// /// Configurazione speciale comportamenti IOB (es setup) /// public ActionDto ActionConf { get; set; } /// /// Dizionario dei parametri opzionali /// public Dictionary OptParConf { get; set; } = new Dictionary(); /// /// Dizionario delle chiavi opz da dizionario /// public Dictionary OptKVP { get; set; } = new Dictionary(); #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; } #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"] = GenConf.CodIOB; 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"] = GenConf.CodIOB; 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"] = GenConf.CodIOB; 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"] = GenConf.CodIOB; Log.Trace(txt2log); } #endregion } }