using CMS_CORE_Library.Models; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using TeamDev.SDK.MVVM; using Thermo.Active.Core; using Thermo.Active.Database.Controllers; using Thermo.Active.Model.DTOModels; using Thermo.Active.Model.DTOModels.AlarmModels; using Thermo.Active.Model.DTOModels.Scada; using Thermo.Active.Model.DTOModels.ThAxes; using Thermo.Active.Model.DTOModels.ThModules; using Thermo.Active.Model.DTOModels.ThProd; using Thermo.Active.Model.DTOModels.ThRecipe; using Thermo.Active.Model.DTOModels.ThWarmers; using Thermo.Active.NC; using Thermo.Active.Utils; using static CMS_CORE_Library.Models.DataStructures; using static Thermo.Active.Config.ServerConfig; using static Thermo.Active.Model.Constants; using static Thermo.Active.Utils.ExceptionManager; using System.Windows; using System.Drawing; using System.Configuration; using Thermo.Active.Model.DTOModels.ThIO; using Thermo.Active.Thermocamera; public static class ThreadsFunctions { #region Private Fields private static Thread ConnThread; private static ConcurrentDictionary Counter = new ConcurrentDictionary(); private static ConcurrentDictionary Timers = new ConcurrentDictionary(); #endregion Private Fields #region Public Fields public static int axisRtCounter = 0; public static int modulesRtCounter = 0; public static int recipeRtCounter = 0; public static bool reconnectionIsRunning = false; #endregion Public Fields #region Internal Properties /// /// Swap x/y requesto from FLIR camera /// internal static bool cacheWarmers { get { bool answ = false; bool.TryParse(ConfigurationManager.AppSettings["cacheWarmers"], out answ); return answ; } } #endregion Internal Properties #region Private Methods private static int CalcSleepTime(int maxSleep, int execTime) { int sleep = 0; // Check if the execution time is greater than the half of the max sleep time if (maxSleep - execTime < maxSleep / 2) { sleep = maxSleep; } else { sleep = maxSleep - execTime; } return sleep; } private static bool ClientIsRunning() { Process[] p = Process.GetProcessesByName(CLIENT_EXE_NAME_NOEXT); foreach (Process pr in p) { if (pr.MainWindowHandle != IntPtr.Zero) { ShowWindow(pr.MainWindowHandle, 9); SetForegroundWindow(pr.MainWindowHandle); return true; } } return false; } private static void clientProcess() { string CMSClientPath = ""; // Check if the system is 64/32 bit if (Environment.Is64BitOperatingSystem && File.Exists(CLIENT_PATH_64)) CMSClientPath = CLIENT_PATH_64; else if (File.Exists(CLIENT_PATH_86)) CMSClientPath = CLIENT_PATH_86; if (!String.IsNullOrEmpty(CMSClientPath)) { Process pr = Process.Start(CMSClientPath, null); if (ServerStartupConfig.AutoOpenCmsClient) { pr.WaitForExit(); MessageServices.Current.Publish(SEND_STOP_SERVER); } } } private static Dictionary GetPlcAlarmsTranslations(string language) { using (NcAdapter ncAdapter = new NcAdapter()) { Dictionary returnValue = new Dictionary(); Dictionary messages = new Dictionary(); // Read data from CN ncAdapter.numericalControl.NC_GetTranslatedPlcMessages(language, ref messages); // Avoid checking error because in the worst case "messages" is empty // Id start from 1 for (int i = 1; i <= 1024; i++) { // Get configurated alarms var tmpAlarmConfig = InitialAlarmsConfig.Where(x => x.PlcId == i).FirstOrDefault(); // Default string string message = string.Format(NOT_CONFIGURATED_ALARM_MESSAGE, i); // If is configurated if (tmpAlarmConfig != null) { // Find translated string message = messages.Where(x => x.Key == tmpAlarmConfig.AlarmId).FirstOrDefault().Value; if (message == null) message = string.Format(NOT_FOUND_ALARM_MESSAGE, i); } // Add to dictionary returnValue.Add(i.ToString("D6") + "|900", message); } return returnValue; } } /// /// restituisce il periodo di campionamento SE configurato, altrimenti 1000 ms /// /// /// private static int samplMsec(string threadName) { int answ = 500; if (ThreadSamplingConfig.ContainsKey(threadName)) { answ = ThreadSamplingConfig[threadName]; } return answ; } [DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); private static void StatReset() { foreach (var value in Counter) { Timers[value.Key] = 0; Counter[value.Key] = 0; } } private static void TryNcConnection() { // Stop all the NC threads ThreadsHandler.Stop(); StatReset(); NcAdapter ncAdapter = new NcAdapter(); CmsError libraryError = NO_ERROR; // Run loop until NC is connected while (!ncAdapter.numericalControl.NC_IsConnected()) { // Try reconnection libraryError = ncAdapter.Connect(); if (libraryError.errorCode == CMS_ERROR_CODES.SIEMENS_ENVIRONMENT_NOT_FOUND || libraryError.errorCode == CMS_ERROR_CODES.SIEMENS_HMI_NOT_RUNNING || libraryError.errorCode == CMS_ERROR_CODES.OSAI_TT_FOLDER_NOT_FOUND) ManageLibraryError(libraryError); else if (libraryError.errorCode != CMS_ERROR_CODES.OK) { ncAdapter.Dispose(); } // Send status to UI MessageServices.Current.Publish(SEND_NC_STATUS_UI, null, ncAdapter.numericalControl.NC_IsConnected()); // Send status to signalr MessageServices.Current.Publish(SEND_NC_STATUS, null, ncAdapter.numericalControl.NC_IsConnected()); Thread.Sleep(1000); } if (!libraryError.IsError()) { if (ServerStartupConfig.AutoOpenCmsClient) StartCMSClient(); // Start/Restart NC threads ThreadsHandler.StartWorkers(); reconnectionIsRunning = false; } } #endregion Private Methods #region Internal Methods internal static void StatThread() { int samplePeriod = samplMsec("stats") > 0 ? samplMsec("stats") : 1000; while (true) { long totTime = 0; foreach (var value in Counter) { if (ThreadsHandler.RunningThreadStatus.ContainsKey(value.Key) && Counter[value.Key] != 0) { totTime += Timers[value.Key]; ThreadsHandler.RunningThreadStatus[value.Key] = $"{((double)Timers[value.Key] / samplePeriod):P1} | {(Timers[value.Key] / Counter[value.Key])} ms x {Counter[value.Key]}"; Timers[value.Key] = 0; Counter[value.Key] = 0; } } // aggiungo totale string grandTotal = $"{((double)totTime / samplePeriod):P1} | {totTime} ms"; if (ThreadsHandler.RunningThreadStatus.ContainsKey(" TOTAL")) { ThreadsHandler.RunningThreadStatus[" TOTAL"] = grandTotal; } else { ThreadsHandler.RunningThreadStatus.Add(" TOTAL", grandTotal); } MessageServices.Current.Publish(SEND_THREADS_STATUS, null, ThreadsHandler.RunningThreadStatus); Thread.Sleep(samplePeriod); } } internal static void UpdateStat(string functionName, long timer) { if (!Timers.ContainsKey(functionName)) Timers.TryAdd(functionName, timer); else Timers[functionName] += timer; if (!Counter.ContainsKey(functionName)) Counter.TryAdd(functionName, 1); else Counter[functionName]++; } #endregion Internal Methods #region Public Methods public static void AbortNcConnection() { if (ConnThread != null && ConnThread.IsAlive) ConnThread.Abort(); } /// /// Manage action for conf request /// public static void ManageConfRequest() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { // Manage status command libraryError = ncAdapter.ManageConfRequest(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("confReq"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException ex) { ncAdapter.Dispose(); } } /// /// Manage Requesto from PLC for FLir Image --> temp readout /// 1) check if pending request /// 2) give ack /// 3) request image to ext sw /// 4) request temp sampling from ext sw /// /// public static void ManageFlirCamera() { NcAdapter ncAdapter = new NcAdapter(); ThermoCamComunicator TCCom = new ThermoCamComunicator(true); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { bool flirImageReq = false; sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { // check if there is a photo request pending libraryError = ncAdapter.checkFlirImageRequest(out flirImageReq); if (libraryError.IsError()) ManageLibraryError(libraryError); if (flirImageReq) { bool done = false; // if requested --> give ack! ncAdapter.ManageFlirStrobe(); // requesto photo from library NcAdapter.lastThermoImage = TCCom.takePicture(); done = !string.IsNullOrEmpty(NcAdapter.lastThermoImage); if (done) { // init List measuredpoints = new List(); Dictionary actualTemp = new Dictionary(); Dictionary chPoints = new Dictionary(); // recupero punti centrali resistenze ncAdapter.GetWarmersChannelCenterPoints(out chPoints); // richiesta temperature per i punti done = TCCom.readMultiTemperatures("", chPoints, out measuredpoints); // converto in actualTemp foreach (var item in measuredpoints) { actualTemp.Add(item.Id, item.Temperature); } // salvo dati temp sul PLC ncAdapter.WriteRecipeWarmChTCamTempAct(actualTemp); // give PLC strobe for uploaded Actual TEMP from image ncAdapter.SendTCamImageReadyStrb(); } } } else RestoreConnection(); sw.Stop(); // Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("FlirCamera"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } finally { // chiudo thermocam TCCom.Dispose(); } } public static void ManageLibraryError(CmsError libraryError) { switch (libraryError.errorCode) { case CMS_ERROR_CODES.NC_PROD_ERROR: ManageError(ERROR_LEVEL.WARNING, libraryError.localizationKey); break; case CMS_ERROR_CODES.NOT_CONNECTED: RestoreConnection(); // If not connected try reconnection break; case CMS_ERROR_CODES.SIEMENS_ENVIRONMENT_NOT_FOUND: case CMS_ERROR_CODES.OSAI_TT_FOLDER_NOT_FOUND: case CMS_ERROR_CODES.OPTION_NOT_CONSISTENT: ManageError(ERROR_LEVEL.FATAL, libraryError.localizationKey); break; case CMS_ERROR_CODES.SIEMENS_HMI_NOT_RUNNING: ManageError(ERROR_LEVEL.FATAL, "SIEMENS HMI NOT RUNNING"); break; case CMS_ERROR_CODES.SELECTED_PROCESS: ManageError(ERROR_LEVEL.WARNING, libraryError.localizationKey); break; case CMS_ERROR_CODES.INTERNAL_ERROR: ManageException(ERROR_LEVEL.FATAL, libraryError.exception); break; } } /// /// Manage status/command words for actions /// public static void ManageStatusCommand() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { // Manage status command libraryError = ncAdapter.ManageStatusCommand(); } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("statusCommand"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException ex) { ncAdapter.Dispose(); } } public static void ManageWatchdog() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); int errorCounter = 0; try { CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { // Manage watchdog libraryError = ncAdapter.ManageWatchdog(); if (libraryError == PLC_NOT_RUNNING_ERROR) { if (errorCounter < MAX_NUM_OF_WATCHDOG_ERROR) errorCounter++; } else if (libraryError == NO_ERROR) errorCounter = 0; } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("watchdog"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException ex) { ncAdapter.Dispose(); } } public static void ReadAlarms() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { // Get Alarms from NC libraryError = ncAdapter.GetNcAlarms(out DTOAlarmsModel alarms); if (libraryError.errorCode != 0) { ManageLibraryError(libraryError); } else // Send through signalR MessageServices.Current.Publish(SEND_ALARMS, null, alarms); } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("alarms"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadAreaData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { // Get new data from PLC... info x area lastra... la % di X / Y libraryError = ncAdapter.GetWarmMaterialArea(out Dictionary currAreaPerc); if (libraryError.IsError()) ManageLibraryError(libraryError); // pubblico MessageServices.Current.Publish(SEND_THERMO_AREA_DATA, null, currAreaPerc); } else RestoreConnection(); sw.Stop(); // Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("area"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } /// /// Lettura valori ASSI (tutti i disponibili) /// public static void ReadAxisInfoData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { // ogni n counter leggo anche dati NON RT axisRtCounter--; bool onlyRt = axisRtCounter > 0; //check reset... axisRtCounter = axisRtCounter < 0 ? 4 : axisRtCounter; sw.Restart(); if (ncAdapter.numericalControl.NC_IsConnected()) { // Get Data from config and PLC libraryError = ncAdapter.ReadAxisData(onlyRt, out Dictionary axisData); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); else // Send through signalR MessageServices.Current.Publish(SEND_AXIS_INFO, null, axisData); } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("axis"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } /// /// Lettura valorichannelsIO /// public static void ReadChannelsIoData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); if (ncAdapter.numericalControl.NC_IsConnected()) { // Get Data from config and PLC libraryError = ncAdapter.ReadValIO(out DTOChannelsIOVal currChannelsIoVal); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); else // Send through signalR MessageServices.Current.Publish(SEND_CHANNELS_IO_DATA, null, currChannelsIoVal); } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // verifico se periodo rapido o veloce... int timerAct = RedisController.FastIoSample ? samplMsec("channelsIoFast") : samplMsec("channelsIoSlow"); // Wait Thread.Sleep(CalcSleepTime(timerAct, (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadEnabledFunctionality() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); if (ncAdapter.numericalControl.NC_IsConnected()) { // Get Data from NC libraryError = ncAdapter.GetFunctionsMappedWithNC(out List functionsAccessList); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); else // Send through signalR MessageServices.Current.Publish(SEND_FUNCTIONALITY_DATA, null, functionsAccessList); } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("functionEnab"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadExpiredMaintenances() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); if (ncAdapter.numericalControl.NC_IsConnected()) { // Get Data from database and PLC libraryError = ncAdapter.GetExpiredMaintenances(out List expiredMaintenances); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); else // Send through signalR MessageServices.Current.Publish(SEND_EXPIRED_MAINTENANCES_DATA, null, expiredMaintenances); // 2020.06.18 commentata da indicazione di Lucio Maranta (NON dovrebbe servire ora) #if false //Manage Candies libraryError = ncAdapter.ManageCandies(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); #endif } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("expMan"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } catch (Exception ex) { } } public static void ReadGaugeData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { // Get new data from PLC libraryError = ncAdapter.ReadGaugeData(out Dictionary currentLiveProd); if (libraryError.IsError()) ManageLibraryError(libraryError); MessageServices.Current.Publish(SEND_THERMO_GAUGE_DATA, null, currentLiveProd); } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("gauges"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadM154Data() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { libraryError = ncAdapter.GetM154Data(out List data, out bool MTCStatus); if (libraryError.IsError()) ManageLibraryError(libraryError); string ApplicationPath = ServerStartupConfig.MTCFolderPath + "\\" + ServerStartupConfig.MTCApplicationName + ".exe"; if (ServerStartupConfig.MTCFolderPath != "") { // Check if process exists Process[] processes = Process.GetProcessesByName(ServerStartupConfig.MTCApplicationName); if (!MTCStatus) { // Kill if is running if (processes.Count() > 0) processes[0].Kill(); } else { // if is already running ignore if (processes.Count() == 0) if (File.Exists(ApplicationPath)) { ProcessStartInfo PSI = new ProcessStartInfo(ApplicationPath); var directory = new FileInfo(ApplicationPath).Directory; if (directory != null) { PSI.WorkingDirectory = directory.FullName; Process.Start(PSI); } } } } foreach (M154DataModel m154 in data) { //if (CmsConnectConfig.Enabled) if (ServerStartupConfig.CmsConnectReady) { if (m154.Parameters.Count() >= 2 && m154.Parameters[0] == "SOUR") { // Convert tag string in Pascal Case and add to result string switch (m154.Parameters[1].ToLower()) { case "currprog": if (m154.Parameters.Count() < 3) return; RedisController.WriteProductionName(m154.Process, m154.Parameters[2]); break; case "repstarget": if (m154.Parameters.Count() < 3) return; RedisController.WriteProductionRepsTarget(m154.Process, m154.Parameters[2]); break; case "repsdone": if (m154.Parameters.Count() < 3) return; RedisController.WriteProductionRepsDone(m154.Process, m154.Parameters[2]); break; default: string notif = m154.Parameters[1]; if (m154.Parameters.Count() > 2) notif += m154.Parameters[2]; RedisController.WriteProductionNotification(m154.Process, notif); break; } } // Write ack libraryError = ncAdapter.WriteM154Ack((int)m154.Process); if (libraryError.IsError()) ManageLibraryError(libraryError); } else //MTC { string stringVal = "Path_0" + m154.Process + "_"; string val = ""; // Check if command is MTC if (m154.Parameters[0] == "MTC") { // Convert tag string in Pascal Case and add to result string switch (m154.Parameters[1].ToLower()) { case "currprog": stringVal += "CurrProg"; break; case "partid": stringVal += "PartId"; break; default: stringVal += m154.Parameters[1]; break; } // Set value if (m154.Parameters.Count() > 2) val = m154.Parameters[2]; // Create MTC Directory if not exist if (!Directory.Exists(ServerStartupConfig.MTCFolderPath)) Directory.CreateDirectory(ServerStartupConfig.MTCFolderPath); string outputFileName = ServerStartupConfig.MTCFolderPath + "\\DATA\\CmsGeneralStatus.mtc"; // Create file if not exits if (!File.Exists(outputFileName)) using (var f = File.Create(outputFileName)) { }; // Read file List fileLines = File.ReadAllLines(outputFileName).ToList(); string[] parametersInLine; bool found = false; for (int i = 0; i < fileLines.Count() && !found; i++) { // Get tag & value from row parametersInLine = fileLines[i].Split('|'); if (parametersInLine[0] == stringVal) { found = true; fileLines[i] = stringVal + "|" + val; } } // If tag doesn't exists, append new line if (!found) fileLines.Add(stringVal + "|" + val); // Write file File.WriteAllLines(outputFileName, fileLines.ToArray()); // Write ack libraryError = ncAdapter.WriteM154Ack((int)m154.Process); if (libraryError.IsError()) ManageLibraryError(libraryError); } } } } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("m154"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadMComandsData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); if (ncAdapter.numericalControl.NC_IsConnected()) { // solo x S7Net... if (NcConfig.NcVendor == NC_VENDOR.S7NET) { libraryError = ncAdapter.GetM156Data(out List m156Data); if (libraryError.IsError()) ManageLibraryError(libraryError); else MessageServices.Current.Publish(SEND_M156_DATA, null, m156Data); } } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("mCommands"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadModulesData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { // Get new data from PLC libraryError = ncAdapter.ReadModulesBlock(out Dictionary currModules); if (libraryError.IsError()) ManageLibraryError(libraryError); MessageServices.Current.Publish(SEND_THERMO_MODULE_DATA, null, currModules); } else RestoreConnection(); sw.Stop(); // Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("modules"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadPowerOnData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { // Get Data from NC libraryError = ncAdapter.GetPowerOnData(out DTOPowerOnDataModel powerOnData); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); else // Send through signalR MessageServices.Current.Publish(SEND_POWER_ON_DATA, null, powerOnData); } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("powerOn"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadProcessesPPStatus() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); if (ncAdapter.numericalControl.NC_IsConnected()) { // Get Data from NC libraryError = ncAdapter.GetProcessesData(out DTOProcessesDataModel processesPPData); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); else { // Send processes through signalR MessageServices.Current.Publish(SEND_PROCESSES_DATA, null, processesPPData); } } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(200, (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadProdCycleData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { // Get new data from PLC libraryError = ncAdapter.ReadProdCycleData(out ThermoModels.ProdCycleModel prodCycleData); if (libraryError.IsError()) ManageLibraryError(libraryError); MessageServices.Current.Publish(SEND_THERMO_PROD_CYCLE_DATA, null, prodCycleData); } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("prodCycle"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadProdInfoData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { // Get new data from PLC (and log if changed...) libraryError = ncAdapter.ReadProdInfoData(out DTOProdInfo prodInfoData); if (libraryError.IsError()) ManageLibraryError(libraryError); MessageServices.Current.Publish(SEND_THERMO_PROD_INFO_DATA, null, prodInfoData); } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("prodInfo"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadProdPanelData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { // Get new data from PLC (and log if changed...) libraryError = ncAdapter.ReadProdPanel(out DTOThermoPanelProd currentProdPanel); if (libraryError.IsError()) ManageLibraryError(libraryError); MessageServices.Current.Publish(SEND_THERMO_PROD_PANEL_DATA, null, currentProdPanel); } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait 500 ms Thread.Sleep(CalcSleepTime(samplMsec("prodPanel"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadRecipeData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { // ogni n counter leggo anche dati NON RT recipeRtCounter--; bool onlyRt = recipeRtCounter > 0; //check reset... recipeRtCounter = recipeRtCounter < 0 ? 4 : recipeRtCounter; sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { // Get new data from PLC libraryError = ncAdapter.ReadRecipeData(onlyRt, false, out Dictionary currRecipe); if (libraryError.IsError()) ManageLibraryError(libraryError); MessageServices.Current.Publish(SEND_THERMO_RECIPE_FULL, null, currRecipe); // ora gestisco la overview! libraryError = ncAdapter.GetRecipeOverview(out Dictionary currOverview); if (libraryError.IsError()) ManageLibraryError(libraryError); MessageServices.Current.Publish(SEND_THERMO_RECIPE_OVERWIEW, null, currOverview); // ora gestisco la lettura della overview di "modificata DTORecipeStatus message = new DTORecipeStatus() { recipeName = NcAdapter.RecipeLiveData.RecipeName, hasChanged = NcAdapter.RecipeLiveData.hasChanged }; MessageServices.Current.Publish(SEND_THERMO_RECIPE_CHANGED, null, message); // verifico se dal PLC è segnalato che i setpointHMI sono invalidati, nel qual caso INVIO bool setpointHmiInvalidated = false; libraryError = ncAdapter.checkSetpointInvalidated(out setpointHmiInvalidated); if (setpointHmiInvalidated) { // ora gestisco l'ack della richiesta libraryError = ncAdapter.doAckSetpointInvalidated(); } // pubblico booleana dei setpointHMI invalidati MessageServices.Current.Publish(SEND_THERMO_RECIPE_SETPOINTHMI_CHANGED, null, setpointHmiInvalidated); } else RestoreConnection(); sw.Stop(); // Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("recipe"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadScadaData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { List scadaToRead = ProductionScadaSchema.Concat(SubscribedScada).ToList(); // Get new data from PLC libraryError = ncAdapter.ReadScadasData(scadaToRead, out List scadas); if (libraryError.IsError()) ManageLibraryError(libraryError); MessageServices.Current.Publish(SEND_SCADA_DATA, null, scadas); } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("scada"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadUserSoftKeysData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); while (true) { sw.Restart(); if (ncAdapter.numericalControl.NC_IsConnected()) { // Get softkey data from config and PLC libraryError = ncAdapter.GetUserSoftKeys(out List softKeys); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); else // Send through signalR MessageServices.Current.Publish(SEND_USER_SOFTKEYS_DATA, null, softKeys); } else RestoreConnection(); sw.Stop(); //Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("userSK"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void ReadWarmersData() { NcAdapter ncAdapter = new NcAdapter(); Stopwatch sw = new Stopwatch(); try { // Try connection CmsError libraryError = ncAdapter.Connect(); if (libraryError.errorCode != 0) ManageLibraryError(libraryError); int readCount = 0; bool useCache = false; while (true) { sw.Restart(); // Check if client is connected if (ncAdapter.numericalControl.NC_IsConnected()) { if (cacheWarmers) { // every 10 reads all data... useCache = (readCount != 0); readCount++; // ciclo resettato ogni 20 readCount = readCount % 20; } // Get new data from PLC libraryError = ncAdapter.ReadWarmers(useCache, out Dictionary currWarmers); if (libraryError.IsError()) ManageLibraryError(libraryError); // pubblico MessageServices.Current.Publish(SEND_THERMO_WARMERS_DATA, null, currWarmers); } else RestoreConnection(); sw.Stop(); // Update thread timer UpdateStat(MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds); // Wait Thread.Sleep(CalcSleepTime(samplMsec("warmers"), (int)sw.ElapsedMilliseconds)); } } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void RestoreConnection() { if (reconnectionIsRunning == false) { // Set thread as running state reconnectionIsRunning = true; // Start reconnection thread ConnThread = new Thread(() => TryNcConnection() ); ConnThread.Start(); } } public static void SetupCmsConnect() { NcAdapter ncAdapter = new NcAdapter(); try { //Write all the datamodel if (!RedisController.WriteDatamodel(CMSConnectDataModel)) ManageError(ERROR_LEVEL.FATAL, CMS_CONNECT_SETUP_ALARM_MESSAGE); //Write all the default entries if (!RedisController.WriteDefaultEntry(CMSConnectEntry)) ManageError(ERROR_LEVEL.FATAL, CMS_CONNECT_SETUP_ALARM_MESSAGE); //Write the Active Version if (!RedisController.WriteActiveVersion(SupportFunctions.GetSoftwareVersionAndBuildDate())) ManageError(ERROR_LEVEL.FATAL, CMS_CONNECT_SETUP_ALARM_MESSAGE); //Write the Overrides if (!RedisController.WriteFakeOverrides(1)) ManageError(ERROR_LEVEL.FATAL, CMS_CONNECT_SETUP_ALARM_MESSAGE); List availableLanguages = LanguageController.GetLanguageListFromDirectory(); if (availableLanguages == null) return; ICollection cultureInfos = new List(); // Get nc available language CmsError libraryError = ncAdapter.numericalControl.NC_GetAvailableLanguages(ref cultureInfos); if (libraryError.IsError()) ManageLibraryError(libraryError); // Filter available language with availableLanguages = availableLanguages.Where(x => cultureInfos.Any(y => y.TwoLetterISOLanguageName == x.IsoId)).ToList(); // Fill redis DB int count = 1; Dictionary defAlarmsNamesEn = null; Dictionary defAlarmsNamesIt = null; foreach (DTOLanguageModel lang in availableLanguages) { Dictionary alarmsNames = GetPlcAlarmsTranslations(lang.IsoId); if (lang.IsoId.ToLower() == "en") { defAlarmsNamesEn = alarmsNames; if (!RedisController.WriteAlarmsConfigEn(alarmsNames)) ManageError(ERROR_LEVEL.FATAL, CMS_CONNECT_SETUP_ALARM_MESSAGE); } else if (lang.IsoId.ToLower() == "it") { defAlarmsNamesIt = alarmsNames; if (!RedisController.WriteAlarmsConfigIt(alarmsNames)) ManageError(ERROR_LEVEL.FATAL, CMS_CONNECT_SETUP_ALARM_MESSAGE); } else if (!RedisController.WriteAlarmsConfigCurr(alarmsNames)) ManageError(ERROR_LEVEL.FATAL, CMS_CONNECT_SETUP_ALARM_MESSAGE); if (count == 3) break; else count++; } if (availableLanguages.Count < 3 && defAlarmsNamesEn != null) if (!RedisController.WriteAlarmsConfigCurr(defAlarmsNamesEn)) ManageError(ERROR_LEVEL.FATAL, CMS_CONNECT_SETUP_ALARM_MESSAGE); else if (availableLanguages.Count < 3 && defAlarmsNamesIt != null) if (!RedisController.WriteAlarmsConfigCurr(defAlarmsNamesIt)) ManageError(ERROR_LEVEL.FATAL, CMS_CONNECT_SETUP_ALARM_MESSAGE); } catch (ThreadAbortException) { ncAdapter.Dispose(); } } public static void StartCMSClient() { //Setup the Path Variable if (!ClientIsRunning()) { ThreadsHandler.StartClient = new Thread(() => clientProcess()); ThreadsHandler.StartClient.Start(); } } #endregion Public Methods }