285 lines
9.8 KiB
C#
285 lines
9.8 KiB
C#
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<string, long> Timers = new ConcurrentDictionary<string, long>();
|
|
private static ConcurrentDictionary<string, long> Counter = new ConcurrentDictionary<string, long>();
|
|
|
|
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<string, string> GetPlcAlarmsTranslations(string language)
|
|
{
|
|
using (NcAdapter ncAdapter = new NcAdapter())
|
|
{
|
|
Dictionary<string, string> returnValue = new Dictionary<string, string>();
|
|
|
|
Dictionary<int, string> messages = new Dictionary<int, string>();
|
|
// 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
|
|
}
|
|
}
|