Merge branch 'release/CitizenRest01'

This commit is contained in:
Samuele Locatelli
2024-11-11 19:58:22 +01:00
16 changed files with 1782 additions and 25 deletions
+10
View File
@@ -532,6 +532,16 @@ namespace IOB_UT_NEXT
/// </summary>
PingWatchdog,
/// <summary>
/// Adapter REST (base)
/// </summary>
REST,
/// <summary>
/// Adapter REST Citizen
/// </summary>
REST_CITIZEN,
/// <summary>
/// Adapter SIEMENS
/// </summary>
+14 -2
View File
@@ -84,8 +84,8 @@
<Reference Include="MapoSDK, Version=6.14.2309.1908, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MapoSDK.6.14.2309.1908\lib\MapoSDK.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.6.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
@@ -96,6 +96,9 @@
<Reference Include="Pipelines.Sockets.Unofficial, Version=1.0.0.0, Culture=neutral, PublicKeyToken=42ea0a778e13fbe2, processorArchitecture=MSIL">
<HintPath>..\packages\Pipelines.Sockets.Unofficial.2.2.8\lib\net461\Pipelines.Sockets.Unofficial.dll</HintPath>
</Reference>
<Reference Include="RestSharp, Version=112.1.0.0, Culture=neutral, PublicKeyToken=598062e77f915f75, processorArchitecture=MSIL">
<HintPath>..\packages\RestSharp.112.1.0\lib\netstandard2.0\RestSharp.dll</HintPath>
</Reference>
<Reference Include="StackExchange.Redis, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c219ff1ca8c2ce46, processorArchitecture=MSIL">
<HintPath>..\packages\StackExchange.Redis.2.6.122\lib\net461\StackExchange.Redis.dll</HintPath>
</Reference>
@@ -130,6 +133,12 @@
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Text.Encodings.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encodings.Web.8.0.0\lib\net462\System.Text.Encodings.Web.dll</HintPath>
</Reference>
<Reference Include="System.Text.Json, Version=8.0.0.4, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Json.8.0.4\lib\net462\System.Text.Json.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Channels, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Channels.6.0.0\lib\net461\System.Threading.Channels.dll</HintPath>
</Reference>
@@ -137,6 +146,9 @@
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Transactions" />
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
+72
View File
@@ -723,6 +723,78 @@ namespace IOB_UT_NEXT
#endregion Public Properties
}
/// <summary>
/// Classe gestione configurazione parametri specifici Rest Client da BaseParamConf
/// </summary>
public class RestParamConf : BaseParamConf
{
/// <summary>
/// Timeout chiamate REST
/// </summary>
public int timeOutSec { get; set; } = 60;
/// <summary>
/// API di base x chiamate REST, eventuali variabili van indicate come [[nomevar]]
/// </summary>
public string apiUrl { get; set; } = "";
/// <summary>
/// Elenco delle chiamate x ID / struttura
/// </summary>
public Dictionary<string, CallStruc> CallList { get; set; } = new Dictionary<string, CallStruc>();
#if false
/// <summary>
/// Dizionario "tampone" di variabili da poter reimpiegare in chiamate successive (es token)
/// </summary>
public Dictionary<string, string> TempVars { get; set; } = new Dictionary<string, string>();
/// <summary>
/// Elenco delle chiamate VIETATE (con nota opzionale sul motivo)
/// </summary>
public Dictionary<string, string> CallVeto { get; set; } = new Dictionary<string, string>();
#endif
public class CallStruc
{
/// <summary>
/// ID univoco chiamata per poterla recuperare
/// </summary>
public int Idx { get; set; } = 0;
/// <summary>
/// Metodo chaimata
/// </summary>
public RestSharp.Method Method { get; set; } = RestSharp.Method.Get;
/// <summary>
/// Url chiamata
/// </summary>
public string Url { get; set; } = "";
/// <summary>
/// Nome x invio a MES
/// </summary>
public string Name { get; set; } = "";
/// <summary>
/// Nome x salvataggio valore output in ProdData da poter richiamare
/// </summary>
public string OutVarName { get; set; } = "";
/// <summary>
/// Intervallo di campionamento (minimo) da rispettare x evitare flood chiamate
/// </summary>
public int SamplePeriod { get; set; } = 5000;
/// <summary>
/// Elenco chiamate richieste se non fosse trovata/valida una variabile
/// </summary>
public List<string> ListPrevCall { get; set; } = new List<string>();
}
}
public class UserIdent
{
#region Public Properties
+5 -1
View File
@@ -20,7 +20,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
@@ -38,6 +38,10 @@
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.4" newVersion="8.0.0.4" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" /></startup></configuration>
+5 -1
View File
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MapoSDK" version="6.14.2309.1908" targetFramework="net462" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="6.0.0" targetFramework="net462" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="8.0.0" targetFramework="net462" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net462" />
<package id="NLog" version="5.2.3" targetFramework="net462" />
<package id="Pipelines.Sockets.Unofficial" version="2.2.8" targetFramework="net462" />
<package id="RestSharp" version="112.1.0" targetFramework="net462" />
<package id="SharpZipLib" version="1.4.2" targetFramework="net462" />
<package id="StackExchange.Redis" version="2.6.122" targetFramework="net462" />
<package id="System.Buffers" version="4.5.1" targetFramework="net462" />
@@ -15,6 +16,9 @@
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net462" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net462" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net462" />
<package id="System.Text.Encodings.Web" version="8.0.0" targetFramework="net462" />
<package id="System.Text.Json" version="8.0.4" targetFramework="net462" />
<package id="System.Threading.Channels" version="6.0.0" targetFramework="net462" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net462" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net462" />
</packages>
+11
View File
@@ -1,4 +1,5 @@
using IOB_UT_NEXT;
using IOB_WIN_NEXT.IobSoap;
using MapoSDK;
using Newtonsoft.Json;
using NLog;
@@ -1848,6 +1849,16 @@ namespace IOB_WIN_NEXT
start.Enabled = true;
break;
case tipoAdapter.REST:
iobObj = new IobRest.Base(this, IOBConf);
start.Enabled = true;
break;
case tipoAdapter.REST_CITIZEN:
iobObj = new IobRest.Citizen(this, IOBConf);
start.Enabled = true;
break;
case tipoAdapter.SIEMENS:
iobObj = new IobSiemens.Siemens(this, IOBConf);
start.Enabled = true;
+5 -1
View File
@@ -133,7 +133,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
@@ -179,6 +179,10 @@
<assemblyIdentity name="FluentFTP" publicKeyToken="f4af092b1d8df44f" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-41.0.0.0" newVersion="41.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.4" newVersion="8.0.0.4" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.web>
+77
View File
@@ -0,0 +1,77 @@
;Configurazione IOB-WIN
[IOB]
CNCTYPE=FANUC
[MACHINE]
VENDOR=COLCOM
MODEL=DMG-MORI-02
[CNC]
; TEST FANUC!
;IP=192.168.100.81
;Nuovo ip in sottorete .80.
IP=192.168.80.34
PORT=8193
GETPRGNAME=true
[SERVER]
MPIP=192.168.111.104
MPURL=/MP/IO
CMDBASE=/IOB/input/
CMDFLOG=/IOB/flog/
CMDALIVE=/IOB
CMDENABLED=/IOB/enabled/
CMDADV1=?valore=
CMDREBO=/sendReboot.aspx?idxMacchina=
[MEMORY]
; Red: Y12.4 | Yellow: Y51.1 (porta chiusa, da NEGARE) | Green Y12.6 | Alarm Y 51.4 | Blu Y12.7
;BIT0=CONN
BIT1=Y12.6
;BIT2=PZCOUNT.PAR.6711
BIT3=Y12.4
BIT4=Y12.7
;BIT5=Y11.2
BIT5=X18.3
BIT6=X11.3
AREAD_START=0
AREAD_SIZE=9999
AREAG_SIZE=48
AREAR_START=0
AREAR_SIZE=64
AREAX_START=0
AREAX_SIZE=64
AREAY_START=0
AREAY_SIZE=64
PAR_START=6711
PAR_SIZE=3
[BLINK]
;MAX_COUNTER_BLINK = 30
MAX_COUNTER_BLINK = 15
;bit0 = 0
;bit1 = 0
;bit2 = 1
;bit3 = 1
;bit4 = 1
;bit5 = 0
;bit6 = 0
;bit7 = 0
BLINK_FILT=0
;BLINK_FILT=28
[OPTPAR]
;PZCOUNT_MODE=STD|BIT
;PZCOUNT_MODE=STD.PAR.6711
;PZGTOT_MODE=STD.PAR.6712
;PZREQ_MODE=STD.PAR.6713
ENABLE_PZ_RESET=TRUE
ENABLE_PZ_RESET_stopSetup=TRUE
;gestione invio pezzi in blocco
ENABLE_SEND_PZC_BLOCK=TRUE
MIN_SEND_PZC_BLOCK=10
MAX_SEND_PZC_BLOCK=100
DISABLE_SEND_WDST=TRUE
[BRANCH]
NAME=master
+75
View File
@@ -0,0 +1,75 @@
;Configurazione IOB-WIN
[IOB]
CNCTYPE=REST_CITIZEN
[MACHINE]
VENDOR=Citizen_Mecmatica
MODEL=Citizen
[CNC]
IP=192.168.80.61
PORT=8733
GETPRGNAME=true
[SERVER]
MPIP=192.168.111.104
MPURL=/MP/IO
CMDBASE=/IOB/input/
CMDFLOG=/IOB/flog/
CMDALIVE=/IOB
CMDENABLED=/IOB/enabled/
CMDADV1=?valore=
CMDREBO=/sendReboot.aspx?idxMacchina=
[MEMORY]
; Red: Y12.4 | Yellow: Y51.1 (porta chiusa, da NEGARE) | Green Y12.6 | Alarm Y 51.4 | Blu Y12.7
;BIT0=CONN
BIT1=Y12.6
;BIT2=PZCOUNT.PAR.6711
BIT3=Y12.4
BIT4=Y12.7
;BIT5=Y11.2
BIT5=X18.3
BIT6=X11.3
AREAD_START=0
AREAD_SIZE=9999
AREAG_SIZE=48
AREAR_START=0
AREAR_SIZE=64
AREAX_START=0
AREAX_SIZE=64
AREAY_START=0
AREAY_SIZE=64
PAR_START=6711
PAR_SIZE=3
[BLINK]
;MAX_COUNTER_BLINK = 30
MAX_COUNTER_BLINK = 15
;bit0 = 0
;bit1 = 0
;bit2 = 1
;bit3 = 1
;bit4 = 1
;bit5 = 0
;bit6 = 0
;bit7 = 0
BLINK_FILT=0
;BLINK_FILT=28
[OPTPAR]
;PZCOUNT_MODE=STD|BIT
;PZCOUNT_MODE=STD.PAR.6711
;PZGTOT_MODE=STD.PAR.6712
;PZREQ_MODE=STD.PAR.6713
ENABLE_PZ_RESET=TRUE
ENABLE_PZ_RESET_stopSetup=TRUE
;gestione invio pezzi in blocco
ENABLE_SEND_PZC_BLOCK=TRUE
MIN_SEND_PZC_BLOCK=10
MAX_SEND_PZC_BLOCK=100
DISABLE_SEND_WDST=TRUE
REST_CONF=L020_Rest.conf
[BRANCH]
NAME=master
+141
View File
@@ -0,0 +1,141 @@
{
"timeOutSec": 60,
"apiUrl": "http://192.168.80.61:8733/DRIVER_MES/rest/",
"mMapRead": {
//"GetQtyTot": {
// "name": "GetQtyTot",
// "description": "Contatore GTot",
// //"memAddr": "",
// "tipoMem": "Int",
// //"index": 0,
// //"size": 4,
// "func": "LAST",
// //"period": 60,
// "factor": 1,
// "displOrdinal": 1
//}
},
"mMapWrite": {
},
"CallList": {
"GetConnection": {
"Method": "Get",
"Url": "checkconnection",
"Name": "Connection",
"OutVarName": "Connected"
},
"GetToken": {
"Method": "Get",
"Url": "gettoken/mecmaticames/mecmatica@mes",
"OutVarName": "token",
"SamplePeriod": 1000
},
"GetLampGreen": {
"Method": "Get",
"Url": "getsingleladderio/[[token]]/Y/8E",
"Name": "Lampada Verde",
"OutVarName": "LampGreen",
"ListPrevCall": [ "GetToken" ],
"SamplePeriod": 1000
},
"GetLampYellow": {
"Method": "Get",
"Url": "getsingleladderio/[[token]]/Y/21",
"Name": "Lampada Gialla",
"OutVarName": "LampYellow",
"ListPrevCall": [ "GetToken" ],
"SamplePeriod": 1000
},
"GetLampRed": {
"Method": "Get",
"Url": "getsingleladderio/[[token]]/Y/22",
"Name": "Lampada Rossa",
"OutVarName": "LampRed",
"ListPrevCall": [ "GetToken" ],
"SamplePeriod": 1000
},
//"GetStateAlarm": {
// "Method": "Get",
// "Url": "getsingleladderio/[[token]]/Y/200",
// "Name": "Macchina in Allarme",
// "OutVarName": "AlarmState",
// "ListPrevCall": [ "GetToken" ],
// "SamplePeriod": 2000
//},
//"GetStateCaution": {
// "Method": "Get",
// "Url": "getsingleladderio/[[token]]/Y/201",
// "Name": "Macchina in Caution",
// "OutVarName": "CautionState",
// "ListPrevCall": [ "GetToken" ],
// "SamplePeriod": 2000
//},
//"GetStateStart": {
// "Method": "Get",
// "Url": "getsingleladderio/[[token]]/Y/222",
// "Name": "Macchina in Start",
// "OutVarName": "StartState",
// "ListPrevCall": [ "GetToken" ],
// "SamplePeriod": 2000
//},
//"GetStateStop": {
// "Method": "Get",
// "Url": "getsingleladderio/[[token]]/Y/223",
// "Name": "Macchina in Stop",
// "OutVarName": "StopState",
// "ListPrevCall": [ "GetToken" ],
// "SamplePeriod": 2000
//},
"GetQtyTot": {
"Method": "Get",
"Url": "gettotalquantity/[[token]]",
"Name": "Contapezzi Assoluto",
"OutVarName": "ContapezziAssoluto",
"ListPrevCall": [ "GetToken" ]
},
"GetQtyReq": {
"Method": "Get",
"Url": "getneededquantity/[[token]]",
"Name": "Qta Richiesta",
"OutVarName": "setPzComm",
"ListPrevCall": [ "GetToken" ]
},
"GetQtyProd": {
"Method": "Get",
"Url": "getworkedquantity/[[token]]",
"Name": "Contapezzi Parziale",
"OutVarName": "ContapezziParziale",
"ListPrevCall": [ "GetToken" ]
},
"GetCycleTime": {
"Method": "Get",
"Url": "getcycletime/[[token]]",
"Name": "tempoCiclo (sec)",
"OutVarName": "LastTC",
"ListPrevCall": [ "GetToken" ]
},
"GetProgName": {
"Method": "Get",
"Url": "getmainprogram/[[token]]",
"Name": "Programma MAIN",
"OutVarName": "PROG",
"ListPrevCall": [ "GetToken" ]
},
"GetCurrAlarm": {
"Method": "Get",
"Url": "getalarm/[[token]]",
"Name": "Allarme attivo",
"OutVarName": "AlarmActive",
"ListPrevCall": [ "GetToken" ],
"SamplePeriod": 2000
},
"GetAllAlarmLog": {
"Method": "Get",
"Url": "getallalarmlog/[[token]]",
"Name": "Log Allarmi (last)",
"OutVarName": "",
"ListPrevCall": [ "GetToken" ],
"SamplePeriod": 20000
}
}
}
+29 -15
View File
@@ -3,7 +3,7 @@
"setArt": {
"name": "setArt",
"description": "Articolo",
"memAddr": "",
"memAddr": "NONE.01",
"tipoMem": "String",
"index": 0,
"size": 20,
@@ -21,7 +21,7 @@
"setComm": {
"name": "setComm",
"description": "Commessa",
"memAddr": "",
"memAddr": "NONE.02",
"tipoMem": "String",
"index": 0,
"size": 20,
@@ -47,27 +47,41 @@
}
},
"mMapRead": {
"ContatoreAssoluto": {
"name": "ContatoreAssoluto",
"description": "Contapezzi ASSOLUTO",
"memAddr": "MACRO.929",
"PZ_GTOT": {
"name": "PZ_GTOT",
"description": "Contatore GTot",
"memAddr": "",
"tipoMem": "Int",
"index": 929,
"index": 0,
"size": 4,
"func": "MAX",
"period": 60,
"factor": 1
"factor": 1,
"displOrdinal": 7
},
"ContatoreParziale": {
"name": "ContatoreParziale",
"description": "Contapezzi Parziale",
"memAddr": "MACRO.930",
"tipoMem": "DInt",
"index": 930,
"PZ_COUNT": {
"name": "PZ_COUNT",
"description": "Contatore",
"memAddr": "",
"tipoMem": "Int",
"index": 0,
"size": 4,
"func": "MAX",
"period": 60,
"factor": 1
"factor": 1,
"displOrdinal": 8
},
"PROG": {
"name": "PROG",
"description": "Programma",
"memAddr": "",
"tipoMem": "Int",
"index": 0,
"size": 4,
"func": "MAX",
"period": 60,
"factor": 1,
"displOrdinal": 9
}
},
"mMapWriteLink": {
+19 -3
View File
@@ -153,6 +153,9 @@
<Reference Include="MathNet.Numerics, Version=4.15.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MathNet.Numerics.4.15.0\lib\net461\MathNet.Numerics.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.2.1.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
</Reference>
@@ -204,9 +207,8 @@
<HintPath>..\packages\OPCFoundation.NetStandard.Opc.Ua.Security.Certificates.1.4.367.75\lib\net462\Opc.Ua.Security.Certificates.dll</HintPath>
</Reference>
<Reference Include="PresentationFramework" />
<Reference Include="RestSharp, Version=105.2.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\RestSharp.105.2.3\lib\net46\RestSharp.dll</HintPath>
<Private>True</Private>
<Reference Include="RestSharp, Version=112.1.0.0, Culture=neutral, PublicKeyToken=598062e77f915f75, processorArchitecture=MSIL">
<HintPath>..\packages\RestSharp.112.1.0\lib\netstandard2.0\RestSharp.dll</HintPath>
</Reference>
<Reference Include="S7.Net, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d5812d469e84c693, processorArchitecture=MSIL">
<HintPath>..\packages\S7netplus.0.1.9\lib\net45\S7.Net.dll</HintPath>
@@ -366,6 +368,15 @@
<Reference Include="System.ServiceModel.Security, Version=4.6.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.ServiceModel.Security.4.6.0\lib\net461\System.ServiceModel.Security.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encodings.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encodings.Web.8.0.0\lib\net462\System.Text.Encodings.Web.dll</HintPath>
</Reference>
<Reference Include="System.Text.Json, Version=8.0.0.4, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Json.8.0.4\lib\net462\System.Text.Json.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Transactions" />
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
@@ -403,6 +414,8 @@
<Compile Include="IobOpc\OpcUaEwonAdige.cs" />
<Compile Include="IobOpc\OpcUaKpwRama.cs" />
<Compile Include="IobOpc\OpcUaKpw.cs" />
<Compile Include="IobRest\Citizen.cs" />
<Compile Include="IobRest\Base.cs" />
<Compile Include="Iob\BaseObj.cs" />
<Compile Include="Iob\iobRefreshedEventArgs.cs" />
<Compile Include="IobSoap\Gomba.cs" />
@@ -514,6 +527,9 @@
</None>
<None Include="DATA\CONF\FOV098.ini" />
<None Include="DATA\CONF\FOV099.ini" />
<None Include="DATA\CONF\L019.ini" />
<None Include="DATA\CONF\L020_Rest.json" />
<None Include="DATA\CONF\L020.ini" />
<None Include="DATA\CONF\VL27.json" />
<None Include="DATA\CONF\VL27.ini" />
<None Include="DATA\CONF\SIMUL_01.json">
+1 -1
View File
@@ -866,7 +866,7 @@ namespace IOB_WIN_NEXT.IobOpc
}
/// <summary>
/// Parametri specifici MTC
/// Parametri specifici OPC-UA
/// </summary>
protected OpcUaParamConf opcUaParams { get; set; }
+758
View File
@@ -0,0 +1,758 @@
using RestSharp;
using IOB_UT_NEXT;
using MapoSDK;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net.NetworkInformation;
using System.IO;
using System.Windows.Forms;
using System.Threading;
using S7.Net.Types;
using System.Text.RegularExpressions;
namespace IOB_WIN_NEXT.IobRest
{
/// <summary>
/// Adapter base per sviluppo chiamate con servizi REST
/// </summary>
public class Base : Iob.Generic
{
#region Public Constructors
/// <summary>
/// Costruttore dell'IOB Rest generico
/// </summary>
/// <param name="caller">AdapterForm chiamante</param>
/// <param name="IOBConf">Configurazione IOB per avvio</param>
public Base(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf)
{
lgInfo($"Richiesto Adapter IobRest.Base con i parametri seguenti | ADDR: {IOBConf.cncIpAddr} | PORT: {IOBConf.cncPort}");
lastPING = DateTime.Now.AddHours(-1);
// predispongo configurazione specifica Rest...
if (!string.IsNullOrEmpty(getOptJsonKVP("REST_CONF")))
{
setupRestConf(getOptJsonKVP("REST_CONF"));
}
}
#endregion Public Constructors
#region Public Methods
/// <summary>
/// Implementazione custom esecuzione task specifici
/// </summary>
/// <param name="task2exe"></param>
/// <returns></returns>
public override Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe)
{
/*---------------------------------------
* gestione execute task SPECIFICI x pesa:
* - salva i parametri richiesta (RM, cod1..cod6)
* - esegue metodo richiesta (IN/OUT)
*---------------------------------------*/
// Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti...
Dictionary<string, string> taskDone = new Dictionary<string, string>();
#if false
if (task2exe != null)
{
lgTrace($"executeTasks: richiesta esecuzione {task2exe.Count} task");
// controllo se memMap != null...
if (memMap != null)
{
bool taskOk = false;
string taskVal = "";
// cerco task specifici: qui sono NON standard...
foreach (var item in task2exe)
{
lgInfo($"TASK | {item.Key} --> {item.Value}");
taskOk = false;
taskVal = "";
// converto richiesta in enum...
taskType tName = taskType.nihil;
Enum.TryParse(item.Key, out tName);
// controllo sulla KEY...
switch (tName)
{
case taskType.setParameter:
// richiedo da URL i parametri WRITE da popolare
lgInfo("Chiamata setParameter --> processMemWriteRequests");
taskVal = processMemWriteRequests();
// se restituiscce "" faccio altra prova...
if (string.IsNullOrEmpty(taskVal))
{
// i parametri me li aspetto come stringa composta paramName|paramvalue
if (item.Value.Contains("|"))
{
string[] paramsJob = item.Value.Split('|');
taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}";
}
else
{
taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {item.Value} doesnt contain pipe for splitting key/value";
}
}
break;
default:
taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC";
lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}");
break;
}
// aggiungo task!
taskDone.Add(item.Key, taskVal);
}
}
else
{
lgError($"Attenzione! memMap è nullo, non posso eseguire task2exe!");
}
}
#endif
return taskDone;
}
/// <summary>
/// Recupero dati dinamici...
/// </summary>
public override Dictionary<string, string> getDynData()
{
// valore non presente in vers default... se gestito fare override
Dictionary<string, string> outVal = new Dictionary<string, string>();
#if false
// controllo se ho indicato ancora che ci siano pesate già lette da inviare...
if (num2send() > 0)
{
// preparo oggetti x confronto ...
List<WeightRec> listaArch = listPesateArchivio;
// se non ho nulla in archivio prendo ultima pesata (essendo DESC è la prima cronologicamente)
if (listaArch.Count == 0)
{
WeightRec lastRec = listPesateCurr.LastOrDefault();
// aggiungo...
SavePesata(ref outVal, lastRec);
}
// ora il confronto è cronologico sulle pesate + recenti...
else
{
// prendo prima della lista pesate archiviate = più recente come dt da cui partire...
DateTime dtRif = listaArch.FirstOrDefault().DtEvent;
var firstRec = listPesateCurr
.Where(x => x.DtEvent > dtRif)
.OrderBy(x => x.DtEvent)
.FirstOrDefault();
if (firstRec != null)
{
SavePesata(ref outVal, firstRec);
}
}
// processo comunque le aree memoria READ...
if (memMap.mMapRead.Count > 0)
{
foreach (var item in memMap.mMapRead)
{
var currVal = getCurrProdData(item.Key, "");
if (!outVal.ContainsKey(item.Key))
{
outVal.Add(item.Key, $"{currVal}");
}
// se fosse logReq --> resetto...
if (item.Key == "logReq" && !string.IsNullOrEmpty(currVal))
{
upsertKey(item.Key, "");
}
}
}
}
// altrimenti rileggo e cerco se ci siano
else
{
Stopwatch sw = new Stopwatch();
sw.Start();
try
{
// test lettura elenco pesate... se NON nullo --> OK!
var weightArray = RestConn.reqWeightList("ALL", dataFrom, dataTo);
// riordino DESC
listPesateCurr = WeightRec.ConvertPesate(weightArray.OrderByDescending(x => x.dateIn).ToList());
}
catch (Exception exc)
{
lgError($"Eccezione in RestConn.reqWeightList{Environment.NewLine}{exc}");
}
sw.Stop();
lgInfo($"getDynData | SOAP: effettuata chiamata reqWeightList in {sw.Elapsed.TotalMilliseconds}ms | {dataFrom} --> {dataTo} | {listPesateCurr.Count} rec");
}
#endif
// indico esecuzione e proseguo
lastReadPLC = DateTime.Now;
return outVal;
}
/// <summary>
/// Effettua lettura semafori principale
/// <paramref name="currDispData">Parametri da aggiornare x display in form</paramref>
/// </summary>
public override void readSemafori(ref newDisplayData currDispData)
{
DateTime adesso = DateTime.Now;
lastReadPLC = adesso;
// verifico non sia in veto invio iniziale...
if (queueInEnabCurr)
{
try
{
if (verboseLog)
{
lgInfo("inizio read semafori");
}
currDispData.semIn = Semaforo.SV;
// effettua refresh dati da leggere SPECIFICi x citizen...
refreshData();
// decodifica e gestione
decodeToBaseBitmap(ref currDispData);
// display
reportRawInput(ref currDispData);
}
catch (Exception exc)
{
currDispData.semIn = Semaforo.SR;
lgError($"Eccezione in readSemafori:{Environment.NewLine}{exc}");
}
}
else
{
lgDebug($"[VETO readSemafori] | veto attivo alle {adesso:yyyy.MM.dd HH:mm:ss}");
checkVetoQueueIn();
}
}
/// <summary>
/// Override connessione
/// </summary>
public override void tryConnect()
{
if (!connectionOk)
{
// controllo che il ping sia stato tentato almeno pingTestSec fa...
if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec"))
{
if (verboseLog || periodicLog)
{
lgInfo("Rest: ConnKO - tryConnect");
}
// in primis salvo data ping...
lastPING = DateTime.Now;
// se passa il ping faccio il resto...
if (testPingMachine == IPStatus.Success)
{
string szStatusConnection = "";
try
{
// ora provo connessione...
parentForm.commPlcActive = true;
// chiamo metodo connect
var checkResp = ExecuteCallGet(GetUrlResource("GetConnection"));
// forse va eliminato...
lgInfo($"GetConnection | {checkResp}");
if (checkResp != null && checkResp.ToLower().Contains("true"))
{
connectionOk = true;
}
else
{
lgError($"Errore check connessione | checkResp: {checkResp}");
}
// refresh stato connessione!!!
if (connectionOk)
{
queueInEnabCurr = true;
if (adpRunning)
{
lgInfo("Connessione OK");
}
}
else
{
lgError("Impossibile procedere, connessione mancante...");
}
}
catch (Exception exc)
{
lgFatal($"Errore nella connessione all'Adapter IobRest.Base: {szStatusConnection}{Environment.NewLine}{exc}");
connectionOk = false;
lgInfo($"Eccezione in TryConnect, Adapter IobRest.Base NON running, pausa di {utils.CRI("waitRecMSec")} msec prima di ulteriori tentativi di riconnessione");
}
}
else
{
// loggo no risposta ping ...
connectionOk = false;
if (verboseLog || periodicLog)
{
lgInfo($"Attenzione: Rest controllo PING fallito per IP {cIobConf.cncPingAddr}");
}
}
}
}
else
{
needRefresh = true;
}
}
public override void tryDisconnect()
{
// registro solo che è disconnesso
connectionOk = false;
queueInEnabCurr = false;
}
#endregion Public Methods
#region Protected Fields
/// <summary>
/// Api Url di base x chiamate REST
/// </summary>
protected string apiUrl = "http://localhost:8733";
/// <summary>
/// Timeout chiamate REST
/// </summary>
protected int tOutSec = 60;
#endregion Protected Fields
#region Protected Properties
/// <summary>
/// Parametri specifici Client Rest
/// </summary>
protected RestParamConf restParams { get; set; } = new RestParamConf();
#endregion Protected Properties
#region Protected Methods
/// <summary>
/// verifica stato ok ovvero connected oppure open
/// </summary>
/// <param name="currState"></param>
/// <returns></returns>
protected bool checkStateOk(System.ServiceModel.CommunicationState currState)
{
bool answ = false;
#if false
answ == System.ServiceModel.CommunicationState.Opened || currState == System.ServiceModel.CommunicationState.Created;
#endif
return answ;
}
/// <summary>
/// Esecuzione chiamata Rest tipo GET
/// </summary>
/// <param name="resource"></param>
/// <returns></returns>
protected string ExecuteCallGet(string resource)
{
string answ = "";
if (!string.IsNullOrEmpty(resource))
{
// client chiamate rest
using (var client = new RestClient(restOptStd))
{
var currReq = new RestRequest(resource, Method.Get);
currReq.AddHeader("Content-type", "application/json");
// effettuo vera chiamata
var currResp = client.Get(currReq);
if (currResp.StatusCode == System.Net.HttpStatusCode.OK && currResp.Content != null)
{
answ = currResp.Content ?? "";
}
}
}
return answ;
}
/// <summary>
/// restituisce URL della risorsa eventualmente completato con token o altro
/// </summary>
/// <param name="resName"></param>
/// <returns></returns>
protected string GetUrlResource(string resName)
{
string answ = "";
if (restParams != null && restParams.CallList != null && restParams.CallList.Count > 0)
{
if (restParams.CallList.ContainsKey(resName))
{
answ = restParams.CallList[resName].Url;
// eseguo eventuale sostituzione (se trovo "[[")
if (answ.Contains("[["))
{
string pattern = @"\[\[.*\]\]";
Regex regex = new Regex(pattern);
Match match = regex.Match(resName);
if (match.Success)
{
string key = match.Value.Replace("[[", "").Replace("]]", "");
// cerco nella LUT...
if (RestDataLUT.ContainsKey(key))
{
// sostituisco!
answ = answ.Replace($"[[{key}]]", RestDataLUT[key]);
}
}
}
}
}
return answ;
}
/// <summary>
/// Upsert in cache LUT del parametro
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
protected void RestLutUpsert(string key, string value)
{
if (RestDataLUT.ContainsKey(key))
{
RestDataLUT[key] = value;
}
else
{
RestDataLUT.Add(key, value);
}
}
/// <summary>
/// Recupero valore da cache LUT
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
protected string RestLutGet(string key)
{
string value = "";
if (RestDataLUT.ContainsKey(key))
{
value = RestDataLUT[key];
}
return value;
}
/// <summary>
/// Metodo da overridare x scrivere DAVVERO i parametri sul PLC
/// </summary>
/// <param name="updatedPar"></param>
protected override void plcWriteParams(ref List<objItem> updatedPar)
{
lgTrace($"plcWriteParams: richiesta per {updatedPar.Count} params");
foreach (var item in updatedPar)
{
lgInfo($"ITEM | {item.uid} | {item.value}");
// salvo i valori di setup x prox pesata...
upsertKey(item.uid, item.value);
#if false
bool fatto = false;
bool isPesata = false;
bool isIN = false;
gestWeightOut answ = new gestWeightOut();
// se è richiesta pesata IN/OUT --> mando chiamata
if (item.uid == "reqPesata")
{
isPesata = true;
isIN = item.reqValue.ToUpper() == "IN";
//isIN = item.value.ToUpper() == "IN";
try
{
answ = reqWeight(isIN);
}
catch (Exception exc)
{
lgError($"Eccezione in plcWriteParams.reqWeight | isIn: {isIN}{Environment.NewLine}{exc}");
}
}
else if (item.uid == "RM" || item.uid.StartsWith("Cod"))
{
// comunque segno fatto x altri casi
fatto = true;
}
// se è pesata...
if (isPesata)
{
// se è OK
if (answ.feedback == "C")
{
lgInfo($"reqWeight | Effettuato richiesta | {answ.feedback} | {answ.notes}");
// resetto pesata
upsertKey(item.uid, "");
}
else
{
lgError($"reqWeight | Errore in richiesta peso Rest | {answ.feedback} | {answ.notes}");
}
item.value = "";
item.reqValue = "";
item.lastRead = DateTime.Now;
item.UM = "";
// salvo esito richiesta comunque
upsertKey("logReq", $"{answ.feedback} | {answ.notes}");
// faccio in modo di eseguire subito getDynData
demFactDynData = 1;
processDynData();
}
else
{
// se fatto --> aggiorno!
if (fatto)
{
//item.value = item.reqValue;
item.reqValue = "";
item.lastRead = DateTime.Now;
item.UM = "";
}
}
#endif
}
}
protected void setupRestConf(string restConfFile)
{
// se ho file specifico
if (!string.IsNullOrEmpty(getOptJsonKVP("REST_CONF")))
{
string rawData = "";
// leggo file e decodifico...
string confPath = $"{Application.StartupPath}/DATA/CONF/{restConfFile}";
lgInfo($"Apertura file {confPath}");
using (StreamReader sr = new StreamReader(confPath))
{
rawData = sr.ReadToEnd().Replace("\n", "").Replace("\r", "");
}
// continuo decodifica
if (!string.IsNullOrEmpty(rawData))
{
restParams = JsonConvert.DeserializeObject<RestParamConf>(rawData);
if (restParams != null)
{
// inizializzo dal file di conf le variabili necessarie...
tOutSec = restParams.timeOutSec;
apiUrl = restParams.apiUrl ?? "http://localhost:8733";
}
}
}
// sistemo conf standard x call REST
restOptStd = new RestClientOptions
{
Timeout = TimeSpan.FromSeconds(tOutSec),
BaseUrl = new Uri(apiUrl)
};
}
#endregion Protected Methods
#region Private Fields
/// <summary>
/// LookUpTable informazioni raccolte
/// </summary>
protected Dictionary<string, string> RestDataLUT = new Dictionary<string, string>();
/// <summary>
/// Conf client RestSharp standard:
/// - timeout 1 min
/// </summary>
private RestClientOptions restOptStd = new RestClientOptions { Timeout = TimeSpan.FromSeconds(60) };
#endregion Private Fields
#region Private Methods
/// <summary>
/// Effettua decodifica aree memoria alla bitmap usata x MAPO
/// </summary>
protected virtual void decodeToBaseBitmap(ref newDisplayData currDispData)
{
// init a zero...
B_input = 0;
if (queueInEnabCurr)
{
/* -----------------------------------------------------
* bitmap MAPO STD 60
* B0: POWER_ON
* B1: RUN
* B2: pzCount
* B3: allarme
* B4: manuale
* B5: allarme TCiclo (SLOW)
* B6: WarmUp_CoolDown
* B7: EmergArmed (1 = NON emergenza, 0 = emergenza)
----------------------------------------------------- */
// per prima cosa controllo ping e se sia connesso...
#if false
if (connectionOk)
{
B_input = 1;
currDispData.semIn = Semaforo.SV;
// se ho pesate in memoria nel periodo richiesto --> RUN
if (listPesateCurr != null && listPesateCurr.Count > 0)
{
B_input += (1 << 1);
}
// metto manuale
else
{
B_input += (1 << 4);
}
// accodo NON emergenza
B_input += (1 << 7);
}
else
{
B_input = 0;
currDispData.semIn = Semaforo.SR;
}
#endif
#if false
// Controllo booleano PING e POWERON...
string currPowerOn = getDataItemValue(mtcParams.condPowerOn.keyName);
// se valido il check ping lo eseguo... altrimenti lo do x buono
bool isPingOk = mtcParams.pingAsPowerOn && (testPingMachine == IPStatus.Success);
// verifico da target value richiesto...
bool checkPowerOn = (currPowerOn == mtcParams.condPowerOn.targetValue);
// bit 0 (poweron) imposto a 1 SE pingo o PowerOn=="ON"...
B_input = (isPingOk || checkPowerOn) ? 1 : 0;
// variabili RUN...
string currRun = getDataItemValue(mtcParams.keyRunMode);
// controllo RUN MODE preliminare... CABLATO - è GENERALE x MTC
if (currRun == "AUTOMATIC" || currRun == "SEMI_AUTO" || currRun == "SEMI_AUTOMATIC")
{
int numCond = mtcParams.condWork.Count;
int numCondOk = 0;
// cerco nell'elenco delle condizioni che indicano lavora se sono ok faccio +1 conteggio......
foreach (var item in mtcParams.condWork)
{
if (getDataItemValue(item.keyName) == item.targetValue)
{
numCondOk++;
}
}
// se tutte condizioni rispettate --> lavora!
if (numCond == numCondOk)
{
// RUN = LAVORA!
B_input += (1 << 1);
}
}
// se ho almeno 1 allarme E NON SONO IN AUTO --> ALARM!
else if (hasError)
{
B_input += (1 << 3);
}
// 2024.01.90: gestione dati UNAVAILABLE che indicano poweroff...
else if (hasUnavailableData && unavailPoweroff)
{
B_input = 0;
}
else
{
// se ho run mode != auto --> manual
B_input += (1 << 4);
}
// emergenza armata da riportare con bit True/ 1
if (mtcParams.emergencyArmedTrue)
{
//se NON premuta lazo il bit
if (!hasEStopTriggered)
{
B_input += (1 << 5);
}
}
// emergenza armata da riportare come False/0 (!mtcParams.emergencyArmedTrue)
else
{
// se premuta alzo il bit...
if (hasEStopTriggered)
{
B_input += (1 << 5);
}
}
DateTime adesso = DateTime.Now;
int vFactor = 1;
// controllo SE HO dati per fare verifiche...
if (string.IsNullOrEmpty(currRun))
{
// se ho parametro x gestione reset...
if (enableMtcRestart)
{
// controllo se ho ricevuto il current da OLTRE 1 minuto...
if (lastCurrent.AddMinutes(3) < adesso)
{
lastCurrent = adesso;
// stop...
lgInfo("Fermato MTC_ref per mancanza dati current");
MTC_ref.Stop();
Thread.Sleep(1000);
// restart
lgInfo("Riavviato MTC_ref per mancanza dati current");
MTC_ref.Start();
}
}
}
else
{
vFactor = 6;
}
// solo se non ho veto check
if (vetoCheckStatus < adesso)
{
lgInfo($"Stato variabili: currRun: {currRun}");
// imposto veto per vetoSeconds...
vetoCheckStatus = adesso.AddSeconds(vetoSeconds * vFactor);
}
// log opzionale!
if (verboseLog)
{
lgInfo($"Trasformazione B_input: {B_input} | currRun = {currRun}");
}
#endif
}
else
{
lgDebug($"[VETO getDataItemValue] | veto attivo alle {DateTime.Now:yyyy.MM.dd HH:mm:ss}");
}
}
/// <summary>
/// Esegue lettura dati + salvataggio in LUT
/// </summary>
protected virtual void refreshData()
{ }
#endregion Private Methods
}
}
+555
View File
@@ -0,0 +1,555 @@
using IOB_UT_NEXT;
using MapoSDK;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using static IOB_WIN_NEXT.IobRest.Citizen.Responses;
namespace IOB_WIN_NEXT.IobRest
{
/// <summary>
/// Adapter specializzato per Citizen (Colcom, MT70)
/// </summary>
public class Citizen : Base
{
#region Public Constructors
/// <summary>
/// Costruttore dell'IOB SOAP della bilancia RestCitizen
/// </summary>
/// <param name="caller">AdapterForm chiamante</param>
/// <param name="IOBConf">Configurazione IOB per avvio</param>
public Citizen(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf)
{
lgInfo($"Richiesto Adapter IobRest.RestCitizen con i parametri seguenti | ADDR: {IOBConf.cncIpAddr} | PORT: {IOBConf.cncPort}");
lastPING = DateTime.Now.AddHours(-1);
redKeyAlarm = redisMan.redHash($"IOB:Status:{cIobConf.codIOB}:Alarm:LastRead");
lastPING = DateTime.Now.AddHours(-1);
// predispongo configurazione specifica Rest...
if (!string.IsNullOrEmpty(getOptJsonKVP("REST_CONF")))
{
setupRestConf(getOptJsonKVP("REST_CONF"));
}
// fixme todo levare forzatura test iniziale...
if (EnableTest || true)
{
// test folder salvataggio log
var appPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
var fPath = Directory.GetParent(appPath).FullName;
basePath = Path.Combine(fPath, "Test");
if (!Directory.Exists(basePath))
{
Directory.CreateDirectory(basePath);
}
string token = TestCitizenCall("gettoken/mecmaticames/mecmatica@mes");
string gLamp = TestCitizenCall($"getsingleladderio/{token}/Y/8E");
string yLamp = TestCitizenCall($"getsingleladderio/{token}/Y/21");
string rLamp = TestCitizenCall($"getsingleladderio/{token}/Y/22");
string qtyTot = TestCitizenCall($"gettotalquantity/{token}");
string qtyReq = TestCitizenCall($"getneededquantity/{token}");
string qtyWrk = TestCitizenCall($"getworkedquantity/{token}");
string cTime = TestCitizenCall($"getcycletime/{token}");
string pName = TestCitizenCall($"getmainprogram/{token}");
string cAlarm = ExecuteCallGet($"getalarm/{token}");
var sAlarm = JsonConvert.DeserializeObject<WarnInfo>(cAlarm);
cAlarm = JsonConvert.SerializeObject(sAlarm, Formatting.Indented);
lgInfo($"Call: getalarm/{token} | resp: {cAlarm}");
string allAlarm = ExecuteCallGet($"getallalarmlog/{token}");
var alarmList = JsonConvert.DeserializeObject<List<AlarmInfo>>(allAlarm);
allAlarm = JsonConvert.SerializeObject(alarmList, Formatting.Indented);
lgInfo($"Call: getallalarmlog/{token} | resp: {allAlarm}");
string err = TestCitizenCall($"getsingleladderio/ABC/Y/22");
// salvo i valori
File.WriteAllText(Path.Combine(basePath, "token.txt"), token);
File.WriteAllText(Path.Combine(basePath, "gLamp.txt"), gLamp);
File.WriteAllText(Path.Combine(basePath, "yLamp.txt"), yLamp);
File.WriteAllText(Path.Combine(basePath, "rLamp.txt"), rLamp);
File.WriteAllText(Path.Combine(basePath, "qtyTot.txt"), qtyTot);
File.WriteAllText(Path.Combine(basePath, "qtyReq.txt"), qtyReq);
File.WriteAllText(Path.Combine(basePath, "qtyWrk.txt"), qtyWrk);
File.WriteAllText(Path.Combine(basePath, "cTime.txt"), cTime);
File.WriteAllText(Path.Combine(basePath, "pName.txt"), pName);
File.WriteAllText(Path.Combine(basePath, "cAlarm.txt"), cAlarm);
File.WriteAllText(Path.Combine(basePath, "allAlarm.txt"), allAlarm);
File.WriteAllText(Path.Combine(basePath, "err.txt"), err);
}
}
#endregion Public Constructors
#region Public Methods
/// <summary>
/// Override connessione
/// </summary>
public override void tryConnect()
{
if (!connectionOk)
{
// controllo che il ping sia stato tentato almeno pingTestSec fa...
if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec"))
{
if (verboseLog || periodicLog)
{
lgInfo("Rest: ConnKO - tryConnect");
}
// in primis salvo data ping...
lastPING = DateTime.Now;
bool checkMachine = false;
// se passa il ping faccio il resto...
if (testPingMachine == IPStatus.Success)
{
string szStatusConnection = "";
try
{
// ora provo connessione...
parentForm.commPlcActive = true;
// chiamo metodo connect
var checkResp = ExecuteCallGet(GetUrlResource("GetConnection"));
lgInfo($"GetConnection | {checkResp}");
bool.TryParse(checkResp, out checkMachine);
// forse va eliminato...
if (checkMachine)
{
connectionOk = true;
queueInEnabCurr = true;
if (adpRunning)
{
lgInfo("Connessione OK");
}
}
else
{
lgError($"Errore check connessione | checkResp: {checkResp}");
}
}
catch (Exception exc)
{
lgFatal($"Errore nella connessione all'Adapter IobRest.Base: {szStatusConnection}{Environment.NewLine}{exc}");
connectionOk = false;
lgInfo($"Eccezione in TryConnect, Adapter IobRest.Base NON running, pausa di {utils.CRI("waitRecMSec")} msec prima di ulteriori tentativi di riconnessione");
}
}
else
{
// loggo no risposta ping ...
connectionOk = false;
if (verboseLog || periodicLog)
{
lgInfo($"Attenzione: Rest controllo PING fallito per IP {cIobConf.cncPingAddr}");
}
}
}
}
else
{
needRefresh = true;
}
}
#endregion Public Methods
#region Internal Classes
/// <summary>
/// Struttura delle risposte alle chiamare REST specifiche
/// </summary>
internal class Responses
{
#region Internal Classes
/// <summary>
/// Struttura info restituiti da AlarmList
/// </summary>
internal class AlarmInfo
{
#region Public Properties
public DateTime date { get; set; } = DateTime.Today.AddYears(-10);
public string ErrorMessage { get; set; } = "";
public int id { get; set; } = 0;
public string message { get; set; } = "";
public string type { get; set; } = "";
#endregion Public Properties
}
/// <summary>
/// Struttura info restituiti x lettura Ladder
/// </summary>
internal class LadderIO
{
#region Public Properties
public string Address { get; set; } = "";
public string Description { get; set; } = "";
public string ErrorMessage { get; set; } = "";
public string IOType { get; set; } = "";
public string VarValue { get; set; } = "";
#endregion Public Properties
}
/// <summary>
/// Struttura dato AlarmState (singolo, corrente)
/// </summary>
internal class WarnInfo
{
#region Public Properties
public string ErrorMessage { get; set; } = "";
public bool IsAlarm { get; set; } = false;
public bool IsCaution { get; set; } = false;
public string message { get; set; } = "";
#endregion Public Properties
}
#endregion Internal Classes
}
#endregion Internal Classes
#region Private Fields
private string basePath = "";
#endregion Private Fields
#region Private Properties
/// <summary>
/// Elenco pesate attuali
/// </summary>
private List<AlarmInfo> listAllarmiCurr { get; set; } = new List<AlarmInfo>();
/// <summary>
/// CHiave redis di salvataggio ultimo set di allarmi scaricato
/// </summary>
private string redKeyAlarm { get; set; } = "";
#endregion Private Properties
#region Private Methods
/// <summary>
/// Effettua decodifica aree memoria alla bitmap usata x MAPO
/// </summary>
protected override void decodeToBaseBitmap(ref newDisplayData currDispData)
{
// init a zero...
B_input = 0;
if (queueInEnabCurr)
{
/* -----------------------------------------------------
* bitmap MAPO STD 60
* B0: POWER_ON
* B1: RUN
* B2: pzCount
* B3: allarme
* B4: manuale
* B5: allarme TCiclo (SLOW)
* B6: WarmUp_CoolDown
* B7: EmergArmed (1 = NON emergenza, 0 = emergenza)
----------------------------------------------------- */
// per prima cosa controllo ping e se sia connesso...
if (connectionOk)
{
B_input = 1;
currDispData.semIn = Semaforo.SV;
// controllo lampade... da rosso a verde...
if(RestLutGet("rLamp")=="1")
{
B_input += (1 << 3);
}
else if (RestLutGet("yLamp") == "1")
{
B_input += (1 << 4);
}
else if (RestLutGet("gLamp") == "1")
{
B_input += (1 << 1);
}
// accodo NON emergenza ... poi da cercare meglio...
B_input += (1 << 7);
}
else
{
B_input = 0;
currDispData.semIn = Semaforo.SR;
}
#if false
// Controllo booleano PING e POWERON...
string currPowerOn = getDataItemValue(mtcParams.condPowerOn.keyName);
// se valido il check ping lo eseguo... altrimenti lo do x buono
bool isPingOk = mtcParams.pingAsPowerOn && (testPingMachine == IPStatus.Success);
// verifico da target value richiesto...
bool checkPowerOn = (currPowerOn == mtcParams.condPowerOn.targetValue);
// bit 0 (poweron) imposto a 1 SE pingo o PowerOn=="ON"...
B_input = (isPingOk || checkPowerOn) ? 1 : 0;
// variabili RUN...
string currRun = getDataItemValue(mtcParams.keyRunMode);
// controllo RUN MODE preliminare... CABLATO - è GENERALE x MTC
if (currRun == "AUTOMATIC" || currRun == "SEMI_AUTO" || currRun == "SEMI_AUTOMATIC")
{
int numCond = mtcParams.condWork.Count;
int numCondOk = 0;
// cerco nell'elenco delle condizioni che indicano lavora se sono ok faccio +1 conteggio......
foreach (var item in mtcParams.condWork)
{
if (getDataItemValue(item.keyName) == item.targetValue)
{
numCondOk++;
}
}
// se tutte condizioni rispettate --> lavora!
if (numCond == numCondOk)
{
// RUN = LAVORA!
B_input += (1 << 1);
}
}
// se ho almeno 1 allarme E NON SONO IN AUTO --> ALARM!
else if (hasError)
{
B_input += (1 << 3);
}
// 2024.01.90: gestione dati UNAVAILABLE che indicano poweroff...
else if (hasUnavailableData && unavailPoweroff)
{
B_input = 0;
}
else
{
// se ho run mode != auto --> manual
B_input += (1 << 4);
}
// emergenza armata da riportare con bit True/ 1
if (mtcParams.emergencyArmedTrue)
{
//se NON premuta lazo il bit
if (!hasEStopTriggered)
{
B_input += (1 << 5);
}
}
// emergenza armata da riportare come False/0 (!mtcParams.emergencyArmedTrue)
else
{
// se premuta alzo il bit...
if (hasEStopTriggered)
{
B_input += (1 << 5);
}
}
DateTime adesso = DateTime.Now;
int vFactor = 1;
// controllo SE HO dati per fare verifiche...
if (string.IsNullOrEmpty(currRun))
{
// se ho parametro x gestione reset...
if (enableMtcRestart)
{
// controllo se ho ricevuto il current da OLTRE 1 minuto...
if (lastCurrent.AddMinutes(3) < adesso)
{
lastCurrent = adesso;
// stop...
lgInfo("Fermato MTC_ref per mancanza dati current");
MTC_ref.Stop();
Thread.Sleep(1000);
// restart
lgInfo("Riavviato MTC_ref per mancanza dati current");
MTC_ref.Start();
}
}
}
else
{
vFactor = 6;
}
// solo se non ho veto check
if (vetoCheckStatus < adesso)
{
lgInfo($"Stato variabili: currRun: {currRun}");
// imposto veto per vetoSeconds...
vetoCheckStatus = adesso.AddSeconds(vetoSeconds * vFactor);
}
// log opzionale!
if (verboseLog)
{
lgInfo($"Trasformazione B_input: {B_input} | currRun = {currRun}");
}
#endif
}
else
{
lgDebug($"[VETO queueInEnabCurr] | veto attivo alle {DateTime.Now:yyyy.MM.dd HH:mm:ss}");
}
}
/// <summary>
/// Esegue lettura dati + salvataggio in LUT
/// </summary>
protected override void refreshData()
{
bool checkMachine = false;
LadderIO ladderResp = new LadderIO();
// in primis testo che sia connessa...
var checkResp = ExecuteCallGet(GetUrlResource("GetConnection"));
lgInfo($"GetConnection | {checkResp}");
bool.TryParse(checkResp, out checkMachine);
// proseguo SOLO SE macchina OK, altrimenti disconnetto...
if (checkMachine)
{
// faccio refresh token comunque...
string token = ExecuteCallGet(GetUrlResource("GetToken"));
RestLutUpsert("token", token);
// ora controllo valori lampada SE scaduti
// FixMe ToDo !!! gestione con scadenza info x evitare troppe letture...
if (true)
{
// resetto 3 valori lamp
RestLutUpsert("gLamp", "0");
RestLutUpsert("yLamp", "0");
RestLutUpsert("rLamp", "0");
int signVal = 0;
string gLamp = ExecuteCallGet(GetUrlResource("GetLampGreen"));
ladderResp = JsonConvert.DeserializeObject<LadderIO>(gLamp);
if (string.IsNullOrEmpty(ladderResp.ErrorMessage))
{
int.TryParse(gLamp, out signVal);
RestLutUpsert("gLamp", gLamp);
}
// se il valore è zero --> proseguo con yellow!
if (signVal == 0)
{
string yLamp = ExecuteCallGet(GetUrlResource("GetLampYellow"));
ladderResp = JsonConvert.DeserializeObject<LadderIO>(yLamp);
if (string.IsNullOrEmpty(ladderResp.ErrorMessage))
{
int.TryParse(yLamp, out signVal);
RestLutUpsert("yLamp", yLamp);
}
}
// se il valore è zero --> proseguo con red!
if (signVal == 0)
{
string rLamp = ExecuteCallGet(GetUrlResource("GetLampRed"));
ladderResp = JsonConvert.DeserializeObject<LadderIO>(rLamp);
if (string.IsNullOrEmpty(ladderResp.ErrorMessage))
{
int.TryParse(rLamp, out signVal);
RestLutUpsert("rLamp", rLamp);
}
}
}
}
else
{
tryDisconnect();
}
}
/// <summary>
/// Esegue gestioen contapezzi...
/// </summary>
public override void processContapezzi()
{
bool checkMachine = false;
LadderIO ladderResp = new LadderIO();
// in primis testo che sia connessa...
var checkResp = ExecuteCallGet(GetUrlResource("GetConnection"));
lgInfo($"GetConnection | {checkResp}");
bool.TryParse(checkResp, out checkMachine);
// proseguo SOLO SE macchina OK, altrimenti disconnetto...
if (checkMachine)
{
// faccio refresh token comunque...
string token = ExecuteCallGet(GetUrlResource("GetToken"));
RestLutUpsert("token", token);
// contapezzi corrente
int intVal = 0;
string qtyWrk = ExecuteCallGet(GetUrlResource("GetQtyProd"));
int.TryParse(qtyWrk, out intVal);
contapezziPLC = intVal;
RestLutUpsert("qtyWrk", qtyWrk);
// gestione altri contapezzi x
string qtyTot = ExecuteCallGet(GetUrlResource("GetQtyTot"));
string qtyReq = ExecuteCallGet(GetUrlResource("GetQtyReq"));
RestLutUpsert("qtyTot", qtyTot);
RestLutUpsert("qtyReq", qtyReq);
// gestione tempociclo e nome programma...
string cTime = ExecuteCallGet(GetUrlResource("GetCycleTime"));
string pName = ExecuteCallGet(GetUrlResource("GetProgName"));
RestLutUpsert("cTime", cTime);
RestLutUpsert("pName", pName);
}
}
/// <summary>
/// Recupero dati DYN, impiegando i valori della LUT...
/// </summary>
/// <returns></returns>
public override Dictionary<string, string> getDynData()
{
return RestDataLUT;
}
/// <summary>
/// Recupera il progName in modalità custom...
/// </summary>
/// <returns></returns>
public override string getPrgName()
{
return RestLutGet("pName");
}
/// <summary>
/// Test Chiamata Citizen
/// </summary>
/// <param name="urlReq"></param>
/// <returns></returns>
private string TestCitizenCall(string urlReq)
{
string answ = ExecuteCallGet(urlReq);
lgInfo($"Call: {urlReq} | resp: {answ}");
return answ;
}
#endregion Private Methods
}
}
+5 -1
View File
@@ -14,6 +14,7 @@
<package id="Fody" version="6.8.0" targetFramework="net462" developmentDependency="true" />
<package id="MapoSDK" version="6.14.2411.518" targetFramework="net462" />
<package id="MathNet.Numerics" version="4.15.0" targetFramework="net462" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="8.0.0" targetFramework="net462" />
<package id="Microsoft.CodeAnalysis.NetAnalyzers" version="6.0.0" targetFramework="net462" developmentDependency="true" />
<package id="Microsoft.Extensions.Logging.Abstractions" version="2.1.0" targetFramework="net462" />
<package id="Microsoft.IdentityModel.Abstractions" version="6.19.0" targetFramework="net462" />
@@ -33,7 +34,7 @@
<package id="OPCFoundation.NetStandard.Opc.Ua.Core" version="1.4.367.75" targetFramework="net462" />
<package id="OPCFoundation.NetStandard.Opc.Ua.Security.Certificates" version="1.4.367.75" targetFramework="net462" />
<package id="Portable.BouncyCastle" version="1.9.0" targetFramework="net462" />
<package id="RestSharp" version="105.2.3" targetFramework="net462" />
<package id="RestSharp" version="112.1.0" targetFramework="net462" />
<package id="S7netplus" version="0.1.9" targetFramework="net462" />
<package id="Selenium.WebDriver" version="4.12.4" targetFramework="net462" />
<package id="Selenium.WebDriver.ChromeDriver" version="116.0.5845.9600" targetFramework="net462" />
@@ -88,9 +89,12 @@
<package id="System.ServiceModel.Security" version="4.6.0" targetFramework="net462" />
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net462" />
<package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net462" />
<package id="System.Text.Encodings.Web" version="8.0.0" targetFramework="net462" />
<package id="System.Text.Json" version="8.0.4" targetFramework="net462" />
<package id="System.Text.RegularExpressions" version="4.3.0" targetFramework="net462" />
<package id="System.Threading" version="4.3.0" targetFramework="net462" />
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="net462" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net462" />
<package id="System.Threading.Timer" version="4.3.0" targetFramework="net462" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net462" />
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net462" />