diff --git a/Thermo.Active.CmsConnectGateway/CMSConnectConstants.cs b/Thermo.Active.CmsConnectGateway/CMSConnectConstants.cs index 256c36f5..ce9d6434 100644 --- a/Thermo.Active.CmsConnectGateway/CMSConnectConstants.cs +++ b/Thermo.Active.CmsConnectGateway/CMSConnectConstants.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Thermo.Active.Model.DTOModels.AlarmModels; +using YamlDotNet.Core.Tokens; namespace Thermo.Active.CmsConnectGateway { @@ -35,13 +37,24 @@ namespace Thermo.Active.CmsConnectGateway public const string YAML_CONFIG_FILE = "./example-mconnect.conf.yaml"; - public const string CONNECT_MACHINE_STAUTS_UNDEFINED = "UNDEFINED"; + public const string CONNECT_UNDEFINED = "UNDEFINED"; public const string CONNECT_MACHINE_STAUTS_EXE = "EXE"; public const string CONNECT_MACHINE_STAUTS_READY = "READY"; public const string CONNECT_MACHINE_STAUTS_SETUP = "SETUP"; public const string CONNECT_MACHINE_STAUTS_FAIL = "FAIL"; public const string CONNECT_MACHINE_STAUTS_POWEROFF = "POWER_OFF"; + public const string CONNECT_PROC_STAUTS_EXE = "EXE"; + public const string CONNECT_PROC_STAUTS_READY = "READY"; + public const string CONNECT_PROC_STAUTS_HOLD = "HOLD"; + public const string CONNECT_PROC_STAUTS_FHOLD = "FEED_HOLD"; + public const string CONNECT_PROC_STAUTS_OSTOP = "OPTIONAL_STOP"; + public const string CONNECT_PROC_STAUTS_PSTOPPED = "PROGRAM_STOPPED"; + + public const string CONNECT_PROC_MODE_AUTO = "AUTOMATIC"; + public const string CONNECT_PROC_MODE_EDIT = "EDIT"; + public const string CONNECT_PROC_MODE_JOG = "MANUAL_JOG"; + public static string ConvertThermoToConnectStatus(int status) { switch (status) @@ -51,10 +64,37 @@ namespace Thermo.Active.CmsConnectGateway case 2: return CONNECT_MACHINE_STAUTS_EXE; case 4: return CONNECT_MACHINE_STAUTS_SETUP; case 8: return CONNECT_MACHINE_STAUTS_FAIL; - case 16: return CONNECT_MACHINE_STAUTS_FAIL; - default: return CONNECT_MACHINE_STAUTS_UNDEFINED; + case 16: return CONNECT_MACHINE_STAUTS_READY; + case 128: return CONNECT_MACHINE_STAUTS_FAIL; + default: return CONNECT_UNDEFINED; } } + + public static string ConvertThermoToConnectProcessStatus(int status) + { + switch (status) + { + case 0: return CONNECT_PROC_STAUTS_READY; + case 1: return CONNECT_PROC_STAUTS_READY; + case 2: return CONNECT_PROC_STAUTS_EXE; + case 4: return CONNECT_PROC_STAUTS_FHOLD; + case 8: return CONNECT_PROC_STAUTS_OSTOP; + case 16: return CONNECT_PROC_STAUTS_HOLD; + case 128: return CONNECT_PROC_STAUTS_HOLD; + default: return CONNECT_UNDEFINED; + } + } + public static string ConvertThermoToConnectProcessMode(int status) + { + switch (status) + { + case 1: return CONNECT_PROC_MODE_EDIT; + case 2: return CONNECT_PROC_MODE_AUTO; + case 4: return CONNECT_PROC_MODE_JOG; + default: return CONNECT_UNDEFINED; + } + } + public static bool ConvertThermoToConnectPower(int status) { switch (status) @@ -63,9 +103,20 @@ namespace Thermo.Active.CmsConnectGateway default: return true; } } - - - + public static bool ConvertThermoToConnectMachineAlarm(DTOAlarmsModel alarms) + { + return alarms.PlcAlarms.Count > 0; + } + + public static string ConvertThermoToConnectAlarms(DTOAlarmsModel alarms) + { + List alms = new List(); + foreach (DTOPlcAlarmModel alarm in alarms.PlcAlarms) { + int severity = alarm.IsWarning ? 500 : 900; + alms.Add(alarm.Id + "|" + severity); + } + return string.Join(",", alms); + } } } diff --git a/Thermo.Active.CmsConnectGateway/Thermo.Active.CmsConnectGateway.csproj b/Thermo.Active.CmsConnectGateway/Thermo.Active.CmsConnectGateway.csproj index 572bcf5b..7aa36ef9 100644 --- a/Thermo.Active.CmsConnectGateway/Thermo.Active.CmsConnectGateway.csproj +++ b/Thermo.Active.CmsConnectGateway/Thermo.Active.CmsConnectGateway.csproj @@ -126,5 +126,15 @@ + + + {4abf8eef-2b23-483e-acdc-53214fe28681} + CMS_CORE_Library + + + {631375dd-06d3-49bb-8130-d9ddb34c429d} + Thermo.Active.Model + + \ No newline at end of file diff --git a/Thermo.Active.Config/Config/DataModel.xml b/Thermo.Active.Config/Config/DataModel.xml new file mode 100644 index 00000000..2db47901 --- /dev/null +++ b/Thermo.Active.Config/Config/DataModel.xml @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Thermo.Active.Config/ServerConfig.cs b/Thermo.Active.Config/ServerConfig.cs index d4517ec8..06cc5210 100644 --- a/Thermo.Active.Config/ServerConfig.cs +++ b/Thermo.Active.Config/ServerConfig.cs @@ -65,6 +65,7 @@ namespace Thermo.Active.Config public static List RiskChannelConfig; public static List RiskBoardConfig; public static List AxesConfig; + public static Dictionary CMSConnectEntry; } diff --git a/Thermo.Active.Config/ServerConfigController.cs b/Thermo.Active.Config/ServerConfigController.cs index 2c348c6d..87671519 100644 --- a/Thermo.Active.Config/ServerConfigController.cs +++ b/Thermo.Active.Config/ServerConfigController.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Xml; using System.Xml.Linq; @@ -43,6 +44,7 @@ namespace Thermo.Active.Config ReadMacros(); ReadScadaFile(); ReadM156(); + ReadDataModel(); } catch (XmlException ex) { @@ -86,6 +88,14 @@ namespace Thermo.Active.Config return xmlConfigFile; } + private static XDocument GetXmlHandler(string configFilePath, bool isFullPath = false) + { + // Open file reader + XDocument xmlConfigFile = XDocument.Load((!isFullPath ? BASE_PATH + "\\" : "") + configFilePath); + + return xmlConfigFile; + } + private static void validateScada(string configSchemaFilePath, string configFilePath) { // Create new instance @@ -281,7 +291,27 @@ namespace Thermo.Active.Config }) .ToList(); } - + private static void ReadDataModel() + { + XDocument xmlConfigFile = GetXmlHandler(CONNECT_DATAMODEL_CONFIG_PATH); + XElement el = xmlConfigFile.Descendants("Machine").First(); + CMSConnectEntry = new Dictionary(); + ElaborateDataModel(el,el.Name.LocalName, ref CMSConnectEntry); + } + + private static void ElaborateDataModel(XElement el, string Parent, ref Dictionary Paths) + { + List intEl = el.Elements().ToList(); + foreach (XElement elem in intEl) + { + if (elem.Name.LocalName == "Component") + ElaborateDataModel(elem, Parent + ":" + elem.Attribute("Name").Value, ref Paths); + else if(elem.Name.LocalName == "Property") + Paths.Add(Parent + ":" + elem.Attribute("SymbolicName").Value, elem.Attribute("Value").Value); + else + Paths.Add(Parent + ":" + elem.Attribute("SymbolicName").Value, "UNAVAILABLE"); + } + } public static string GetInputOperatoType(string tagName) { diff --git a/Thermo.Active.Config/Thermo.Active.Config.csproj b/Thermo.Active.Config/Thermo.Active.Config.csproj index dd4d411a..c906d194 100644 --- a/Thermo.Active.Config/Thermo.Active.Config.csproj +++ b/Thermo.Active.Config/Thermo.Active.Config.csproj @@ -51,6 +51,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Thermo.Active.Core/ThreadsFunctions.cs b/Thermo.Active.Core/ThreadsFunctions.cs index e1bf2687..77fc6604 100644 --- a/Thermo.Active.Core/ThreadsFunctions.cs +++ b/Thermo.Active.Core/ThreadsFunctions.cs @@ -1140,6 +1140,11 @@ public static class ThreadsFunctions NcAdapter ncAdapter = new NcAdapter(); try { + + //Write all the default Entry + if (!RedisController.WriteDefaultEntry(CMSConnectEntry)) + ManageError(ERROR_LEVEL.FATAL, CMS_CONNECT_SETUP_ALARM_MESSAGE); + List availableLanguages = LanguageController.GetLanguageListFromDirectory(); if (availableLanguages == null) return; diff --git a/Thermo.Active.Database/Controllers/RedisController.cs b/Thermo.Active.Database/Controllers/RedisController.cs index 7cec7e4a..73668e09 100644 --- a/Thermo.Active.Database/Controllers/RedisController.cs +++ b/Thermo.Active.Database/Controllers/RedisController.cs @@ -17,7 +17,11 @@ namespace Thermo.Active.Database.Controllers private const string machineMessagePath = "Machine:Messages"; private const string machineStatusPath = "Machine:Status"; private const string machinePowerPath = "Machine:Power"; + private const string machineAlarmPath = "Machine:Alarm"; private const string machineEmergencyPath = "Machine:Emergency"; + private const string alarmsPath = "Machine:Plc:Condition"; + private const string processStatusPath = "Machine:Cnc:CncProcesses:%NN%:Status"; + private const string processModePath = "Machine:Cnc:CncProcesses:%NN%:Mode"; public static void WriteProductionNotification(uint ProductionProcess, string Notification) { @@ -55,6 +59,17 @@ namespace Thermo.Active.Database.Controllers return redUtil.man.redSaveHashDict(redisHash, alarms); } + + public static bool WriteDefaultEntry(Dictionary entries) + { + foreach (KeyValuePair entry in entries) + { + if (!redUtil.man.setRSV(redUtil.man.redHash(entry.Key), entry.Value)) + return false; + } + return true; + } + public static bool WriteAlarmsConfigIt(Dictionary alarms) { string redisHash = redUtil.man.redHash(redisAlmIt); @@ -77,6 +92,18 @@ namespace Thermo.Active.Database.Controllers string redisHash = redUtil.man.redHash(machineStatusPath); return redUtil.man.setRSV(redisHash, status.ToString()); } + + public static bool WriteCurrentProcessStatus(uint ProductionProcess, string status) + { + string redisHash = redUtil.man.redHash(processStatusPath).Replace("%NN%", ProductionProcess.ToString("00")); + return redUtil.man.setRSV(redisHash, status.ToString()); + } + + public static bool WriteCurrentProcessMode(uint ProductionProcess, string status) + { + string redisHash = redUtil.man.redHash(processModePath).Replace("%NN%", ProductionProcess.ToString("00")); + return redUtil.man.setRSV(redisHash, status.ToString()); + } public static bool WriteCurrentMachinePowerPath(bool status) { @@ -86,6 +113,15 @@ namespace Thermo.Active.Database.Controllers else return redUtil.man.setRSV(redisHash, "false"); } + + public static bool WriteCurrentMachineAlarmPath(bool status) + { + string redisHash = redUtil.man.redHash(machineAlarmPath); + if (status) + return redUtil.man.setRSV(redisHash, "true"); + else + return redUtil.man.setRSV(redisHash, "false"); + } public static bool WriteCurrentMachineEmergencyPath(bool status) { @@ -95,7 +131,12 @@ namespace Thermo.Active.Database.Controllers else return redUtil.man.setRSV(redisHash, "false"); } - + public static bool WriteCurrentAlarms(string alarms) + { + string redisHash = redUtil.man.redHash(alarmsPath); + return redUtil.man.setRSV(redisHash, alarms); + } + } } diff --git a/Thermo.Active.Model/Constants.cs b/Thermo.Active.Model/Constants.cs index c5ff0fd9..d986d893 100644 --- a/Thermo.Active.Model/Constants.cs +++ b/Thermo.Active.Model/Constants.cs @@ -268,6 +268,9 @@ namespace Thermo.Active.Model public const string M156_CONFIG_SCHEMA_PATH = RESOURCE_DIRECTORY + "inputOperatorConfigValidator.xsd"; public const string M156_CONFIG_PATH = CONFIG_DIRECTORY + "inputOperatorConfig.xml"; + public const string CONNECT_DATAMODEL_CONFIG_SCHEMA_PATH = RESOURCE_DIRECTORY + "dataModelConfigValidator.xsd"; + public const string CONNECT_DATAMODEL_CONFIG_PATH = CONFIG_DIRECTORY + "DataModel.xml"; + public const string MAINTENANCES_CONFIG_SCHEMA_PATH = RESOURCE_DIRECTORY + "maintenancesConfigValidator.xsd"; public const string CUSTOMER_CONTACTS_CONFIG_SCHEMA_PATH = RESOURCE_DIRECTORY + "customerContactConfigValidator.xsd"; public const string MAINTENANCES_CONFIG_PATH = CONFIG_DIRECTORY + "maintenancesConfig.xml"; diff --git a/Thermo.Active/Listeners/SignalR/SignalRListener.cs b/Thermo.Active/Listeners/SignalR/SignalRListener.cs index 5f3de79f..757bad54 100644 --- a/Thermo.Active/Listeners/SignalR/SignalRListener.cs +++ b/Thermo.Active/Listeners/SignalR/SignalRListener.cs @@ -35,6 +35,13 @@ namespace Thermo.Active.Listeners.SignalR LastAlarms = LastAlarms.IntersectModels(newAlarmsData as DTOAlarmsModel); // Send data to clients context.Clients.Group("ncData").alarms(LastAlarms); + + if (Config.ServerConfig.ServerStartupConfig.CmsConnectReady) + { + RedisController.WriteCurrentAlarms(CMSConnectConstants.ConvertThermoToConnectAlarms(newAlarmsData)); + + RedisController.WriteCurrentMachineAlarmPath(CMSConnectConstants.ConvertThermoToConnectMachineAlarm(newAlarmsData)); + } } } @@ -299,6 +306,11 @@ namespace Thermo.Active.Listeners.SignalR recipeHasChanged = currMessage.hasChanged; var context = GlobalHost.ConnectionManager.GetHubContext(); context.Clients.Group("ncData").recipeChangedData(currMessage); + + if (Config.ServerConfig.ServerStartupConfig.CmsConnectReady) + { + RedisController.WriteProductionName(1,currMessage.recipeName); + } } } @@ -472,6 +484,9 @@ namespace Thermo.Active.Listeners.SignalR { RedisController.WriteCurrentMachineStatus(CMSConnectConstants.ConvertThermoToConnectStatus(currProdCycle.Status)); RedisController.WriteCurrentMachinePowerPath(CMSConnectConstants.ConvertThermoToConnectPower(currProdCycle.Status)); + + RedisController.WriteCurrentProcessStatus(1,CMSConnectConstants.ConvertThermoToConnectProcessStatus(currProdCycle.Status)); + RedisController.WriteCurrentProcessMode(1,CMSConnectConstants.ConvertThermoToConnectProcessMode(currProdCycle.Mode)); } } }