using CMS_CORE_Library.Models; using Step.NC; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Threading; using TeamDev.SDK.MVVM; using static CMS_CORE_Library.Models.DataStructures; using static Step.Config.ServerConfig; using static Step.Model.Constants; using static Step.Utils.ExceptionManager; namespace Step.Core { internal static class ThreadsSupportFunctions { public static bool reconnectionIsRunning = false; private static ConcurrentDictionary Timers = new ConcurrentDictionary(); private static ConcurrentDictionary Counter = new ConcurrentDictionary(); private static Thread ConnThread; #region SupportFunctions internal static void TryNcConnection() { // Stop all the NC threads ThreadsHandler.Stop(); StatReset(); NcAdapter ncAdapter = new NcAdapter(); CmsError cmsError = NO_ERROR; // Run loop until NC is connected while (!ncAdapter.numericalControl.NC_IsConnected()) { // Try reconnection cmsError = ncAdapter.Connect(); if (cmsError.errorCode == CMS_ERROR_CODES.SIEMENS_ENVIRONMENT_NOT_FOUND || cmsError.errorCode == CMS_ERROR_CODES.SIEMENS_HMI_NOT_RUNNING || cmsError.errorCode == CMS_ERROR_CODES.OSAI_TT_FOLDER_NOT_FOUND) ManageLibraryError(cmsError); else if (cmsError.errorCode != CMS_ERROR_CODES.OK) { ncAdapter.Dispose(); } if (cmsError.errorCode == CMS_ERROR_CODES.SIEMENS_TOOL_TABLE_ERROR) ManageLibraryError(cmsError); // Send status to UI MessageServices.Current.Publish(SEND_NC_STATUS, null, ncAdapter.numericalControl.NC_IsConnected()); Thread.Sleep(1000); } if (NcConfig.NcVendor == NC_VENDOR.FANUC || NcConfig.NcVendor == NC_VENDOR.OSAI) { using (NcToolTableAdapter toolTable = new NcToolTableAdapter()) { toolTable.Connect(); // After reconecction write option cmsError = toolTable.SetupNcToolManager(); if (cmsError.IsError()) ManageLibraryError(cmsError); // cmsError = toolTable.RestoreTableLock(); } } if (!cmsError.IsError()) { if (ServerStartupConfig.AutoOpenCmsClient) StartCMSClient(); // Start/Restart NC threads ThreadsHandler.StartWorkers(); reconnectionIsRunning = false; } } internal static void RestoreConnection() { if (reconnectionIsRunning == false) { // Set thread as running state reconnectionIsRunning = true; // Start reconnection thread ConnThread = new Thread(() => TryNcConnection() ); ConnThread.Start(); } } internal static void AbortNcConnection() { if (ConnThread != null && ConnThread.IsAlive) ConnThread.Abort(); } internal static void ManageLibraryError(CmsError cmsError) { switch (cmsError.errorCode) { case CMS_ERROR_CODES.NC_PROD_ERROR: ManageError(ERROR_LEVEL.WARNING, cmsError.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: case CMS_ERROR_CODES.SIEMENS_TOOL_TABLE_ERROR: ManageError(ERROR_LEVEL.FATAL, cmsError.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, cmsError.localizationKey); break; case CMS_ERROR_CODES.INTERNAL_ERROR: ManageException(ERROR_LEVEL.FATAL, cmsError.exception); break; } } 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]++; } internal static void StatThread() { while (true) { foreach (var value in Counter) { if (ThreadsHandler.RunningThreadStatus.ContainsKey(value.Key) && Counter[value.Key] != 0) { ThreadsHandler.RunningThreadStatus[value.Key] = (Timers[value.Key] / Counter[value.Key]) + " mS"; Timers[value.Key] = 0; Counter[value.Key] = 0; } } MessageServices.Current.Publish(SEND_THREADS_STATUS, null, ThreadsHandler.RunningThreadStatus); Thread.Sleep(2000); } } private static void StatReset() { foreach (var value in Counter) { Timers[value.Key] = 0; Counter[value.Key] = 0; } } internal 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; } internal static void StartCMSClient() { //Setup the Path Variable if (!ClientIsRunning()) { ThreadsHandler.StartClient = new Thread(() => clientProcess()); ThreadsHandler.StartClient.Start(); } } 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 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; } internal 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; } } [DllImport("user32.dll")] static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); #endregion SupportFunctions } }