diff --git a/Thermo.Active.Config/Config/IOConfig.xml b/Thermo.Active.Config/Config/IOConfig.xml
new file mode 100644
index 00000000..6d641346
--- /dev/null
+++ b/Thermo.Active.Config/Config/IOConfig.xml
@@ -0,0 +1,229 @@
+
+
+
+ 0
+ DI
+ 0
+ 0
+ 301
+ 404
+ A32.3
+
+
+ 1
+ DI
+ 0
+ 1
+ 301
+ 405
+ A32.5
+ true
+
+
+ 2
+ DI
+ 0
+ 2
+ 301
+ 406
+ A32.7
+
+
+ 3
+ DI
+ 0
+ 3
+ 301
+ 407
+ A32.8
+
+
+ 4
+ DI
+ 0
+ 4
+ 301
+ 408
+ A32.1
+
+
+ 5
+ AI
+ 0
+ 5
+ 301
+ 409
+ A32.2
+
+
+ 6
+ DI
+ 0
+ 6
+ 301
+ 210
+ A32.4
+
+
+ 7
+ DI
+ 0
+ 7
+ 301
+ 211
+ A32.6
+
+
+ 0
+ DO
+ 0
+ 0
+ 301
+ 404
+ B43.3
+
+
+ 1
+ DO
+ 0
+ 1
+ 301
+ 405
+ B43.5
+
+
+ 2
+ DO
+ 0
+ 2
+ 301
+ 406
+ B43.7
+
+
+ 3
+ DO
+ 0
+ 3
+ 301
+ 407
+ B43.8
+
+
+ 4
+ DO
+ 0
+ 4
+ 301
+ 408
+ B43.1
+
+
+ 21
+ DO
+ 1
+ 5
+ 301
+ 409
+ B43.2
+
+
+ 22
+ DO
+ 1
+ 6
+ 301
+ 210
+ B43.4
+
+
+ 23
+ DO
+ 1
+ 7
+ 301
+ 211
+ B43.6
+
+
+ 0
+ AI
+ 0
+ 0
+ 511
+ 614
+ C43.23
+
+
+ 1
+ AI
+ 0
+ 1
+ 511
+ 615
+ C43.25
+
+
+ 16
+ AI
+ 2
+ 0
+ 501
+ 604
+ C43.3
+
+
+ 17
+ AI
+ 2
+ 1
+ 501
+ 605
+ C43.5
+
+
+ 0
+ AO
+ 0
+ 0
+ 700
+ 800
+ D43.13
+
+
+ 1
+ AO
+ 0
+ 1
+ 701
+ 801
+ D43.14
+
+
+ 2
+ AO
+ 0
+ 2
+ 702
+ 802
+ D43.15
+
+
+ 16
+ AO
+ 3
+ 0
+ 701
+ 804
+ D43.3
+
+
+ 31
+ AO
+ 4
+ 15
+ 701
+ 805
+ D43.5
+
+
\ No newline at end of file
diff --git a/Thermo.Active.Config/Config/IOConfigValidator.xsd b/Thermo.Active.Config/Config/IOConfigValidator.xsd
new file mode 100644
index 00000000..2f1a68ab
--- /dev/null
+++ b/Thermo.Active.Config/Config/IOConfigValidator.xsd
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Thermo.Active.Config/Config/serverConfig.xml b/Thermo.Active.Config/Config/serverConfig.xml
index 6301f517..43d120f2 100644
--- a/Thermo.Active.Config/Config/serverConfig.xml
+++ b/Thermo.Active.Config/Config/serverConfig.xml
@@ -4,7 +4,7 @@
S7NET
false
- 192.168.0.1
+ 192.168.0.102
102
Thermo 2020
C:\CMS\Recipes\
@@ -119,6 +119,8 @@
+
+
diff --git a/Thermo.Active.Config/ServerConfig.cs b/Thermo.Active.Config/ServerConfig.cs
index 21598824..e1b1b2e2 100644
--- a/Thermo.Active.Config/ServerConfig.cs
+++ b/Thermo.Active.Config/ServerConfig.cs
@@ -61,6 +61,7 @@ namespace Thermo.Active.Config
public static List ThermoProdConfig;
public static List RecipeConfig;
public static List ModBlockConfig;
+ public static List IOConfig;
public static List RiskResistConfig;
public static List RiskChannelConfig;
public static List RiskBoardConfig;
diff --git a/Thermo.Active.Config/ServerConfigController.cs b/Thermo.Active.Config/ServerConfigController.cs
index 8ee9f64a..de8b6946 100644
--- a/Thermo.Active.Config/ServerConfigController.cs
+++ b/Thermo.Active.Config/ServerConfigController.cs
@@ -326,6 +326,7 @@ namespace Thermo.Active.Config
ReadThermoProdConfig();
ReadRecipeConfig();
ReadModBlockConfig();
+ ReadIOConfig();
ReadRiskConfig();
ReadAxesConfig();
ReadCMSConnectConfig();
@@ -499,6 +500,30 @@ namespace Thermo.Active.Config
.ToList();
}
+ ///
+ /// IO config setup from file
+ ///
+ private static void ReadIOConfig()
+ {
+ XDocument xmlConfigFile = GetXmlHandlerWithValidator(IO_CONFIG_SCHEMA_PATH, IO_CONFIG_PATH);
+ // Read head config from XML file
+ IOConfig = xmlConfigFile
+ .Root
+ .Elements()
+ .Select(x => new IOConfigModel()
+ {
+ Id = Convert.ToInt16(x.Element("id").Value),
+ Category = GetTActIO_Type(x.Element("category").Value),
+ Bank = x.Element("bank") != null ? x.Element("bank").Value : "0",
+ Position = x.Element("position") != null ? x.Element("position").Value : "0",
+ Page = x.Element("page") != null ? x.Element("page").Value : "",
+ Wire = x.Element("wire") != null ? x.Element("wire").Value : "",
+ Profinet = x.Element("profinet") != null ? x.Element("profinet").Value : "",
+ DisableForce = x.Element("disableForce") != null ? Convert.ToBoolean(x.Element("disableForce").Value): false
+ })
+ .ToList();
+ }
+
private static void ReadNcSoftKeys()
{
XDocument xmlConfigFile = GetXmlHandlerWithValidator(NC_SOFTKEYS_CONFIG_SCHEMA_PATH, NC_SOFTKEYS_CONFIG_PATH);
diff --git a/Thermo.Active.Config/Thermo.Active.Config.csproj b/Thermo.Active.Config/Thermo.Active.Config.csproj
index db77d72e..99d8c390 100644
--- a/Thermo.Active.Config/Thermo.Active.Config.csproj
+++ b/Thermo.Active.Config/Thermo.Active.Config.csproj
@@ -65,6 +65,9 @@
+
+ PreserveNewest
+
PreserveNewest
@@ -215,6 +218,10 @@
Designer
Always
+
+ Designer
+ Always
+
Always
diff --git a/Thermo.Active.Core/ThreadsFunctions.cs b/Thermo.Active.Core/ThreadsFunctions.cs
index 211a283c..57fa3178 100644
--- a/Thermo.Active.Core/ThreadsFunctions.cs
+++ b/Thermo.Active.Core/ThreadsFunctions.cs
@@ -30,6 +30,7 @@ using static Thermo.Active.Utils.ExceptionManager;
using System.Windows;
using System.Drawing;
using System.Configuration;
+using Thermo.Active.Model.DTOModels.ThIO;
public static class ThreadsFunctions
{
@@ -412,6 +413,55 @@ public static class ThreadsFunctions
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()
{
diff --git a/Thermo.Active.Core/ThreadsHandler.cs b/Thermo.Active.Core/ThreadsHandler.cs
index 1727e073..0c608eb8 100644
--- a/Thermo.Active.Core/ThreadsHandler.cs
+++ b/Thermo.Active.Core/ThreadsHandler.cs
@@ -36,6 +36,7 @@ namespace Thermo.Active.Core
ThreadsFunctions.ReadScadaData,
ThreadsFunctions.ReadMComandsData,
ThreadsFunctions.ReadAxisInfoData,
+ ThreadsFunctions.ReadChannelsIoData,
ThreadsFunctions.ReadM154Data // levare?
};
diff --git a/Thermo.Active.Database/Controllers/RedisController.cs b/Thermo.Active.Database/Controllers/RedisController.cs
index 1143bef6..9bd42ef6 100644
--- a/Thermo.Active.Database/Controllers/RedisController.cs
+++ b/Thermo.Active.Database/Controllers/RedisController.cs
@@ -19,7 +19,7 @@ namespace Thermo.Active.Database.Controllers
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 alarmsPath = "Machine:Plc:Condition";
private const string processStatusPath = "Machine:Cnc:CncProcesses:%NN%:Status";
private const string processModePath = "Machine:Cnc:CncProcesses:%NN%:Mode";
private const string processFeedOverridePath = "Machine:Cnc:CncProcesses:%NN%:FeedOverride";
@@ -27,7 +27,7 @@ namespace Thermo.Active.Database.Controllers
private const string processSpeedOverridePath = "Machine:Cnc:CncProcesses:%NN%:SpeedOverride";
private const string datamodelPath = "AdpConf:DataModel";
- private const string currentActiveVersionPath = "Machine:Hmi:Version";
+ private const string currentActiveVersionPath = "Machine:Hmi:Version";
private const string machineAxisPosition = "Machine:Axes:%NN%:CurrentPos";
private const string machineAxisSpeed = "Machine:Axes:%NN%:FeedRate";
private const string machineAxisLoad = "Machine:Axes:%NN%:Load";
@@ -70,7 +70,7 @@ namespace Thermo.Active.Database.Controllers
string redisHash = redUtil.man.redHash(redisAlmEn);
return redUtil.man.redSaveHashDict(redisHash, alarms);
}
-
+
public static bool WriteDatamodel(string datamodel)
{
@@ -79,7 +79,7 @@ namespace Thermo.Active.Database.Controllers
}
public static bool WriteDefaultEntry(Dictionary entries)
{
- foreach (KeyValuePair entry in entries)
+ foreach (KeyValuePair entry in entries)
{
if (!redUtil.man.setRSV(redUtil.man.redHash(entry.Key), entry.Value))
return false;
@@ -109,7 +109,7 @@ 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"));
@@ -131,21 +131,21 @@ namespace Thermo.Active.Database.Controllers
if (!redUtil.man.setRSV(redisHash, "100"))
return false;
redisHash = redUtil.man.redHash(processSpeedOverridePath).Replace("%NN%", ProductionProcess.ToString("00"));
- if(!redUtil.man.setRSV(redisHash, "100"))
+ if (!redUtil.man.setRSV(redisHash, "100"))
return false;
return true;
}
-
+
public static bool WriteCurrentMachinePowerPath(bool status)
{
string redisHash = redUtil.man.redHash(machinePowerPath);
- if(status)
+ if (status)
return redUtil.man.setRSV(redisHash, "true");
else
return redUtil.man.setRSV(redisHash, "false");
}
-
+
public static bool WriteCurrentMachineAlarmPath(bool status)
{
string redisHash = redUtil.man.redHash(machineAlarmPath);
@@ -154,7 +154,7 @@ namespace Thermo.Active.Database.Controllers
else
return redUtil.man.setRSV(redisHash, "false");
}
-
+
public static bool WriteCurrentMachineEmergencyPath(bool status)
{
string redisHash = redUtil.man.redHash(machineEmergencyPath);
@@ -183,14 +183,41 @@ namespace Thermo.Active.Database.Controllers
redUtil.man.ListPush(redisHash, msg);
return true;
}
+ public static string ReadValue(string msgKey)
+ {
+ string redisHash = redUtil.man.redHash(msgKey);
+ return redUtil.man.getRSV(redisHash);
+ }
+ public static bool WriteValue(string msgKey, string msg, int ttlSec)
+ {
+ string redisHash = redUtil.man.redHash(msgKey);
+ redUtil.man.setRSV(redisHash, msg, ttlSec);
+ return true;
+ }
+
+ public static bool FastIoSample
+ {
+ get
+ {
+ var currVal = ReadValue("FastIoSample");
+ bool answ = !string.IsNullOrEmpty(currVal);
+ return answ;
+ }
+ set
+ {
+ // TTL: se true 5 min, altrimenti 1 sec
+ int ttlSec = value ? 60 * 5 : 1;
+ WriteValue("FastIoSample", "Active", ttlSec);
+ }
+ }
public static bool WriteCurrentAxisStatus(Dictionary axis)
{
- foreach(KeyValuePair asse in axis)
+ foreach (KeyValuePair asse in axis)
{
string redisHash = redUtil.man.redHash(machineAxisName).Replace("%NN%", asse.Value.ID.ToString("00"));
- if(redUtil.man.getRSV(redisHash) != null)
+ if (redUtil.man.getRSV(redisHash) != null)
{
redisHash = redUtil.man.redHash(machineAxisPosition).Replace("%NN%", asse.Value.ID.ToString("00"));
if (!redUtil.man.setRSV(redisHash, asse.Value.position.ToString()))
@@ -203,7 +230,7 @@ namespace Thermo.Active.Database.Controllers
redisHash = redUtil.man.redHash(machineAxisLoad).Replace("%NN%", asse.Value.ID.ToString("00"));
if (!redUtil.man.setRSV(redisHash, asse.Value.load.ToString()))
return false;
- }
+ }
}
return true;
}
diff --git a/Thermo.Active.Model/ConfigModels/IOConfigModel.cs b/Thermo.Active.Model/ConfigModels/IOConfigModel.cs
new file mode 100644
index 00000000..2cfc288c
--- /dev/null
+++ b/Thermo.Active.Model/ConfigModels/IOConfigModel.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using static Thermo.Active.Model.Constants;
+
+namespace Thermo.Active.Model.ConfigModels
+{
+ public class IOConfigModel
+ {
+ public TACT_IO_TYPE Category { get; set; }
+ public int Id { get; set; } =0;
+ public string Bank { get; set; } = "0";
+ public string Position { get; set; } = "0";
+ public string Page { get; set; } = "";
+ public string Wire { get; set; } = "";
+ public string Profinet { get; set; } = "";
+ public bool DisableForce { get; set; } = false;
+ public string Label
+ {
+ get
+ {
+ string answ = $"LBL_IO_{Category}_{Id}";
+ return answ;
+ }
+ }
+ }
+
+}
diff --git a/Thermo.Active.Model/Constants.cs b/Thermo.Active.Model/Constants.cs
index b69607df..fc041bc4 100644
--- a/Thermo.Active.Model/Constants.cs
+++ b/Thermo.Active.Model/Constants.cs
@@ -98,6 +98,26 @@ namespace Thermo.Active.Model
Options
}
+ public enum TACT_IO_TYPE
+ {
+ ND = 0,
+ ///
+ /// Digital IN
+ ///
+ DI,
+ ///
+ /// Digital OUT
+ ///
+ DO,
+ ///
+ /// Analog IN
+ ///
+ AI,
+ ///
+ /// Analog OUT
+ ///
+ AO
+ }
public enum TACT_MBLOCK_TYPE
{
ND = 0,
@@ -303,6 +323,9 @@ namespace Thermo.Active.Model
public const string MODBLOCK_CONFIG_SCHEMA_PATH = RESOURCE_DIRECTORY + "moduleBlockConfigValidator.xsd";
public const string MODBLOCK_CONFIG_PATH = CONFIG_DIRECTORY + "moduleBlockConfig.xml";
+ public const string IO_CONFIG_SCHEMA_PATH = RESOURCE_DIRECTORY + "IOConfigValidator.xsd";
+ public const string IO_CONFIG_PATH = CONFIG_DIRECTORY + "IOConfig.xml";
+
public const string RISK_CONFIG_SCHEMA_PATH = RESOURCE_DIRECTORY + "risk2007Validator.xsd";
public const string RISK_CONFIG_PATH = CONFIG_DIRECTORY + "risk2007.xml";
@@ -354,6 +377,7 @@ namespace Thermo.Active.Model
public const string SEND_NC_SOFTKEYS_DATA = "SEND_NC_SOFTKEYS_DATA";
public const string SEND_HEADS_DATA = "SEND_HEADS_DATA";
public const string SEND_AXIS_INFO = "SEND_AXIS_INFO";
+ public const string SEND_CHANNELS_IO_DATA = "SEND_CHANNELS_IO_DATA";
public const string SEND_ACTIVE_PROGRAM_DATA = "SEND_ACTIVE_PROGRAM_DATA";
public const string SEND_QUEUE_DATA = "SEND_QUEUE_DATA";
public const string SEND_M155_DATA = "SEND_M155_DATA";
diff --git a/Thermo.Active.Model/DTOModels/ThIO/DTOChannelsIO.cs b/Thermo.Active.Model/DTOModels/ThIO/DTOChannelsIO.cs
new file mode 100644
index 00000000..5f7efb57
--- /dev/null
+++ b/Thermo.Active.Model/DTOModels/ThIO/DTOChannelsIO.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Thermo.Active.Model.DTOModels.ThIO
+{
+ public class DTOChannelsIO
+ {
+ public List DI { get; set; } = new List();
+ public List DO { get; set; } = new List();
+ public List AI { get; set; } = new List();
+ public List AO { get; set; } = new List();
+ }
+ public class DigitalIN : IoItemConf
+ {
+ public bool Value { get; set; } = false;
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is DigitalIN item))
+ return false;
+
+ if (Value != item.Value)
+ return false;
+
+ return base.Equals((IoItemConf)obj);
+ }
+ ///
+ /// Hash gen
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+ public class AnalogIN : IoItemConf
+ {
+ public int Value { get; set; } = 0;
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is AnalogIN item))
+ return false;
+
+ if (Value != item.Value)
+ return false;
+
+ return base.Equals((IoItemConf)obj);
+ }
+ ///
+ /// Hash gen
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+ public class DigitalOUT : DigitalIN
+ {
+ public bool ForceEnabled { get; set; } = true;
+ public bool ForceZero { get; set; } = false;
+ public bool ForceOne { get; set; } = false;
+ public bool IsForced { get; set; } = false;
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is DigitalOUT item))
+ return false;
+
+ if (ForceEnabled != item.ForceEnabled)
+ return false;
+ if (ForceZero != item.ForceZero)
+ return false;
+ if (ForceOne != item.ForceOne)
+ return false;
+ if (IsForced != item.IsForced)
+ return false;
+
+ return base.Equals((DigitalIN)obj);
+ }
+ ///
+ /// Hash gen
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+ public class AnalogOUT : AnalogIN
+ {
+ public bool ForceEnabled { get; set; } = true;
+ public int ForcedValue { get; set; } = 0;
+ public bool IsForced { get; set; } = false;
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is AnalogOUT item))
+ return false;
+
+ if (ForceEnabled != item.ForceEnabled)
+ return false;
+ if (ForcedValue != item.ForcedValue)
+ return false;
+ if (IsForced != item.IsForced)
+ return false;
+
+ return base.Equals((AnalogIN)obj);
+ }
+ ///
+ /// Hash gen
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+
+}
diff --git a/Thermo.Active.Model/DTOModels/ThIO/DTOChannelsIOVal.cs b/Thermo.Active.Model/DTOModels/ThIO/DTOChannelsIOVal.cs
new file mode 100644
index 00000000..d327aefe
--- /dev/null
+++ b/Thermo.Active.Model/DTOModels/ThIO/DTOChannelsIOVal.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Thermo.Active.Model.DTOModels.ThIO
+{
+ public class DTOChannelsIOVal
+ {
+ public List DI { get; set; } = new List();
+ public List DO { get; set; } = new List();
+ public List AI { get; set; } = new List();
+ public List AO { get; set; } = new List();
+ }
+ public class DigInVal: IoItem
+ {
+ public bool Value { get; set; } = false;
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is DigitalIN item))
+ return false;
+
+ if (Value != item.Value)
+ return false;
+
+ return base.Equals((IoItemConf)obj);
+ }
+ ///
+ /// Hash gen
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+ public class AnalInVal: IoItem
+ {
+ public int Value { get; set; } = 0;
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is AnalogIN item))
+ return false;
+
+ if (Value != item.Value)
+ return false;
+
+ return base.Equals((IoItemConf)obj);
+ }
+ ///
+ /// Hash gen
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+ public class DigOutVal : DigInVal
+ {
+ public bool ForceEnabled { get; set; } = true;
+ public bool ForceZero { get; set; } = false;
+ public bool ForceOne { get; set; } = false;
+ public bool IsForced { get; set; } = false;
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is DigitalOUT item))
+ return false;
+
+ if (ForceEnabled != item.ForceEnabled)
+ return false;
+ if (ForceZero != item.ForceZero)
+ return false;
+ if (ForceOne != item.ForceOne)
+ return false;
+ if (IsForced != item.IsForced)
+ return false;
+
+ return base.Equals((DigitalIN)obj);
+ }
+ ///
+ /// Hash gen
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+ public class AnalOutVal : AnalInVal
+ {
+ public bool ForceEnabled { get; set; } = true;
+ public int ForcedValue { get; set; } = 0;
+ public bool IsForced { get; set; } = false;
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is AnalogOUT item))
+ return false;
+
+ if (ForceEnabled != item.ForceEnabled)
+ return false;
+ if (ForcedValue != item.ForcedValue)
+ return false;
+ if (IsForced != item.IsForced)
+ return false;
+
+ return base.Equals((AnalogIN)obj);
+ }
+ ///
+ /// Hash gen
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+
+}
diff --git a/Thermo.Active.Model/DTOModels/ThIO/DTOChannelsSetup.cs b/Thermo.Active.Model/DTOModels/ThIO/DTOChannelsSetup.cs
new file mode 100644
index 00000000..8c26c8b9
--- /dev/null
+++ b/Thermo.Active.Model/DTOModels/ThIO/DTOChannelsSetup.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Thermo.Active.Model.DTOModels.ThIO
+{
+ public class DTOChannelsSetup
+ {
+ public List DI { get; set; } = new List();
+ public List DO { get; set; } = new List();
+ public List AI { get; set; } = new List();
+ public List AO { get; set; } = new List();
+ }
+}
diff --git a/Thermo.Active.Model/DTOModels/ThIO/DTOCycleLog.cs b/Thermo.Active.Model/DTOModels/ThIO/DTOCycleLog.cs
new file mode 100644
index 00000000..9cbc2db6
--- /dev/null
+++ b/Thermo.Active.Model/DTOModels/ThIO/DTOCycleLog.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Thermo.Active.Model.DTOModels.ThIO
+{
+ public class DTOCycleLog
+ {
+ public List events { get; set; } = new List();
+ }
+
+ public class CycleEvent
+ {
+ public DateTime dtEvent { get; set; }
+
+ public int code { get; set; } = 0;
+ }
+}
diff --git a/Thermo.Active.Model/DTOModels/ThIO/IoItemConf.cs b/Thermo.Active.Model/DTOModels/ThIO/IoItemConf.cs
new file mode 100644
index 00000000..6e4e2b6c
--- /dev/null
+++ b/Thermo.Active.Model/DTOModels/ThIO/IoItemConf.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Thermo.Active.Model.DTOModels.ThIO
+{
+ public class IoItem
+ {
+ public int Id { get; set; } = 0;
+ }
+ public class IoItemDigi : IoItem
+ {
+ public bool value { get; set; } = false;
+ }
+ public class IoItemAnal : IoItem
+ {
+ public int value { get; set; } = 0;
+ }
+ public class IoItemConf : IoItem
+ {
+ public string Bank { get; set; } = "0";
+ public string Position { get; set; } = "0";
+ public string Page { get; set; } = "0";
+ public string Wire { get; set; } = "0";
+ public string Profinet { get; set; } = "0";
+ public string Label { get; set; } = "LBL";
+ public bool Visible { get; set; } = true;
+
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is IoItemConf item))
+ return false;
+
+ if (Id != item.Id)
+ return false;
+ if (Bank != item.Bank)
+ return false;
+ if (Position != item.Position)
+ return false;
+ if (Page != item.Page)
+ return false;
+ if (Wire != Wire)
+ return false;
+ if (Profinet != item.Profinet)
+ return false;
+ if (Label != item.Label)
+ return false;
+ if (Visible != item.Visible)
+ return false;
+
+ return true;
+ }
+ ///
+ /// Hash gen
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+}
diff --git a/Thermo.Active.Model/Thermo.Active.Model.csproj b/Thermo.Active.Model/Thermo.Active.Model.csproj
index 53f0a8d6..9c1f8e90 100644
--- a/Thermo.Active.Model/Thermo.Active.Model.csproj
+++ b/Thermo.Active.Model/Thermo.Active.Model.csproj
@@ -66,6 +66,7 @@
+
@@ -112,6 +113,11 @@
+
+
+
+
+
diff --git a/Thermo.Active.NC/NcAdapter.cs b/Thermo.Active.NC/NcAdapter.cs
index 4cdbb667..e484a923 100644
--- a/Thermo.Active.NC/NcAdapter.cs
+++ b/Thermo.Active.NC/NcAdapter.cs
@@ -14,6 +14,7 @@ using Thermo.Active.Model.DTOModels.AlarmModels;
using Thermo.Active.Model.DTOModels.MaintenanceModels;
using Thermo.Active.Model.DTOModels.Scada;
using Thermo.Active.Model.DTOModels.ThAxes;
+using Thermo.Active.Model.DTOModels.ThIO;
using Thermo.Active.Model.DTOModels.ThModules;
using Thermo.Active.Model.DTOModels.ThProd;
using Thermo.Active.Model.DTOModels.ThRecipe;
@@ -1456,6 +1457,134 @@ namespace Thermo.Active.NC
return libraryError;
}
+
+ ///
+ /// Legge dal PLC elenco di eventi LOG del ciclo e li presenta
+ ///
+ /// Oggetto elenco elementi LOG registrati da macchina
+ ///
+ public CmsError GetCycleLog(out Dictionary machineLog)
+ {
+ CmsError libraryError = NO_ERROR;
+ machineLog = new Dictionary();
+
+ if (false)
+ {
+ // recupero l'oggetto dall'NC
+
+ // effettuo traduzione
+#if false
+ // overview di base: ultima salvata...
+ var err2fix = new Dictionary();
+
+ // leggo la ricetta dal PLC!
+ var currRecipe = new Dictionary();
+ libraryError = ReadFullRecipe(out currRecipe);
+ if (libraryError.IsError())
+ return libraryError;
+
+ // leggo l'intero array delle DB... QUI FAKE sulle DB configurate...
+ List recipeConfig = RecipeConfig.Select(x => new DTORecipeConfigModel()
+ {
+ Id = x.Id,
+ ScaleFactor = x.ScaleFactor,
+ NumDec = x.NumDec,
+ Category = x.Category.ToString(),
+ SubCategory_1 = x.SubCategory_1,
+ SubCategory_2 = x.SubCategory_2,
+ Name = x.Name,
+ Description = x.Description,
+ Format = x.Format,
+ Label = $"{x.Category}_{x.SubCategory_1}_{x.SubCategory_2}_{x.Name}".Replace("__", "_").Replace("__", "_").ToLower(),
+ EnumVal = x.EnumVal
+ }).ToList();
+
+ RecipeCatStatus currStatus = RecipeCatStatus.Unchanged;
+
+ // da conf ricetta --> se ci sono li leggo da li...
+ if (NcFileAdapter.RecipeLiveData.RecipeOverview != null)
+ {
+ currOverview = NcFileAdapter.RecipeLiveData.RecipeOverview;
+ }
+
+ // verifico eventualmente se mancasse qualcosa...
+ bool changed = false;
+ foreach (var item in recipeConfig)
+ {
+ if (!currOverview.ContainsKey(getRecipeSection(item.Category)))
+ {
+ currOverview.Add(getRecipeSection(item.Category), RecipeCatStatus.Unchanged);
+ changed = true;
+ }
+ }
+
+ // ricerco SE co fossero errori --> reset come changedOK
+ foreach (var item in currOverview)
+ {
+ if (item.Value == RecipeCatStatus.HasError)
+ err2fix.Add(item.Key, RecipeCatStatus.ChangedOk);
+ }
+ foreach (var item in err2fix)
+ {
+ currOverview[item.Key] = item.Value;
+ changed = true;
+ }
+
+ // se cambiato --> salvo in live data...
+ if (changed)
+ {
+ NcFileAdapter.RecipeLiveData.RecipeOverview = currOverview;
+ }
+
+ // ORA percorro conf ricetta x cercare eventuali ERRORI......
+ foreach (var item in recipeConfig)
+ {
+ currStatus = currOverview[getRecipeSection(item.Category)];
+
+ // se lo stato è errore --> esco...
+ if (currStatus == RecipeCatStatus.HasError)
+ {
+ continue;
+ }
+ // altrimenti controllo
+ else
+ {
+ // se in errore AND visibile --> registro...
+ bool checkCondition = false;
+ checkCondition = (currRecipe[item.Label].Status.HasError);
+ // 2020.07.29 - controllo condizione secondo status debug/release...
+ if (checkCondition)
+ {
+ currOverview[getRecipeSection(item.Category)] = RecipeCatStatus.HasError;
+ }
+ }
+ }
+#endif
+ }
+ // altrimenti genero FAKE data
+ else
+ {
+ int eventVal = 0;
+ DateTime eventDate = DateTime.Now;
+ // genero random eventi da 1..maxEvent
+ Random rndGen = new Random();
+ int maxEvent = 16;
+ int maxDelay = 30000;
+ for (int i = 0; i < 1024; i++)
+ {
+ // calcolo nuovo evento
+ eventVal = rndGen.Next(maxEvent);
+ // calcolo tempo anticipato
+ eventDate = eventDate.AddMilliseconds(-rndGen.Next(maxDelay));
+ //salvo
+ machineLog.Add(eventDate, eventVal);
+ }
+ }
+
+ // restituisco cod errore se trovato
+ return libraryError;
+ }
+
///
/// Legge tutti i parametri della ricetta e calcolo la overview dei vari steps
///
@@ -2038,6 +2167,154 @@ namespace Thermo.Active.NC
}
return libraryError;
}
+ ///
+ /// Restituisce intero set dati IO Channels (conf + valori)
+ ///
+ ///
+ ///
+ public CmsError ReadFullIO(out DTOChannelsIO currChannelsIO)
+ {
+ CmsError libraryError = NO_ERROR;
+ currChannelsIO = new DTOChannelsIO();
+
+ // read and return channel IO data
+ if (NcConfig.NcVendor == NC_VENDOR.S7NET)
+ {
+ // lettura da PLC
+ Dictionary currModBlock = new Dictionary();
+ ThermoModels.ChanIOVis currThermoIOVis = new ThermoModels.ChanIOVis();
+ ThermoModels.ChanIOVal currThermoIOVal = new ThermoModels.ChanIOVal();
+ ThermoModels.ChanIOFor currThermoIOFor = new ThermoModels.ChanIOFor();
+ ThermoModels.ChanIOValFor currThermoIOValFor = new ThermoModels.ChanIOValFor();
+ libraryError = numericalControl.PLC_RIOChannelsConf(ref currThermoIOVis);
+ libraryError = numericalControl.PLC_RIOChannelsVal(ref currThermoIOVal, ref currThermoIOFor, ref currThermoIOValFor);
+
+ // setup da config
+ List listDI = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.DI).Select(x => new DigitalIN()
+ {
+ Id = x.Id,
+ Bank = x.Bank,
+ Position = x.Position,
+ //Page = x.Category.ToString(),
+ Page = x.Page,
+ Wire = x.Wire,
+ Profinet = x.Profinet,
+ Label = x.Label.Replace("__", "_").Replace("__", "_").ToLower(),
+ Visible = currThermoIOVis.DI.ContainsKey(x.Id)? currThermoIOVis.DI[x.Id]:false,
+ Value = currThermoIOVal.DI.ContainsKey(x.Id) ? currThermoIOVal.DI[x.Id] : false
+ }).ToList();
+ List listDO = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.DO).Select(x => new DigitalOUT()
+ {
+ Id = x.Id,
+ Bank = x.Bank,
+ Position = x.Position,
+ //Page = x.Category.ToString(),
+ Page = x.Page,
+ Wire = x.Wire,
+ Profinet = x.Profinet,
+ Label = x.Label.Replace("__", "_").Replace("__", "_").ToLower(),
+ ForceEnabled=!x.DisableForce,
+ Visible = currThermoIOVis.DO.ContainsKey(x.Id) ? currThermoIOVis.DO[x.Id] : false,
+ Value = currThermoIOVal.DO.ContainsKey(x.Id) ? currThermoIOVal.DO[x.Id] : false,
+ IsForced = currThermoIOFor.DO.ContainsKey(x.Id) ? currThermoIOFor.DO[x.Id] : false,
+ ForceOne = currThermoIOValFor.DO.ContainsKey(x.Id) ? currThermoIOValFor.DO[x.Id] : false,
+ ForceZero = currThermoIOValFor.DO.ContainsKey(x.Id) ? !currThermoIOValFor.DO[x.Id] : false
+ }).ToList();
+ List listAI = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.AI).Select(x => new AnalogIN()
+ {
+ Id = x.Id,
+ Bank = x.Bank,
+ Position = x.Position,
+ //Page = x.Category.ToString(),
+ Page = x.Page,
+ Wire = x.Wire,
+ Profinet = x.Profinet,
+ Label = x.Label.Replace("__", "_").Replace("__", "_").ToLower(),
+ Visible = currThermoIOVis.AI.ContainsKey(x.Id) ? currThermoIOVis.AI[x.Id] : false,
+ Value = currThermoIOVal.AI.ContainsKey(x.Id) ? currThermoIOVal.AI[x.Id] : 0
+ }).ToList();
+ List listAO = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.AO).Select(x => new AnalogOUT()
+ {
+ Id = x.Id,
+ Bank = x.Bank,
+ Position = x.Position,
+ //Page = x.Category.ToString(),
+ Page = x.Page,
+ Wire = x.Wire,
+ Profinet = x.Profinet,
+ Label = x.Label.Replace("__", "_").Replace("__", "_").ToLower(),
+ ForceEnabled = !x.DisableForce,
+ Visible = currThermoIOVis.AO.ContainsKey(x.Id) ? currThermoIOVis.AO[x.Id] : false,
+ Value = currThermoIOVal.AO.ContainsKey(x.Id) ? currThermoIOVal.AO[x.Id] : 0,
+ IsForced = currThermoIOFor.AO.ContainsKey(x.Id) ? currThermoIOFor.AO[x.Id] : false,
+ ForcedValue = currThermoIOValFor.AO.ContainsKey(x.Id) ? currThermoIOValFor.AO[x.Id] : 0
+ }).ToList();
+
+ // assegno!
+ currChannelsIO.DI = listDI;
+ currChannelsIO.DO = listDO;
+ currChannelsIO.AI = listAI;
+ currChannelsIO.AO = listAO;
+ }
+ return libraryError;
+ }
+ ///
+ /// Restitusice SOLO VALORI IO Channels
+ ///
+ ///
+ ///
+ public CmsError ReadValIO(out DTOChannelsIOVal currChannelsIoVal)
+ {
+ CmsError libraryError = NO_ERROR;
+ currChannelsIoVal = new DTOChannelsIOVal();
+ // read and return channel IO data
+ if (NcConfig.NcVendor == NC_VENDOR.S7NET)
+ {
+ // lettura da PLC
+ Dictionary currModBlock = new Dictionary();
+ ThermoModels.ChanIOVal currThermoIOVal = new ThermoModels.ChanIOVal();
+ ThermoModels.ChanIOFor currThermoIOFor = new ThermoModels.ChanIOFor();
+ ThermoModels.ChanIOValFor currThermoIOValFor = new ThermoModels.ChanIOValFor();
+ libraryError = numericalControl.PLC_RIOChannelsVal(ref currThermoIOVal, ref currThermoIOFor, ref currThermoIOValFor);
+
+ // setup da config
+ List listDI = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.DI).Select(x => new DigInVal()
+ {
+ Id = x.Id,
+ Value = currThermoIOVal.DI.ContainsKey(x.Id) ? currThermoIOVal.DI[x.Id] : false
+ }).ToList();
+ List listDO = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.DO).Select(x => new DigOutVal()
+ {
+ Id = x.Id,
+ ForceEnabled = !x.DisableForce,
+ Value = currThermoIOVal.DO.ContainsKey(x.Id) ? currThermoIOVal.DO[x.Id] : false,
+ IsForced = currThermoIOFor.DO.ContainsKey(x.Id) ? currThermoIOFor.DO[x.Id] : false,
+ ForceOne = currThermoIOValFor.DO.ContainsKey(x.Id) ? currThermoIOValFor.DO[x.Id] : false,
+ ForceZero = currThermoIOValFor.DO.ContainsKey(x.Id) ? !currThermoIOValFor.DO[x.Id] : false
+ }).ToList();
+ List listAI = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.AI).Select(x => new AnalInVal()
+ {
+ Id = x.Id,
+ Value = currThermoIOVal.AI.ContainsKey(x.Id) ? currThermoIOVal.AI[x.Id] : 0
+ }).ToList();
+ List listAO = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.AO).Select(x => new AnalOutVal()
+ {
+ Id = x.Id,
+ ForceEnabled = !x.DisableForce,
+ Value = currThermoIOVal.AO.ContainsKey(x.Id) ? currThermoIOVal.AO[x.Id] : 0,
+ IsForced = currThermoIOFor.AO.ContainsKey(x.Id) ? currThermoIOFor.AO[x.Id] : false,
+ ForcedValue = currThermoIOValFor.AO.ContainsKey(x.Id) ? currThermoIOValFor.AO[x.Id] : 0
+ }).ToList();
+
+ // assegno!
+ currChannelsIoVal.DI = listDI;
+ currChannelsIoVal.DO = listDO;
+ currChannelsIoVal.AI = listAI;
+ currChannelsIoVal.AO = listAO;
+ }
+ return libraryError;
+
+ }
///
/// Legge tutti i parametri della ricetta
@@ -3061,7 +3338,7 @@ namespace Thermo.Active.NC
///
/// Oggetto parametri da aggiornare (from HMI)
/// num max parametri da scrivere singolarmente
- /// delay in scriottura multi parametri singoli
+ /// delay in scrittura multi parametri singoli
///
public CmsError WriteRecipeParametersToPLC(Dictionary updtRecipe, int nMaxParamWrite, int delayParamWrite)
{
@@ -3091,7 +3368,7 @@ namespace Thermo.Active.NC
///
/// Oggetto parametri da aggiornare (from HMI)
/// num max parametri da scrivere singolarmente
- /// delay in scriottura multi parametri singoli
+ /// delay in scrittura multi parametri singoli
///
public CmsError WriteRecipeParams(Dictionary updtRecipe, int nMaxParamWrite, int delayParamWrite)
{
@@ -3100,6 +3377,125 @@ namespace Thermo.Active.NC
return libraryError;
}
+
+ ///
+ /// ChannelsID: write DO to PLC (values + setForce)
+ ///
+ /// Oggetto parametri da aggiornare (from HMI)
+ ///
+ public CmsError Write_IO_DO_ToPLC(Dictionary newValues)
+ {
+ // solo x S7...
+ if (NcConfig.NcVendor == NC_VENDOR.S7NET)
+ {
+ // scrivo!
+ CmsError libraryError = numericalControl.PLC_W_IO_DO_Val(newValues);
+ if (libraryError.IsError())
+ return libraryError;
+ }
+ else
+ {
+ return FUNCTION_NOT_ALLOWED_ERROR;
+ }
+ return NO_ERROR;
+ }
+ ///
+ /// ChannelsID: write AO to PLC (values + setForce)
+ ///
+ /// Oggetto parametri da aggiornare (from HMI)
+ ///
+ public CmsError Write_IO_AO_ToPLC(Dictionary newValues)
+ {
+ // solo x S7...
+ if (NcConfig.NcVendor == NC_VENDOR.S7NET)
+ {
+ // scrivo!
+ CmsError libraryError = numericalControl.PLC_W_IO_AO_Val(newValues);
+ if (libraryError.IsError())
+ return libraryError;
+ }
+ else
+ {
+ return FUNCTION_NOT_ALLOWED_ERROR;
+ }
+ return NO_ERROR;
+ }
+ ///
+ /// ChannelsID: Write RESET (not forced) for DO to PLC (setForce = false)
+ ///
+ /// Oggetto parametri da aggiornare (from HMI)
+ ///
+ public CmsError WriteReset_IO_DO_ToPLC(List channels)
+ {
+ // solo x S7...
+ if (NcConfig.NcVendor == NC_VENDOR.S7NET)
+ {
+ Dictionary newForced = new Dictionary();
+ foreach (var item in channels)
+ {
+ newForced.Add(item, false);
+ }
+ // scrivo!
+ CmsError libraryError = numericalControl.PLC_W_IO_DO_Reset(newForced);
+ if (libraryError.IsError())
+ return libraryError;
+ }
+ else
+ {
+ return FUNCTION_NOT_ALLOWED_ERROR;
+ }
+ return NO_ERROR;
+ }
+ ///
+ /// ChannelsID: Write RESET (not forced) for AO to PLC (setForce = false)
+ ///
+ /// Oggetto parametri da aggiornare (from HMI)
+ ///
+ public CmsError WriteReset_IO_AO_ToPLC(List channels)
+ {
+ // solo x S7...
+ if (NcConfig.NcVendor == NC_VENDOR.S7NET)
+ {
+ Dictionary newForced = new Dictionary();
+ foreach (var item in channels)
+ {
+ newForced.Add(item, false);
+ }
+ // scrivo!
+ CmsError libraryError = numericalControl.PLC_W_IO_AO_Reset(newForced);
+ if (libraryError.IsError())
+ return libraryError;
+ }
+ else
+ {
+ return FUNCTION_NOT_ALLOWED_ERROR;
+ }
+ return NO_ERROR;
+ }
+ ///
+ /// ChannelsID: Write RESET (not forced) for DO + AO to PLC (setForce = false)
+ ///
+ /// Oggetto parametri da aggiornare (from HMI)
+ /// num max parametri da scrivere singolarmente
+ /// delay in scrittura multi parametri singoli
+ ///
+ public CmsError WriteReset_IO_ALL_ToPLC()
+ {
+ // solo x S7...
+ if (NcConfig.NcVendor == NC_VENDOR.S7NET)
+ {
+ // scrivo!
+ CmsError libraryError = numericalControl.PLC_W_IO_ResetAll();
+ if (libraryError.IsError())
+ return libraryError;
+ }
+ else
+ {
+ return FUNCTION_NOT_ALLOWED_ERROR;
+ }
+ return NO_ERROR;
+ }
+
///
/// Scrive le softkey star
///
diff --git a/Thermo.Active.Utils/supportFunctions.cs b/Thermo.Active.Utils/supportFunctions.cs
index 3cd93d2f..faab6cce 100644
--- a/Thermo.Active.Utils/supportFunctions.cs
+++ b/Thermo.Active.Utils/supportFunctions.cs
@@ -100,6 +100,21 @@ namespace Thermo.Active.Utils
return answ;
}
///
+ /// Conversion string --> TACT_IO_TYPE
+ ///
+ ///
+ ///
+ public static TACT_IO_TYPE GetTActIO_Type(string strValue)
+ {
+ TACT_IO_TYPE answ = TACT_IO_TYPE.ND;
+ try
+ {
+ answ = (TACT_IO_TYPE)Enum.Parse(typeof(TACT_IO_TYPE), strValue);
+ }
+ catch { }
+ return answ;
+ }
+ ///
/// Conversion string --> TACT_MBLOCK_SECTION
///
///
diff --git a/Thermo.Active/App_Start/SwaggerConfig.cs b/Thermo.Active/App_Start/SwaggerConfig.cs
index fb0fe40a..704b5f02 100644
--- a/Thermo.Active/App_Start/SwaggerConfig.cs
+++ b/Thermo.Active/App_Start/SwaggerConfig.cs
@@ -1,6 +1,9 @@
using Swashbuckle.Application;
using Swashbuckle.Swagger;
+using System;
using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
using System.Web.Http;
using System.Web.Http.Description;
@@ -33,129 +36,132 @@ namespace Thermo.Active
//
c.SingleApiVersion("v1", "ThermoActive");
- // If you want the output Swagger docs to be indented properly, enable the "PrettyPrint" option.
- //
- //c.PrettyPrint();
+ // If you want the output Swagger docs to be indented properly, enable the "PrettyPrint" option.
+ //
+ //c.PrettyPrint();
- // If your API has multiple versions, use "MultipleApiVersions" instead of "SingleApiVersion".
- // In this case, you must provide a lambda that tells Swashbuckle which actions should be
- // included in the docs for a given API version. Like "SingleApiVersion", each call to "Version"
- // returns an "Info" builder so you can provide additional metadata per API version.
- //
- //c.MultipleApiVersions(
- // (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
- // (vc) =>
- // {
- // vc.Version("v2", "Swashbuckle Dummy API V2");
- // vc.Version("v1", "Swashbuckle Dummy API V1");
- // });
+ // If your API has multiple versions, use "MultipleApiVersions" instead of "SingleApiVersion".
+ // In this case, you must provide a lambda that tells Swashbuckle which actions should be
+ // included in the docs for a given API version. Like "SingleApiVersion", each call to "Version"
+ // returns an "Info" builder so you can provide additional metadata per API version.
+ //
+ //c.MultipleApiVersions(
+ // (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
+ // (vc) =>
+ // {
+ // vc.Version("v2", "Swashbuckle Dummy API V2");
+ // vc.Version("v1", "Swashbuckle Dummy API V1");
+ // });
- // You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API.
- // See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details.
- // NOTE: These only define the schemes and need to be coupled with a corresponding "security" property
- // at the document or operation level to indicate which schemes are required for an operation. To do this,
- // you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
- // according to your specific authorization implementation
- //
- //c.BasicAuth("basic")
- // .Description("Basic HTTP Authentication");
- //
- // NOTE: You must also configure 'EnableApiKeySupport' below in the SwaggerUI section
- //c.ApiKey("apiKey")
- // .Description("API Key Authentication")
- // .Name("apiKey")
- // .In("header");
- //
- //c.OAuth2("oauth2")
- // .Description("OAuth2 Implicit Grant")
- // .Flow("implicit")
- // .AuthorizationUrl("http://localhost:9000/token")
- // .TokenUrl("http://localhost:9000/token")
- // .Scopes(scopes =>
- // {
- // scopes.Add("read", "Read access to protected resources");
- // scopes.Add("write", "Write access to protected resources");
- // });
+ // You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API.
+ // See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details.
+ // NOTE: These only define the schemes and need to be coupled with a corresponding "security" property
+ // at the document or operation level to indicate which schemes are required for an operation. To do this,
+ // you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
+ // according to your specific authorization implementation
+ //
+ //c.BasicAuth("basic")
+ // .Description("Basic HTTP Authentication");
+ //
+ // NOTE: You must also configure 'EnableApiKeySupport' below in the SwaggerUI section
+ //c.ApiKey("apiKey")
+ // .Description("API Key Authentication")
+ // .Name("apiKey")
+ // .In("header");
+ //
+ //c.OAuth2("oauth2")
+ // .Description("OAuth2 Implicit Grant")
+ // .Flow("implicit")
+ // .AuthorizationUrl("http://localhost:9000/token")
+ // .TokenUrl("http://localhost:9000/token")
+ // .Scopes(scopes =>
+ // {
+ // scopes.Add("read", "Read access to protected resources");
+ // scopes.Add("write", "Write access to protected resources");
+ // });
- // Set this flag to omit descriptions for any actions decorated with the Obsolete attribute
- //c.IgnoreObsoleteActions();
+ // Set this flag to omit descriptions for any actions decorated with the Obsolete attribute
+ //c.IgnoreObsoleteActions();
- // Each operation be assigned one or more tags which are then used by consumers for various reasons.
- // For example, the swagger-ui groups operations according to the first tag of each operation.
- // By default, this will be controller name but you can use the "GroupActionsBy" option to
- // override with any value.
- //
- //c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());
+ // Each operation be assigned one or more tags which are then used by consumers for various reasons.
+ // For example, the swagger-ui groups operations according to the first tag of each operation.
+ // By default, this will be controller name but you can use the "GroupActionsBy" option to
+ // override with any value.
+ //
+ //c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());
- // You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate
- // the order in which operations are listed. For example, if the default grouping is in place
- // (controller name) and you specify a descending alphabetic sort order, then actions from a
- // ProductsController will be listed before those from a CustomersController. This is typically
- // used to customize the order of groupings in the swagger-ui.
- //
- //c.OrderActionGroupsBy(new DescendingAlphabeticComparer());
+ // You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate
+ // the order in which operations are listed. For example, if the default grouping is in place
+ // (controller name) and you specify a descending alphabetic sort order, then actions from a
+ // ProductsController will be listed before those from a CustomersController. This is typically
+ // used to customize the order of groupings in the swagger-ui.
+ //
+ //c.OrderActionGroupsBy(new DescendingAlphabeticComparer());
- // If you annotate Controllers and API Types with
- // Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx), you can incorporate
- // those comments into the generated docs and UI. You can enable this by providing the path to one or
- // more Xml comment files.
- //
- //c.IncludeXmlComments(GetXmlCommentsPath());
+ // If you annotate Controllers and API Types with
+ // Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx), you can incorporate
+ // those comments into the generated docs and UI. You can enable this by providing the path to one or
+ // more Xml comment files.
+ //
+ //c.IncludeXmlComments(GetXmlCommentsPath());
+ //var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
+ //var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
+ //c.IncludeXmlComments(xmlPath);
- // Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the various types
- // exposed in your API. However, there may be occasions when more control of the output is needed.
- // This is supported through the "MapType" and "SchemaFilter" options:
- //
- // Use the "MapType" option to override the Schema generation for a specific type.
- // It should be noted that the resulting Schema will be placed "inline" for any applicable Operations.
- // While Swagger 2.0 supports inline definitions for "all" Schema types, the swagger-ui tool does not.
- // It expects "complex" Schemas to be defined separately and referenced. For this reason, you should only
- // use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a
- // complex Schema, use a Schema filter.
- //
- //c.MapType(() => new Schema { type = "integer", format = "int32" });
+ // Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the various types
+ // exposed in your API. However, there may be occasions when more control of the output is needed.
+ // This is supported through the "MapType" and "SchemaFilter" options:
+ //
+ // Use the "MapType" option to override the Schema generation for a specific type.
+ // It should be noted that the resulting Schema will be placed "inline" for any applicable Operations.
+ // While Swagger 2.0 supports inline definitions for "all" Schema types, the swagger-ui tool does not.
+ // It expects "complex" Schemas to be defined separately and referenced. For this reason, you should only
+ // use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a
+ // complex Schema, use a Schema filter.
+ //
+ //c.MapType(() => new Schema { type = "integer", format = "int32" });
- // If you want to post-modify "complex" Schemas once they've been generated, across the board or for a
- // specific type, you can wire up one or more Schema filters.
- //
- //c.SchemaFilter();
+ // If you want to post-modify "complex" Schemas once they've been generated, across the board or for a
+ // specific type, you can wire up one or more Schema filters.
+ //
+ //c.SchemaFilter();
- // In a Swagger 2.0 document, complex types are typically declared globally and referenced by unique
- // Schema Id. By default, Swashbuckle does NOT use the full type name in Schema Ids. In most cases, this
- // works well because it prevents the "implementation detail" of type namespaces from leaking into your
- // Swagger docs and UI. However, if you have multiple types in your API with the same class name, you'll
- // need to opt out of this behavior to avoid Schema Id conflicts.
- //
- //c.UseFullTypeNameInSchemaIds();
+ // In a Swagger 2.0 document, complex types are typically declared globally and referenced by unique
+ // Schema Id. By default, Swashbuckle does NOT use the full type name in Schema Ids. In most cases, this
+ // works well because it prevents the "implementation detail" of type namespaces from leaking into your
+ // Swagger docs and UI. However, if you have multiple types in your API with the same class name, you'll
+ // need to opt out of this behavior to avoid Schema Id conflicts.
+ //
+ //c.UseFullTypeNameInSchemaIds();
- // Alternatively, you can provide your own custom strategy for inferring SchemaId's for
- // describing "complex" types in your API.
- //
- //c.SchemaId(t => t.FullName.Contains('`') ? t.FullName.Substring(0, t.FullName.IndexOf('`')) : t.FullName);
+ // Alternatively, you can provide your own custom strategy for inferring SchemaId's for
+ // describing "complex" types in your API.
+ //
+ //c.SchemaId(t => t.FullName.Contains('`') ? t.FullName.Substring(0, t.FullName.IndexOf('`')) : t.FullName);
- // Set this flag to omit schema property descriptions for any type properties decorated with the
- // Obsolete attribute
- //c.IgnoreObsoleteProperties();
+ // Set this flag to omit schema property descriptions for any type properties decorated with the
+ // Obsolete attribute
+ //c.IgnoreObsoleteProperties();
- // In accordance with the built in JsonSerializer, Swashbuckle will, by default, describe enums as integers.
- // You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given
- // enum type. Swashbuckle will honor this change out-of-the-box. However, if you use a different
- // approach to serialize enums as strings, you can also force Swashbuckle to describe them as strings.
- //
- //c.DescribeAllEnumsAsStrings();
+ // In accordance with the built in JsonSerializer, Swashbuckle will, by default, describe enums as integers.
+ // You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given
+ // enum type. Swashbuckle will honor this change out-of-the-box. However, if you use a different
+ // approach to serialize enums as strings, you can also force Swashbuckle to describe them as strings.
+ //
+ //c.DescribeAllEnumsAsStrings();
- // Similar to Schema filters, Swashbuckle also supports Operation and Document filters:
- //
- // Post-modify Operation descriptions once they've been generated by wiring up one or more
- // Operation filters.
- //
- //c.OperationFilter();
- //
- // If you've defined an OAuth2 flow as described above, you could use a custom filter
- // to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required
- // to execute the operation
- //
- c.OperationFilter(() => new AddRequiredHeaderParameter());
+ // Similar to Schema filters, Swashbuckle also supports Operation and Document filters:
+ //
+ // Post-modify Operation descriptions once they've been generated by wiring up one or more
+ // Operation filters.
+ //
+ //c.OperationFilter();
+ //
+ // If you've defined an OAuth2 flow as described above, you could use a custom filter
+ // to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required
+ // to execute the operation
+ //
+ c.OperationFilter(() => new AddRequiredHeaderParameter());
// Post-modify the entire Swagger document by wiring up one or more Document filters.
// This gives full control to modify the final SwaggerDocument. You should have a good understanding of
diff --git a/Thermo.Active/Controllers/WebApi/ConfigurationController.cs b/Thermo.Active/Controllers/WebApi/ConfigurationController.cs
index 10ae29d5..35f08dbe 100644
--- a/Thermo.Active/Controllers/WebApi/ConfigurationController.cs
+++ b/Thermo.Active/Controllers/WebApi/ConfigurationController.cs
@@ -5,6 +5,7 @@ using Thermo.Active.Database.Controllers;
using Thermo.Active.Model.ConfigModels;
using Thermo.Active.Model.DTOModels;
using Thermo.Active.Model.DTOModels.AlarmModels;
+using Thermo.Active.Model.DTOModels.ThIO;
using Thermo.Active.Model.DTOModels.ThProd;
using Thermo.Active.Model.DTOModels.ThRecipe;
using static Thermo.Active.Config.ServerConfig;
@@ -124,6 +125,27 @@ namespace Thermo.Active.Controllers.WebApi
return Ok(recipeConfig);
}
+ [Route("configIO"), HttpGet]
+ public IHttpActionResult GetIOConfig()
+ {
+ // restituisce la configurazione come item dei banchi DI/DO/AI/AO
+ DTOChannelsSetup configIO = new DTOChannelsSetup();
+ // leggo i 4 tipi di oggetti e popolo
+ List listDI = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.DI).GroupBy(x => x.Bank).Select(x => x.Key).ToList();
+ List listDO = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.DO).GroupBy(x => x.Bank).Select(x => x.Key).ToList();
+ List listAI = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.AI).GroupBy(x => x.Bank).Select(x => x.Key).ToList();
+ List listAO = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.AO).GroupBy(x => x.Bank).Select(x => x.Key).ToList();
+
+ // assegno!
+ configIO.DI = listDI;
+ configIO.DO = listDO;
+ configIO.AI = listAI;
+ configIO.AO = listAO;
+
+ // restituisco
+ return Ok(configIO);
+ }
+
[Route("thermoProd"), HttpGet]
public IHttpActionResult GetThermoProdConfig()
{
diff --git a/Thermo.Active/Controllers/WebApi/ThermocameraController.cs b/Thermo.Active/Controllers/WebApi/ThermocameraController.cs
index 87fa7be3..2738f8c9 100644
--- a/Thermo.Active/Controllers/WebApi/ThermocameraController.cs
+++ b/Thermo.Active/Controllers/WebApi/ThermocameraController.cs
@@ -24,7 +24,7 @@ namespace Thermo.Active.Controllers.WebApi
public class ThermocameraController : ApiController
{
[Route("show"), HttpPost]
- public IHttpActionResult GetDataPaginated()
+ public IHttpActionResult showCamera()
{
String ThermoCameraXpos = AdditionalParametersConfig["ThermoCameraXpos"];
String ThermoCameraYpos = AdditionalParametersConfig["ThermoCameraYpos"];
diff --git a/Thermo.Active/Controllers/WebApi/UnderTheHoodController.cs b/Thermo.Active/Controllers/WebApi/UnderTheHoodController.cs
new file mode 100644
index 00000000..04f40792
--- /dev/null
+++ b/Thermo.Active/Controllers/WebApi/UnderTheHoodController.cs
@@ -0,0 +1,278 @@
+using CMS_CORE_Library.Models;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Security.Claims;
+using System.Threading.Tasks;
+using System.Web;
+using System.Web.Http;
+using System.Web.Http.Description;
+using System.Windows.Media.Animation;
+using TeamDev.SDK.MVVM;
+using Thermo.Active.Config;
+using Thermo.Active.Database.Controllers;
+using Thermo.Active.Model.DTOModels;
+using Thermo.Active.Model.DTOModels.ThIO;
+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;
+
+namespace Thermo.Active.Controllers.WebApi
+{
+ [RoutePrefix("api/underthehood")]
+ public class UnderTheHoodController : ApiController
+ {
+ ///
+ /// Oggetto adapter condiviso da WebAPI
+ ///
+ protected static NcAdapter ncAdapter = new NcAdapter();
+
+ [ResponseType(typeof(DTOCycleLog))]
+ [Route("cyclelog"), HttpGet]
+ public IHttpActionResult GetCycleLog()
+ {
+ // // Try connection
+ CmsError libraryError = ncAdapter.Connect();
+ DTOCycleLog currCycleLog = new DTOCycleLog();
+
+ if (libraryError.IsError())
+ {
+ ThermoActiveLogger.LogError($"ncAdapter Not connected! | GetCycleLog | {libraryError.exception}");
+ }
+
+ libraryError = ncAdapter.GetCycleLog(out Dictionary cycleLog);
+ foreach (var item in cycleLog)
+ {
+ currCycleLog.events.Add(new CycleEvent() { dtEvent=item.Key, code=item.Value });
+ }
+
+ if (libraryError.IsError())
+ {
+ ThermoActiveLogger.LogError($"GetCycleLog error | {libraryError.exception}");
+ return BadRequest(libraryError.localizationKey);
+ }
+
+ return Ok(currCycleLog);
+ }
+
+ [ResponseType(typeof(DTOChannelsIO))]
+ [Route("channels_io"), HttpGet]
+ public IHttpActionResult GetChannelsIO()
+ {
+ // Try connection
+ CmsError libraryError = ncAdapter.Connect();
+ if (libraryError.IsError())
+ {
+ ThermoActiveLogger.LogError($"NC Not connected! | GetChannelsIO | {libraryError.exception}");
+ return BadRequest(libraryError.localizationKey);
+ }
+
+ // leggo dati gauges
+ libraryError = ncAdapter.ReadFullIO(out DTOChannelsIO ChannelsIO);
+ if (libraryError.IsError())
+ {
+ ThermoActiveLogger.LogError($"GetChannelsIO error | {libraryError.exception}");
+ return BadRequest(libraryError.localizationKey);
+ }
+
+ // ritorno!
+ return Ok(ChannelsIO);
+ }
+
+ [ResponseType(typeof(DTOChannelsIOVal))]
+ [Route("channels_io_val"), HttpGet]
+ public IHttpActionResult GetChannelsIoVal()
+ {
+ // Try connection
+ CmsError libraryError = ncAdapter.Connect();
+ if (libraryError.IsError())
+ {
+ ThermoActiveLogger.LogError($"NC Not connected! | GetChannelsIoVal | {libraryError.exception}");
+ return BadRequest(libraryError.localizationKey);
+ }
+
+ // leggo dati gauges
+ libraryError = ncAdapter.ReadValIO(out DTOChannelsIOVal ChannelsIOVal);
+ if (libraryError.IsError())
+ {
+ ThermoActiveLogger.LogError($"GetChannelsIoVal error | {libraryError.exception}");
+ return BadRequest(libraryError.localizationKey);
+ }
+
+ // ritorno!
+ return Ok(ChannelsIOVal);
+ }
+
+ [Route("io_force_ch_do"), HttpPut]
+ [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.MAINTENANCE, Action = ACTIONS.WRITE)]
+ public IHttpActionResult ForceChDO(List updVal)
+ {
+ if (updVal != null)
+ {
+ // Try connection
+ CmsError libraryError = ncAdapter.Connect();
+ if (libraryError.IsError())
+ {
+ ThermoActiveLogger.LogError($"NC Not connected! | ForceChDO | {libraryError.exception}");
+ return InternalServerError();
+ }
+
+ if (updVal.Count > 0)
+ {
+ // converto
+ Dictionary parametersList = new Dictionary();
+ foreach (var item in updVal)
+ {
+ parametersList.Add(item.Id, item.value);
+ }
+
+ // scrivo sul PLC con i parametri specificati
+ ncAdapter.Write_IO_DO_ToPLC(parametersList);
+ }
+
+ // ritorno solo fatto!
+ return Ok();
+ }
+ else
+ {
+ ThermoActiveLogger.LogError($"ForceChDO updatedVal null | Empty Parameters");
+ return BadRequest();
+ }
+ }
+ [Route("io_force_ch_ao"), HttpPut]
+ [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.MAINTENANCE, Action = ACTIONS.WRITE)]
+ public IHttpActionResult ForceChAO(List updVal)
+ {
+ if (updVal != null)
+ {
+ // Try connection
+ CmsError libraryError = ncAdapter.Connect();
+ if (libraryError.IsError())
+ {
+ ThermoActiveLogger.LogError($"NC Not connected! | ForceChAO | {libraryError.exception}");
+ return InternalServerError();
+ }
+
+ if (updVal.Count > 0)
+ {
+ Dictionary parametersList = new Dictionary();
+ foreach (var item in updVal)
+ {
+ parametersList.Add(item.Id, item.value);
+ }
+
+ // scrivo sul PLC con i parametri specificati
+ ncAdapter.Write_IO_AO_ToPLC(parametersList);
+ }
+
+ // ritorno solo fatto!
+ return Ok();
+ }
+ else
+ {
+ ThermoActiveLogger.LogError($"ForceChAO parametersList null | Empty Parameters");
+ return BadRequest();
+ }
+ }
+ [Route("io_reset_ch_do"), HttpPut]
+ [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.MAINTENANCE, Action = ACTIONS.WRITE)]
+ public IHttpActionResult ResetChDO(List parametersList)
+ {
+ if (parametersList != null)
+ {
+ // Try connection
+ CmsError libraryError = ncAdapter.Connect();
+ if (libraryError.IsError())
+ {
+ ThermoActiveLogger.LogError($"NC Not connected! | ResetChDO | {libraryError.exception}");
+ return InternalServerError();
+ }
+
+ if (parametersList.Count > 0)
+ {
+ // scrivo sul PLC con i parametri specificati x ritardo/raggruppamento
+ ncAdapter.WriteReset_IO_DO_ToPLC(parametersList);
+ }
+
+ // ritorno solo fatto!
+ return Ok();
+ }
+ else
+ {
+ ThermoActiveLogger.LogError($"ResetChDO parametersList null | Empty Parameters");
+ return BadRequest();
+ }
+ }
+ ///
+ /// Reset "force bit" on selected channels
+ ///
+ /// List of channels index, zero based
+ ///
+ [Route("io_reset_ch_ao"), HttpPut]
+ [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.MAINTENANCE, Action = ACTIONS.WRITE)]
+ public IHttpActionResult ResetChAO(List parametersList)
+ {
+ if (parametersList != null)
+ {
+ // Try connection
+ CmsError libraryError = ncAdapter.Connect();
+ if (libraryError.IsError())
+ {
+ ThermoActiveLogger.LogError($"NC Not connected! | ResetChAO | {libraryError.exception}");
+ return InternalServerError();
+ }
+
+ if (parametersList.Count > 0)
+ {
+ // scrivo sul PLC con i parametri specificati x ritardo/raggruppamento
+ ncAdapter.WriteReset_IO_AO_ToPLC(parametersList);
+ }
+
+ // ritorno solo fatto!
+ return Ok();
+ }
+ else
+ {
+ ThermoActiveLogger.LogError($"ResetChAO parametersList null | Empty Parameters");
+ return BadRequest();
+ }
+ }
+ [Route("io_reset_all_ch"), HttpPut]
+ [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.MAINTENANCE, Action = ACTIONS.WRITE)]
+ public IHttpActionResult ResetAllCh()
+ {
+ // Try connection
+ CmsError libraryError = ncAdapter.Connect();
+ if (libraryError.IsError())
+ {
+ ThermoActiveLogger.LogError($"NC Not connected! | ResetAllCh | {libraryError.exception}");
+ return InternalServerError();
+ }
+
+ // scrivo sul PLC con i parametri specificati x ritardo/raggruppamento
+ ncAdapter.WriteReset_IO_ALL_ToPLC();//parametersList);
+
+ // ritorno solo fatto!
+ return Ok();
+ }
+
+ [Route("io_sample_fast"), HttpPut]
+ [WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.MAINTENANCE, Action = ACTIONS.WRITE)]
+ public IHttpActionResult SetFastSample(bool value)
+ {
+ // imposta (su redis) campionamento RAPIDO/lento x IO...
+ RedisController.FastIoSample = value;
+
+ // ritorno solo fatto!
+ return Ok();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Thermo.Active/Listeners/ListenersHandler.cs b/Thermo.Active/Listeners/ListenersHandler.cs
index ec75eaa5..f9b7a02e 100644
--- a/Thermo.Active/Listeners/ListenersHandler.cs
+++ b/Thermo.Active/Listeners/ListenersHandler.cs
@@ -64,6 +64,10 @@ namespace Thermo.Active.Listeners
{
SignalRListener.SendThermoAxisInfoData(a);
}));
+ infos.Add(MessageServices.Current.Subscribe(SEND_CHANNELS_IO_DATA, (a, b) =>
+ {
+ SignalRListener.SendThermoChannelsIoData(a);
+ }));
infos.Add(MessageServices.Current.Subscribe(SEND_ACTIVE_PROGRAM_DATA, (a, b) =>
{
SignalRListener.SendActiveProgramData(a);
diff --git a/Thermo.Active/Listeners/SignalR/SignalRListener.cs b/Thermo.Active/Listeners/SignalR/SignalRListener.cs
index e0029ecb..bb86d9d1 100644
--- a/Thermo.Active/Listeners/SignalR/SignalRListener.cs
+++ b/Thermo.Active/Listeners/SignalR/SignalRListener.cs
@@ -13,6 +13,7 @@ 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.ThIO;
using Thermo.Active.Model.DTOModels.ThModules;
using Thermo.Active.Model.DTOModels.ThProd;
using Thermo.Active.Model.DTOModels.ThRecipe;
@@ -59,7 +60,7 @@ namespace Thermo.Active.Listeners.SignalR
{
RedisController.WriteCurrentMachineEmergencyPath(LastPowerOnData.PrePowerOn.EmergencyButtons.Active);
}
-
+
}
}
@@ -456,8 +457,8 @@ namespace Thermo.Active.Listeners.SignalR
LastProdPanelData = currProdPanel;
var context = GlobalHost.ConnectionManager.GetHubContext();
- context.Clients.Group("ncData").prodPanelData(currProdPanel);
-
+ context.Clients.Group("ncData").prodPanelData(currProdPanel);
+
if (Config.ServerConfig.ServerStartupConfig.CmsConnectReady)
{
if (newPiece)
@@ -508,8 +509,8 @@ 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));
+ RedisController.WriteCurrentProcessStatus(1, CMSConnectConstants.ConvertThermoToConnectProcessStatus(currProdCycle.Status));
+ RedisController.WriteCurrentProcessMode(1, CMSConnectConstants.ConvertThermoToConnectProcessMode(currProdCycle.Mode));
}
@@ -551,6 +552,65 @@ namespace Thermo.Active.Listeners.SignalR
}
}
+ public static void SendThermoChannelsIoData(object channelsIoData)
+ {
+ DTOChannelsIOVal currChannelsIoData = channelsIoData as DTOChannelsIOVal;
+ DTOChannelsIOVal diffChannelsData = new DTOChannelsIOVal();
+
+ // processing differenze DI
+ foreach (var item in currChannelsIoData.DI)
+ {
+ // recupero
+ var element = LastChannelsIoData.DI.Find(x => x.Id == item.Id);
+ if ((element == null) || (!item.Value.Equals(element.Value)))
+ {
+ diffChannelsData.DI.Add(item);
+ }
+ }
+ // processing differenze DO
+ foreach (var item in currChannelsIoData.DO)
+ {
+ // recupero
+ var element = LastChannelsIoData.DO.Find(x => x.Id == item.Id);
+ if ((element == null) || (!item.Value.Equals(element.Value)))
+ {
+ diffChannelsData.DO.Add(item);
+ }
+ }
+ // processing differenze AI
+ foreach (var item in currChannelsIoData.AI)
+ {
+ // recupero
+ var element = LastChannelsIoData.AI.Find(x => x.Id == item.Id);
+ if ((element == null) || (!item.Value.Equals(element.Value)))
+ {
+ diffChannelsData.AI.Add(item);
+ }
+ }
+ // processing differenze AO
+ foreach (var item in currChannelsIoData.AO)
+ {
+ // recupero
+ var element = LastChannelsIoData.AO.Find(x => x.Id == item.Id);
+ if ((element == null) || (!item.Value.Equals(element.Value)))
+ {
+ diffChannelsData.AO.Add(item);
+ }
+ }
+
+ // se ho differenze invio!
+ if (diffChannelsData.DI.Count + diffChannelsData.DO.Count + diffChannelsData.AI.Count + diffChannelsData.AO.Count > 0)
+ {
+ // salvo update CLONANDO
+ LastChannelsIoData.DI = currChannelsIoData.DI;
+ LastChannelsIoData.DO = currChannelsIoData.DO;
+ LastChannelsIoData.AI = currChannelsIoData.AI;
+ LastChannelsIoData.AO = currChannelsIoData.AO;
+ var context = GlobalHost.ConnectionManager.GetHubContext();
+ context.Clients.Group("ncData").channelsIoVal(diffChannelsData);
+ }
+ }
+
public static void SetGatewayRebootStatus(object status)
{
string msg = status.ToString();
diff --git a/Thermo.Active/Listeners/SignalRStaticObjects.cs b/Thermo.Active/Listeners/SignalRStaticObjects.cs
index df07bf23..82d3e34f 100644
--- a/Thermo.Active/Listeners/SignalRStaticObjects.cs
+++ b/Thermo.Active/Listeners/SignalRStaticObjects.cs
@@ -1,9 +1,11 @@
using CMS_CORE_Library.Models;
+using System;
using System.Collections.Generic;
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.ThIO;
using Thermo.Active.Model.DTOModels.ThModules;
using Thermo.Active.Model.DTOModels.ThProd;
using Thermo.Active.Model.DTOModels.ThRecipe;
@@ -46,6 +48,8 @@ namespace Thermo.Active.Listeners
public static DTOThermoPanelProd LastProdPanelData = new DTOThermoPanelProd();
// Oggetti per assi THERMO
public static Dictionary LastAxisInfoData = new Dictionary();
+ // Oggetti x Valori Channels IO
+ public static DTOChannelsIOVal LastChannelsIoData = new DTOChannelsIOVal();
public static bool LastIsNcConnected = false;
}
diff --git a/Thermo.Active/Properties/AssemblyInfo.cs b/Thermo.Active/Properties/AssemblyInfo.cs
index be6f7282..5f2eb65b 100644
--- a/Thermo.Active/Properties/AssemblyInfo.cs
+++ b/Thermo.Active/Properties/AssemblyInfo.cs
@@ -1,4 +1,4 @@
-using System.Reflection;
+using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
@@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("CMS S.P.A.")]
[assembly: AssemblyProduct("Thermo Active Server")]
-[assembly: AssemblyCopyright("Copyright © 2020")]
+[assembly: AssemblyCopyright("Copyright � 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
-[assembly: AssemblyVersion("0.110.146")]
+[assembly: AssemblyVersion("1.1.157")]
diff --git a/Thermo.Active/Thermo.Active.csproj b/Thermo.Active/Thermo.Active.csproj
index 853d2397..0e2f0e06 100644
--- a/Thermo.Active/Thermo.Active.csproj
+++ b/Thermo.Active/Thermo.Active.csproj
@@ -223,6 +223,7 @@
+
diff --git a/UpgradeLog.htm b/UpgradeLog.htm
new file mode 100644
index 00000000..864f6498
Binary files /dev/null and b/UpgradeLog.htm differ