diff --git a/IOB-UT-NEXT/Enums.cs b/IOB-UT-NEXT/Enums.cs
index 4f96e586..ee9c46b9 100644
--- a/IOB-UT-NEXT/Enums.cs
+++ b/IOB-UT-NEXT/Enums.cs
@@ -532,6 +532,16 @@ namespace IOB_UT_NEXT
///
PingWatchdog,
+ ///
+ /// Adapter REST (base)
+ ///
+ REST,
+
+ ///
+ /// Adapter REST Citizen
+ ///
+ REST_CITIZEN,
+
///
/// Adapter SIEMENS
///
diff --git a/IOB-UT-NEXT/IOB-UT-NEXT.csproj b/IOB-UT-NEXT/IOB-UT-NEXT.csproj
index d03ea652..271c0d28 100644
--- a/IOB-UT-NEXT/IOB-UT-NEXT.csproj
+++ b/IOB-UT-NEXT/IOB-UT-NEXT.csproj
@@ -84,8 +84,8 @@
..\packages\MapoSDK.6.14.2309.1908\lib\MapoSDK.dll
-
- ..\packages\Microsoft.Bcl.AsyncInterfaces.6.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll
..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll
@@ -96,6 +96,9 @@
..\packages\Pipelines.Sockets.Unofficial.2.2.8\lib\net461\Pipelines.Sockets.Unofficial.dll
+
+ ..\packages\RestSharp.112.1.0\lib\netstandard2.0\RestSharp.dll
+
..\packages\StackExchange.Redis.2.6.122\lib\net461\StackExchange.Redis.dll
@@ -130,6 +133,12 @@
+
+ ..\packages\System.Text.Encodings.Web.8.0.0\lib\net462\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.8.0.4\lib\net462\System.Text.Json.dll
+
..\packages\System.Threading.Channels.6.0.0\lib\net461\System.Threading.Channels.dll
@@ -137,6 +146,9 @@
..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll
+
diff --git a/IOB-UT-NEXT/ToMapo.cs b/IOB-UT-NEXT/ToMapo.cs
index f67d2cbf..a3909105 100644
--- a/IOB-UT-NEXT/ToMapo.cs
+++ b/IOB-UT-NEXT/ToMapo.cs
@@ -723,6 +723,78 @@ namespace IOB_UT_NEXT
#endregion Public Properties
}
+
+ ///
+ /// Classe gestione configurazione parametri specifici Rest Client da BaseParamConf
+ ///
+ public class RestParamConf : BaseParamConf
+ {
+ ///
+ /// Timeout chiamate REST
+ ///
+ public int timeOutSec { get; set; } = 60;
+
+ ///
+ /// API di base x chiamate REST, eventuali variabili van indicate come [[nomevar]]
+ ///
+ public string apiUrl { get; set; } = "";
+
+ ///
+ /// Elenco delle chiamate x ID / struttura
+ ///
+ public Dictionary CallList { get; set; } = new Dictionary();
+
+#if false
+ ///
+ /// Dizionario "tampone" di variabili da poter reimpiegare in chiamate successive (es token)
+ ///
+ public Dictionary TempVars { get; set; } = new Dictionary();
+
+ ///
+ /// Elenco delle chiamate VIETATE (con nota opzionale sul motivo)
+ ///
+ public Dictionary CallVeto { get; set; } = new Dictionary();
+#endif
+
+ public class CallStruc
+ {
+ ///
+ /// ID univoco chiamata per poterla recuperare
+ ///
+ public int Idx { get; set; } = 0;
+
+ ///
+ /// Metodo chaimata
+ ///
+ public RestSharp.Method Method { get; set; } = RestSharp.Method.Get;
+
+ ///
+ /// Url chiamata
+ ///
+ public string Url { get; set; } = "";
+
+ ///
+ /// Nome x invio a MES
+ ///
+ public string Name { get; set; } = "";
+
+ ///
+ /// Nome x salvataggio valore output in ProdData da poter richiamare
+ ///
+ public string OutVarName { get; set; } = "";
+
+ ///
+ /// Intervallo di campionamento (minimo) da rispettare x evitare flood chiamate
+ ///
+ public int SamplePeriod { get; set; } = 5000;
+
+ ///
+ /// Elenco chiamate richieste se non fosse trovata/valida una variabile
+ ///
+ public List ListPrevCall { get; set; } = new List();
+ }
+ }
+
public class UserIdent
{
#region Public Properties
diff --git a/IOB-UT-NEXT/app.config b/IOB-UT-NEXT/app.config
index 15273954..6878afb3 100644
--- a/IOB-UT-NEXT/app.config
+++ b/IOB-UT-NEXT/app.config
@@ -20,7 +20,7 @@
-
+
@@ -38,6 +38,10 @@
+
+
+
+
diff --git a/IOB-UT-NEXT/packages.config b/IOB-UT-NEXT/packages.config
index 5c2a3f51..3a637b5d 100644
--- a/IOB-UT-NEXT/packages.config
+++ b/IOB-UT-NEXT/packages.config
@@ -1,10 +1,11 @@
-
+
+
@@ -15,6 +16,9 @@
+
+
+
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/AdapterForm.cs b/IOB-WIN-NEXT/AdapterForm.cs
index b1b94347..6e148ac8 100644
--- a/IOB-WIN-NEXT/AdapterForm.cs
+++ b/IOB-WIN-NEXT/AdapterForm.cs
@@ -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;
diff --git a/IOB-WIN-NEXT/App.config b/IOB-WIN-NEXT/App.config
index d477e977..f83fb883 100644
--- a/IOB-WIN-NEXT/App.config
+++ b/IOB-WIN-NEXT/App.config
@@ -133,7 +133,7 @@
-
+
@@ -179,6 +179,10 @@
+
+
+
+
diff --git a/IOB-WIN-NEXT/DATA/CONF/L019.ini b/IOB-WIN-NEXT/DATA/CONF/L019.ini
new file mode 100644
index 00000000..14502e3a
--- /dev/null
+++ b/IOB-WIN-NEXT/DATA/CONF/L019.ini
@@ -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
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/DATA/CONF/L020.ini b/IOB-WIN-NEXT/DATA/CONF/L020.ini
new file mode 100644
index 00000000..01c502f2
--- /dev/null
+++ b/IOB-WIN-NEXT/DATA/CONF/L020.ini
@@ -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
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/DATA/CONF/L020_Rest.json b/IOB-WIN-NEXT/DATA/CONF/L020_Rest.json
new file mode 100644
index 00000000..286fe115
--- /dev/null
+++ b/IOB-WIN-NEXT/DATA/CONF/L020_Rest.json
@@ -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
+ }
+ }
+}
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/DATA/CONF/VL27.json b/IOB-WIN-NEXT/DATA/CONF/VL27.json
index 8db03ba7..3975a6ff 100644
--- a/IOB-WIN-NEXT/DATA/CONF/VL27.json
+++ b/IOB-WIN-NEXT/DATA/CONF/VL27.json
@@ -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": {
diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj
index 296c4125..9890afbb 100644
--- a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj
+++ b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj
@@ -153,6 +153,9 @@
..\packages\MathNet.Numerics.4.15.0\lib\net461\MathNet.Numerics.dll
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll
+
..\packages\Microsoft.Extensions.Logging.Abstractions.2.1.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll
@@ -204,9 +207,8 @@
..\packages\OPCFoundation.NetStandard.Opc.Ua.Security.Certificates.1.4.367.75\lib\net462\Opc.Ua.Security.Certificates.dll
-
- ..\packages\RestSharp.105.2.3\lib\net46\RestSharp.dll
- True
+
+ ..\packages\RestSharp.112.1.0\lib\netstandard2.0\RestSharp.dll
..\packages\S7netplus.0.1.9\lib\net45\S7.Net.dll
@@ -366,6 +368,15 @@
..\packages\System.ServiceModel.Security.4.6.0\lib\net461\System.ServiceModel.Security.dll
+
+ ..\packages\System.Text.Encodings.Web.8.0.0\lib\net462\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.8.0.4\lib\net462\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll
@@ -403,6 +414,8 @@
+
+
@@ -514,6 +527,9 @@
+
+
+
diff --git a/IOB-WIN-NEXT/IobOpc/OpcUa.cs b/IOB-WIN-NEXT/IobOpc/OpcUa.cs
index 58d82578..85a71de0 100644
--- a/IOB-WIN-NEXT/IobOpc/OpcUa.cs
+++ b/IOB-WIN-NEXT/IobOpc/OpcUa.cs
@@ -866,7 +866,7 @@ namespace IOB_WIN_NEXT.IobOpc
}
///
- /// Parametri specifici MTC
+ /// Parametri specifici OPC-UA
///
protected OpcUaParamConf opcUaParams { get; set; }
diff --git a/IOB-WIN-NEXT/IobRest/Base.cs b/IOB-WIN-NEXT/IobRest/Base.cs
new file mode 100644
index 00000000..3ac2a2e6
--- /dev/null
+++ b/IOB-WIN-NEXT/IobRest/Base.cs
@@ -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
+{
+ ///
+ /// Adapter base per sviluppo chiamate con servizi REST
+ ///
+ public class Base : Iob.Generic
+ {
+ #region Public Constructors
+
+ ///
+ /// Costruttore dell'IOB Rest generico
+ ///
+ /// AdapterForm chiamante
+ /// Configurazione IOB per avvio
+ 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
+
+ ///
+ /// Implementazione custom esecuzione task specifici
+ ///
+ ///
+ ///
+ public override Dictionary executeTasks(Dictionary 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 taskDone = new Dictionary();
+#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;
+ }
+
+ ///
+ /// Recupero dati dinamici...
+ ///
+ public override Dictionary getDynData()
+ {
+ // valore non presente in vers default... se gestito fare override
+ Dictionary outVal = new Dictionary();
+#if false
+ // controllo se ho indicato ancora che ci siano pesate già lette da inviare...
+ if (num2send() > 0)
+ {
+ // preparo oggetti x confronto ...
+ List 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;
+ }
+
+ ///
+ /// Effettua lettura semafori principale
+ /// Parametri da aggiornare x display in form
+ ///
+ 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();
+ }
+ }
+
+ ///
+ /// Override connessione
+ ///
+ 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
+
+ ///
+ /// Api Url di base x chiamate REST
+ ///
+ protected string apiUrl = "http://localhost:8733";
+
+ ///
+ /// Timeout chiamate REST
+ ///
+ protected int tOutSec = 60;
+
+ #endregion Protected Fields
+
+ #region Protected Properties
+
+ ///
+ /// Parametri specifici Client Rest
+ ///
+ protected RestParamConf restParams { get; set; } = new RestParamConf();
+
+ #endregion Protected Properties
+
+ #region Protected Methods
+
+ ///
+ /// verifica stato ok ovvero connected oppure open
+ ///
+ ///
+ ///
+ 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;
+ }
+
+ ///
+ /// Esecuzione chiamata Rest tipo GET
+ ///
+ ///
+ ///
+ 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;
+ }
+
+ ///
+ /// restituisce URL della risorsa eventualmente completato con token o altro
+ ///
+ ///
+ ///
+ 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;
+ }
+ ///
+ /// Upsert in cache LUT del parametro
+ ///
+ ///
+ ///
+ protected void RestLutUpsert(string key, string value)
+ {
+ if (RestDataLUT.ContainsKey(key))
+ {
+ RestDataLUT[key] = value;
+ }
+ else
+ {
+ RestDataLUT.Add(key, value);
+ }
+ }
+
+ ///
+ /// Recupero valore da cache LUT
+ ///
+ ///
+ ///
+ protected string RestLutGet(string key)
+ {
+ string value = "";
+ if (RestDataLUT.ContainsKey(key))
+ {
+ value = RestDataLUT[key];
+ }
+ return value;
+ }
+ ///
+ /// Metodo da overridare x scrivere DAVVERO i parametri sul PLC
+ ///
+ ///
+ protected override void plcWriteParams(ref List 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(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
+
+ ///
+ /// LookUpTable informazioni raccolte
+ ///
+ protected Dictionary RestDataLUT = new Dictionary();
+
+ ///
+ /// Conf client RestSharp standard:
+ /// - timeout 1 min
+ ///
+ private RestClientOptions restOptStd = new RestClientOptions { Timeout = TimeSpan.FromSeconds(60) };
+
+ #endregion Private Fields
+
+ #region Private Methods
+
+ ///
+ /// Effettua decodifica aree memoria alla bitmap usata x MAPO
+ ///
+ 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}");
+ }
+ }
+
+ ///
+ /// Esegue lettura dati + salvataggio in LUT
+ ///
+ protected virtual void refreshData()
+ { }
+
+ #endregion Private Methods
+ }
+}
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/IobRest/Citizen.cs b/IOB-WIN-NEXT/IobRest/Citizen.cs
new file mode 100644
index 00000000..4d0aa2de
--- /dev/null
+++ b/IOB-WIN-NEXT/IobRest/Citizen.cs
@@ -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
+{
+ ///
+ /// Adapter specializzato per Citizen (Colcom, MT70)
+ ///
+ public class Citizen : Base
+ {
+ #region Public Constructors
+
+ ///
+ /// Costruttore dell'IOB SOAP della bilancia RestCitizen
+ ///
+ /// AdapterForm chiamante
+ /// Configurazione IOB per avvio
+ 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(cAlarm);
+ cAlarm = JsonConvert.SerializeObject(sAlarm, Formatting.Indented);
+ lgInfo($"Call: getalarm/{token} | resp: {cAlarm}");
+
+ string allAlarm = ExecuteCallGet($"getallalarmlog/{token}");
+ var alarmList = JsonConvert.DeserializeObject>(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
+
+ ///
+ /// Override connessione
+ ///
+ 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
+
+ ///
+ /// Struttura delle risposte alle chiamare REST specifiche
+ ///
+ internal class Responses
+ {
+ #region Internal Classes
+
+ ///
+ /// Struttura info restituiti da AlarmList
+ ///
+ 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
+ }
+
+ ///
+ /// Struttura info restituiti x lettura Ladder
+ ///
+ 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
+ }
+
+ ///
+ /// Struttura dato AlarmState (singolo, corrente)
+ ///
+ 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
+
+ ///
+ /// Elenco pesate attuali
+ ///
+ private List listAllarmiCurr { get; set; } = new List();
+
+ ///
+ /// CHiave redis di salvataggio ultimo set di allarmi scaricato
+ ///
+ private string redKeyAlarm { get; set; } = "";
+
+ #endregion Private Properties
+
+ #region Private Methods
+
+ ///
+ /// Effettua decodifica aree memoria alla bitmap usata x MAPO
+ ///
+ 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}");
+ }
+ }
+
+ ///
+ /// Esegue lettura dati + salvataggio in LUT
+ ///
+ 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(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(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(rLamp);
+ if (string.IsNullOrEmpty(ladderResp.ErrorMessage))
+ {
+ int.TryParse(rLamp, out signVal);
+ RestLutUpsert("rLamp", rLamp);
+ }
+ }
+ }
+ }
+ else
+ {
+ tryDisconnect();
+ }
+ }
+
+ ///
+ /// Esegue gestioen contapezzi...
+ ///
+ 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);
+ }
+ }
+
+ ///
+ /// Recupero dati DYN, impiegando i valori della LUT...
+ ///
+ ///
+ public override Dictionary getDynData()
+ {
+ return RestDataLUT;
+ }
+
+ ///
+ /// Recupera il progName in modalità custom...
+ ///
+ ///
+ public override string getPrgName()
+ {
+ return RestLutGet("pName");
+ }
+
+ ///
+ /// Test Chiamata Citizen
+ ///
+ ///
+ ///
+ private string TestCitizenCall(string urlReq)
+ {
+ string answ = ExecuteCallGet(urlReq);
+ lgInfo($"Call: {urlReq} | resp: {answ}");
+ return answ;
+ }
+
+ #endregion Private Methods
+ }
+}
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/packages.config b/IOB-WIN-NEXT/packages.config
index 9bfd01a6..c8d2b4a7 100644
--- a/IOB-WIN-NEXT/packages.config
+++ b/IOB-WIN-NEXT/packages.config
@@ -14,6 +14,7 @@
+
@@ -33,7 +34,7 @@
-
+
@@ -88,9 +89,12 @@
+
+
+