Merge remote-tracking branch 'CMS/develop' into develop

This commit is contained in:
=
2021-02-05 17:45:29 +01:00
29 changed files with 1704 additions and 135 deletions
+229
View File
@@ -0,0 +1,229 @@
<?xml version="1.0" encoding="UTF-8"?>
<IOSetup>
<parameter>
<id>0</id>
<category>DI</category>
<bank>0</bank>
<position>0</position>
<page>301</page>
<wire>404</wire>
<profinet>A32.3</profinet>
</parameter>
<parameter>
<id>1</id>
<category>DI</category>
<bank>0</bank>
<position>1</position>
<page>301</page>
<wire>405</wire>
<profinet>A32.5</profinet>
<disableForce>true</disableForce>
</parameter>
<parameter>
<id>2</id>
<category>DI</category>
<bank>0</bank>
<position>2</position>
<page>301</page>
<wire>406</wire>
<profinet>A32.7</profinet>
</parameter>
<parameter>
<id>3</id>
<category>DI</category>
<bank>0</bank>
<position>3</position>
<page>301</page>
<wire>407</wire>
<profinet>A32.8</profinet>
</parameter>
<parameter>
<id>4</id>
<category>DI</category>
<bank>0</bank>
<position>4</position>
<page>301</page>
<wire>408</wire>
<profinet>A32.1</profinet>
</parameter>
<parameter>
<id>5</id>
<category>AI</category>
<bank>0</bank>
<position>5</position>
<page>301</page>
<wire>409</wire>
<profinet>A32.2</profinet>
</parameter>
<parameter>
<id>6</id>
<category>DI</category>
<bank>0</bank>
<position>6</position>
<page>301</page>
<wire>210</wire>
<profinet>A32.4</profinet>
</parameter>
<parameter>
<id>7</id>
<category>DI</category>
<bank>0</bank>
<position>7</position>
<page>301</page>
<wire>211</wire>
<profinet>A32.6</profinet>
</parameter>
<parameter>
<id>0</id>
<category>DO</category>
<bank>0</bank>
<position>0</position>
<page>301</page>
<wire>404</wire>
<profinet>B43.3</profinet>
</parameter>
<parameter>
<id>1</id>
<category>DO</category>
<bank>0</bank>
<position>1</position>
<page>301</page>
<wire>405</wire>
<profinet>B43.5</profinet>
</parameter>
<parameter>
<id>2</id>
<category>DO</category>
<bank>0</bank>
<position>2</position>
<page>301</page>
<wire>406</wire>
<profinet>B43.7</profinet>
</parameter>
<parameter>
<id>3</id>
<category>DO</category>
<bank>0</bank>
<position>3</position>
<page>301</page>
<wire>407</wire>
<profinet>B43.8</profinet>
</parameter>
<parameter>
<id>4</id>
<category>DO</category>
<bank>0</bank>
<position>4</position>
<page>301</page>
<wire>408</wire>
<profinet>B43.1</profinet>
</parameter>
<parameter>
<id>21</id>
<category>DO</category>
<bank>1</bank>
<position>5</position>
<page>301</page>
<wire>409</wire>
<profinet>B43.2</profinet>
</parameter>
<parameter>
<id>22</id>
<category>DO</category>
<bank>1</bank>
<position>6</position>
<page>301</page>
<wire>210</wire>
<profinet>B43.4</profinet>
</parameter>
<parameter>
<id>23</id>
<category>DO</category>
<bank>1</bank>
<position>7</position>
<page>301</page>
<wire>211</wire>
<profinet>B43.6</profinet>
</parameter>
<parameter>
<id>0</id>
<category>AI</category>
<bank>0</bank>
<position>0</position>
<page>511</page>
<wire>614</wire>
<profinet>C43.23</profinet>
</parameter>
<parameter>
<id>1</id>
<category>AI</category>
<bank>0</bank>
<position>1</position>
<page>511</page>
<wire>615</wire>
<profinet>C43.25</profinet>
</parameter>
<parameter>
<id>16</id>
<category>AI</category>
<bank>2</bank>
<position>0</position>
<page>501</page>
<wire>604</wire>
<profinet>C43.3</profinet>
</parameter>
<parameter>
<id>17</id>
<category>AI</category>
<bank>2</bank>
<position>1</position>
<page>501</page>
<wire>605</wire>
<profinet>C43.5</profinet>
</parameter>
<parameter>
<id>0</id>
<category>AO</category>
<bank>0</bank>
<position>0</position>
<page>700</page>
<wire>800</wire>
<profinet>D43.13</profinet>
</parameter>
<parameter>
<id>1</id>
<category>AO</category>
<bank>0</bank>
<position>1</position>
<page>701</page>
<wire>801</wire>
<profinet>D43.14</profinet>
</parameter>
<parameter>
<id>2</id>
<category>AO</category>
<bank>0</bank>
<position>2</position>
<page>702</page>
<wire>802</wire>
<profinet>D43.15</profinet>
</parameter>
<parameter>
<id>16</id>
<category>AO</category>
<bank>3</bank>
<position>0</position>
<page>701</page>
<wire>804</wire>
<profinet>D43.3</profinet>
</parameter>
<parameter>
<id>31</id>
<category>AO</category>
<bank>4</bank>
<position>15</position>
<page>701</page>
<wire>805</wire>
<profinet>D43.5</profinet>
</parameter>
</IOSetup>
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="IOSetup">
<!-- Heads -->
<xs:complexType>
<xs:sequence>
<xs:element name="parameter" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:element name="id" type="xs:int"/>
<xs:element name="category" type="io_type" />
<xs:element name="bank" type="xs:string" />
<xs:element name="position" type="xs:string" />
<xs:element name="page" type="xs:string" />
<xs:element name="wire" type="xs:string" />
<xs:element name="profinet" type="xs:string" />
<xs:element name="disableForce" type ="xs:boolean" minOccurs="0" />
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- Head Type -->
<xs:simpleType name="io_type" final="restriction">
<xs:restriction base="xs:string">
<xs:enumeration value="DI" />
<xs:enumeration value="DO" />
<xs:enumeration value="AI"/>
<xs:enumeration value="AO"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
+3 -1
View File
@@ -4,7 +4,7 @@
<ncVendor>S7NET</ncVendor>
<!-- NO_NC/DEMO/FANUC/SIEMENS/OSAI/S7NET -->
<showNcHMI>false</showNcHMI>
<ncIpAddress>192.168.0.1</ncIpAddress>
<ncIpAddress>192.168.0.102</ncIpAddress>
<ncPort>102</ncPort>
<machineModel>Thermo 2020</machineModel>
<sharedPath>C:\CMS\Recipes\</sharedPath>
@@ -119,6 +119,8 @@
<sampling>
<thread name="alarms" value="200" />
<thread name="axis" value="200" />
<thread name="channelsIoFast" value="300" />
<thread name="channelsIoSlow" value="5000" />
<thread name="area" value="500" />
<thread name="confReq" value="2000" />
<thread name="expMan" value="30000" />
+1
View File
@@ -61,6 +61,7 @@ namespace Thermo.Active.Config
public static List<ThermoProdConfigModel> ThermoProdConfig;
public static List<RecipeConfigModel> RecipeConfig;
public static List<ModBlockConfigModel> ModBlockConfig;
public static List<IOConfigModel> IOConfig;
public static List<RiskResistModel> RiskResistConfig;
public static List<RiskChannelModel> RiskChannelConfig;
public static List<RiskBoardModel> RiskBoardConfig;
@@ -326,6 +326,7 @@ namespace Thermo.Active.Config
ReadThermoProdConfig();
ReadRecipeConfig();
ReadModBlockConfig();
ReadIOConfig();
ReadRiskConfig();
ReadAxesConfig();
ReadCMSConnectConfig();
@@ -499,6 +500,30 @@ namespace Thermo.Active.Config
.ToList();
}
/// <summary>
/// IO config setup from file
/// </summary>
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);
@@ -65,6 +65,9 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServerConfig.cs" />
<Compile Include="ServerConfigController.cs" />
<Content Include="Config\IOConfig.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Config\thermoProdConfig.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -215,6 +218,10 @@
<SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="Config\IOConfigValidator.xsd">
<SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<None Include="Config\Recipes\template.tpl">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
+50
View File
@@ -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();
}
}
/// <summary>
/// Lettura valorichannelsIO
/// </summary>
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()
{
+1
View File
@@ -36,6 +36,7 @@ namespace Thermo.Active.Core
ThreadsFunctions.ReadScadaData,
ThreadsFunctions.ReadMComandsData,
ThreadsFunctions.ReadAxisInfoData,
ThreadsFunctions.ReadChannelsIoData,
ThreadsFunctions.ReadM154Data // levare?
};
@@ -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<string, string> entries)
{
foreach (KeyValuePair<string,string> entry in entries)
foreach (KeyValuePair<string, string> 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<int, DTOAxisInfoModel> axis)
{
foreach(KeyValuePair<int, DTOAxisInfoModel> asse in axis)
foreach (KeyValuePair<int, DTOAxisInfoModel> 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;
}
@@ -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;
}
}
}
}
+24
View File
@@ -98,6 +98,26 @@ namespace Thermo.Active.Model
Options
}
public enum TACT_IO_TYPE
{
ND = 0,
/// <summary>
/// Digital IN
/// </summary>
DI,
/// <summary>
/// Digital OUT
/// </summary>
DO,
/// <summary>
/// Analog IN
/// </summary>
AI,
/// <summary>
/// Analog OUT
/// </summary>
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";
@@ -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<DigitalIN> DI { get; set; } = new List<DigitalIN>();
public List<DigitalOUT> DO { get; set; } = new List<DigitalOUT>();
public List<AnalogIN> AI { get; set; } = new List<AnalogIN>();
public List<AnalogOUT> AO { get; set; } = new List<AnalogOUT>();
}
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);
}
/// <summary>
/// Hash gen
/// </summary>
/// <returns></returns>
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);
}
/// <summary>
/// Hash gen
/// </summary>
/// <returns></returns>
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);
}
/// <summary>
/// Hash gen
/// </summary>
/// <returns></returns>
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);
}
/// <summary>
/// Hash gen
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}
@@ -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<DigInVal> DI { get; set; } = new List<DigInVal>();
public List<DigOutVal> DO { get; set; } = new List<DigOutVal>();
public List<AnalInVal> AI { get; set; } = new List<AnalInVal>();
public List<AnalOutVal> AO { get; set; } = new List<AnalOutVal>();
}
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);
}
/// <summary>
/// Hash gen
/// </summary>
/// <returns></returns>
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);
}
/// <summary>
/// Hash gen
/// </summary>
/// <returns></returns>
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);
}
/// <summary>
/// Hash gen
/// </summary>
/// <returns></returns>
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);
}
/// <summary>
/// Hash gen
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}
@@ -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<string> DI { get; set; } = new List<string>();
public List<string> DO { get; set; } = new List<string>();
public List<string> AI { get; set; } = new List<string>();
public List<string> AO { get; set; } = new List<string>();
}
}
@@ -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<CycleEvent> events { get; set; } = new List<CycleEvent>();
}
public class CycleEvent
{
public DateTime dtEvent { get; set; }
public int code { get; set; } = 0;
}
}
@@ -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;
}
/// <summary>
/// Hash gen
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}
@@ -66,6 +66,7 @@
<Compile Include="ConfigModels\ExtSoftwareModel.cs" />
<Compile Include="ConfigModels\InputOperatorConfigModel.cs" />
<Compile Include="ConfigModels\AxesConfigModel.cs" />
<Compile Include="ConfigModels\IOConfigModel.cs" />
<Compile Include="ConfigModels\ThermoProdConfigModel.cs" />
<Compile Include="ConfigModels\ModBlockConfigModel.cs" />
<Compile Include="ConfigModels\RiskConfigModel.cs" />
@@ -112,6 +113,11 @@
<Compile Include="DTOModels\DTOM156InputModel.cs" />
<Compile Include="DTOModels\DTOMessageModel.cs" />
<Compile Include="DTOModels\ThAxes\DTOAxisInfoModel.cs" />
<Compile Include="DTOModels\ThIO\DTOChannelsIOVal.cs" />
<Compile Include="DTOModels\ThIO\DTOCycleLog.cs" />
<Compile Include="DTOModels\ThIO\DTOChannelsSetup.cs" />
<Compile Include="DTOModels\ThIO\DTOChannelsIO.cs" />
<Compile Include="DTOModels\ThIO\IoItemConf.cs" />
<Compile Include="DTOModels\ThModules\DTOModulesBlock.cs" />
<Compile Include="DTOModels\ThProd\DTOProdInfo.cs" />
<Compile Include="DTOModels\ThProd\DTOThermoPanelProd.cs" />
+398 -2
View File
@@ -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;
}
/// <summary>
/// Legge dal PLC elenco di eventi LOG del ciclo e li presenta
/// </summary>
/// <param name="machineLog">Oggetto elenco elementi LOG registrati da macchina</param>
/// <returns></returns>
public CmsError GetCycleLog(out Dictionary<DateTime, int> machineLog)
{
CmsError libraryError = NO_ERROR;
machineLog = new Dictionary<DateTime, int>();
if (false)
{
// recupero l'oggetto dall'NC
// effettuo traduzione
#if false
// overview di base: ultima salvata...
var err2fix = new Dictionary<RecipeSection, RecipeCatStatus>();
// leggo la ricetta dal PLC!
var currRecipe = new Dictionary<string, DTORecipeParam>();
libraryError = ReadFullRecipe(out currRecipe);
if (libraryError.IsError())
return libraryError;
// leggo l'intero array delle DB... QUI FAKE sulle DB configurate...
List<DTORecipeConfigModel> 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;
}
/// <summary>
/// Legge tutti i parametri della ricetta e calcolo la overview dei vari steps
/// </summary>
@@ -2038,6 +2167,154 @@ namespace Thermo.Active.NC
}
return libraryError;
}
/// <summary>
/// Restituisce intero set dati IO Channels (conf + valori)
/// </summary>
/// <param name="currChannelsIO"></param>
/// <returns></returns>
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<int, ThermoModels.ModuleBlock> currModBlock = new Dictionary<int, ThermoModels.ModuleBlock>();
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<DigitalIN> 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<DigitalOUT> 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<AnalogIN> 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<AnalogOUT> 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;
}
/// <summary>
/// Restitusice SOLO VALORI IO Channels
/// </summary>
/// <param name="currChannelsIoVal"></param>
/// <returns></returns>
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<int, ThermoModels.ModuleBlock> currModBlock = new Dictionary<int, ThermoModels.ModuleBlock>();
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<DigInVal> 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<DigOutVal> 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<AnalInVal> 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<AnalOutVal> 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;
}
/// <summary>
/// Legge tutti i parametri della ricetta
@@ -3061,7 +3338,7 @@ namespace Thermo.Active.NC
/// </summary>
/// <param name="updtRecipe">Oggetto parametri da aggiornare (from HMI)</param>
/// <param name="nMaxParamWrite">num max parametri da scrivere singolarmente</param>
/// <param name="delayParamWrite">delay in scriottura multi parametri singoli</param>
/// <param name="delayParamWrite">delay in scrittura multi parametri singoli</param>
/// <returns></returns>
public CmsError WriteRecipeParametersToPLC(Dictionary<string, DTORecipeParam> updtRecipe, int nMaxParamWrite, int delayParamWrite)
{
@@ -3091,7 +3368,7 @@ namespace Thermo.Active.NC
/// </summary>
/// <param name="updtRecipe">Oggetto parametri da aggiornare (from HMI)</param>
/// <param name="nMaxParamWrite">num max parametri da scrivere singolarmente</param>
/// <param name="delayParamWrite">delay in scriottura multi parametri singoli</param>
/// <param name="delayParamWrite">delay in scrittura multi parametri singoli</param>
/// <returns></returns>
public CmsError WriteRecipeParams(Dictionary<string, DTORecipeParam> updtRecipe, int nMaxParamWrite, int delayParamWrite)
{
@@ -3100,6 +3377,125 @@ namespace Thermo.Active.NC
return libraryError;
}
/// <summary>
/// ChannelsID: write DO to PLC (values + setForce)
/// </summary>
/// <param name="newValues">Oggetto parametri da aggiornare (from HMI)</param>
/// <returns></returns>
public CmsError Write_IO_DO_ToPLC(Dictionary<int, bool> 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;
}
/// <summary>
/// ChannelsID: write AO to PLC (values + setForce)
/// </summary>
/// <param name="newValues">Oggetto parametri da aggiornare (from HMI)</param>
/// <returns></returns>
public CmsError Write_IO_AO_ToPLC(Dictionary<int, int> 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;
}
/// <summary>
/// ChannelsID: Write RESET (not forced) for DO to PLC (setForce = false)
/// </summary>
/// <param name="channels">Oggetto parametri da aggiornare (from HMI)</param>
/// <returns></returns>
public CmsError WriteReset_IO_DO_ToPLC(List<int> channels)
{
// solo x S7...
if (NcConfig.NcVendor == NC_VENDOR.S7NET)
{
Dictionary<int, bool> newForced = new Dictionary<int, bool>();
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;
}
/// <summary>
/// ChannelsID: Write RESET (not forced) for AO to PLC (setForce = false)
/// </summary>
/// <param name="channels">Oggetto parametri da aggiornare (from HMI)</param>
/// <returns></returns>
public CmsError WriteReset_IO_AO_ToPLC(List<int> channels)
{
// solo x S7...
if (NcConfig.NcVendor == NC_VENDOR.S7NET)
{
Dictionary<int, bool> newForced = new Dictionary<int, bool>();
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;
}
/// <summary>
/// ChannelsID: Write RESET (not forced) for DO + AO to PLC (setForce = false)
/// </summary>
/// <param name="newValues">Oggetto parametri da aggiornare (from HMI)</param>
/// <param name="nMaxParamWrite">num max parametri da scrivere singolarmente</param>
/// <param name="delayParamWrite">delay in scrittura multi parametri singoli</param>
/// <returns></returns>
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;
}
/// <summary>
/// Scrive le softkey star
/// </summary>
+15
View File
@@ -100,6 +100,21 @@ namespace Thermo.Active.Utils
return answ;
}
/// <summary>
/// Conversion string --> TACT_IO_TYPE
/// </summary>
/// <param name="strValue"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Conversion string --> TACT_MBLOCK_SECTION
/// </summary>
/// <param name="strValue"></param>
+116 -110
View File
@@ -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<ProductType>(() => 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<ProductType>(() => 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<ApplySchemaVendorExtensions>();
// 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<ApplySchemaVendorExtensions>();
// 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<AddDefaultResponse>();
//
// 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<AddDefaultResponse>();
//
// 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
@@ -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<string> listDI = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.DI).GroupBy(x => x.Bank).Select(x => x.Key).ToList();
List<string> listDO = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.DO).GroupBy(x => x.Bank).Select(x => x.Key).ToList();
List<string> listAI = IOConfig.Where(x => x.Category == Model.Constants.TACT_IO_TYPE.AI).GroupBy(x => x.Bank).Select(x => x.Key).ToList();
List<string> 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()
{
@@ -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"];
@@ -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
{
/// <summary>
/// Oggetto adapter condiviso da WebAPI
/// </summary>
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<DateTime, int> 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<IoItemDigi> 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<int, bool> parametersList = new Dictionary<int, bool>();
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<IoItemAnal> 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<int, int> parametersList = new Dictionary<int, int>();
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<int> 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();
}
}
/// <summary>
/// Reset "force bit" on selected channels
/// </summary>
/// <param name="parametersList">List of channels index, zero based</param>
/// <returns></returns>
[Route("io_reset_ch_ao"), HttpPut]
[WebApiAuthorize(FunctionAccess = FUNCTIONALITY_NAMES.MAINTENANCE, Action = ACTIONS.WRITE)]
public IHttpActionResult ResetChAO(List<int> 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();
}
}
}
@@ -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);
@@ -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<NcHub>();
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<NcHub>();
context.Clients.Group("ncData").channelsIoVal(diffChannelsData);
}
}
public static void SetGatewayRebootStatus(object status)
{
string msg = status.ToString();
@@ -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<int, DTOAxisInfoModel> LastAxisInfoData = new Dictionary<int, DTOAxisInfoModel>();
// Oggetti x Valori Channels IO
public static DTOChannelsIOVal LastChannelsIoData = new DTOChannelsIOVal();
public static bool LastIsNcConnected = false;
}
+3 -3
View File
@@ -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")]
+1
View File
@@ -223,6 +223,7 @@
<Compile Include="Attributes\SignalRAuthorizeAttribute.cs" />
<Compile Include="Controllers\SignalR\NcHub.cs" />
<Compile Include="Controllers\WebApi\ApiAlarmController.cs" />
<Compile Include="Controllers\WebApi\UnderTheHoodController.cs" />
<Compile Include="Controllers\WebApi\SchedTaskController.cs" />
<Compile Include="Controllers\WebApi\ModulesController.cs" />
<Compile Include="Controllers\WebApi\ProdController.cs" />
BIN
View File
Binary file not shown.