Files
cms_thermo_active/Thermo.Active.Core/ThreadsFunctions.cs
T
Samuele Locatelli 44123da2c2 fix tutte letture
2020-10-24 14:24:11 +02:00

1457 lines
51 KiB
C#

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;
public static class ThreadsFunctions
{
public static int axisRtCounter = 0;
public static int recipeRtCounter = 0;
public static int modulesRtCounter = 0;
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;
/// <summary>
/// restituisce il periodo di campionamento SE configurato, altrimenti 1000 ms
/// </summary>
/// <param name="threadName"></param>
/// <returns></returns>
private static int samplMsec(string threadName)
{
int answ = 500;
if (ThreadSamplingConfig.ContainsKey(threadName))
{
answ = ThreadSamplingConfig[threadName];
}
return answ;
}
#region Functions
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();
}
}
/// <summary>
/// Manage status/command words for actions
/// </summary>
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();
}
}
/// <summary>
/// Manage action for conf request
/// </summary>
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();
}
}
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 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 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<DTORuntimeFunctionalityModel> 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<DTOExpiredMaintenanceModel> 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 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<DTOUserSoftKeyModel> 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();
}
}
/// <summary>
/// Lettura valori ASSI (tutti i disponibili)
/// </summary>
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<int, DTOAxisInfoModel> 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();
}
}
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<ScadaSchemaModel> scadaToRead = ProductionScadaSchema.Concat(SubscribedScada).ToList();
// Get new data from PLC
libraryError = ncAdapter.ReadScadasData(scadaToRead, out List<DTOScadaModel> 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 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<string, DTOThermoProd> 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 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 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 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 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<string, DTORecipeParam> currRecipe);
if (libraryError.IsError())
ManageLibraryError(libraryError);
MessageServices.Current.Publish(SEND_THERMO_RECIPE_FULL, null, currRecipe);
// ora gestisco la overview!
libraryError = ncAdapter.GetRecipeOverview(out Dictionary<RecipeSection, RecipeCatStatus> 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 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())
{
// every 10 reads all data...
useCache = (readCount != 0);
// Get new data from PLC
libraryError = ncAdapter.ReadWarmers(useCache, out Dictionary<int, DTOWarmers> currWarmers);
if (libraryError.IsError())
ManageLibraryError(libraryError);
// pubblico
MessageServices.Current.Publish(SEND_THERMO_WARMERS_DATA, null, currWarmers);
readCount++;
// ciclo resettato ogni 10
readCount = readCount % 10;
}
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 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<string, double> 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();
}
}
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<int, DTOModulesBlock> 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 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<DTOM156InputModel> 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 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<M154DataModel> 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<string> 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 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<DTOLanguageModel> availableLanguages = LanguageController.GetLanguageListFromDirectory();
if (availableLanguages == null)
return;
ICollection<CultureInfo> cultureInfos = new List<CultureInfo>();
// 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<string, string> defAlarmsNamesEn = null;
Dictionary<string, string> defAlarmsNamesIt = null;
foreach (DTOLanguageModel lang in availableLanguages)
{
Dictionary<string, string> 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();
}
}
#endregion Functions
#region SupportFunctions
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;
}
}
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 AbortNcConnection()
{
if (ConnThread != null && ConnThread.IsAlive)
ConnThread.Abort();
}
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;
}
}
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 x {Counter[value.Key]}";
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;
}
}
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;
}
public 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;
}
private 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
}